Skip to content

Commit 25466fd

Browse files
committed
modify some README
1 parent 08cdb5b commit 25466fd

File tree

7 files changed

+137
-17
lines changed

7 files changed

+137
-17
lines changed

Graph/README.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
2+
3+
简单的概念:
4+
5+
* `无向边`: 若顶点vi到vj之间的边没有方向,则称这条边为无向边(Edge),用无序偶对(vi,vj)来表示。
6+
* `无向图`: 如果图中任意两个顶点之间的边都是无向边,则称该图为无向图(Undirected graphs)。
7+
* `有向边`:若从顶点vi到vj的边有方向,则称这条边为有向边,也称为弧(Arc)。用有序偶来表示,vi称为弧尾(Tail),vj称为弧头(Head)。
8+
* `有向图`: 如果图中任意两个顶点之间的边都是有向边,则称该图为有向图(Directed graphs)。
9+
10+
对于下面的无向图G1来说,G1=(V1,{E1}),其中顶点集合V1={A,B,C,D};边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}。对于下有向图G2来说,G2=(V2,{E2}),其中顶点集合V2={A,B,C,D};弧集合E2={<A,D>, <B,A>, (B,C), <C,A>}。
11+
12+
![][1]
13+
14+
15+
16+
# 更多阅读
17+
18+
[数据结构之图](https://www.zybuluo.com/guoxs/note/249812)
19+
20+
[1]: ../Image/Grapth_1.png
21+

HashTable/README.md

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,33 @@
1-
# 哈希表
21

2+
哈希表就是一种以键-值(key-indexed) 存储数据的结构,我们只要输入待查找的值即 key,即可查找到其对应的值。例如若关键字为k,则其值存放在 f(k) 的存储位置上,由此不需比较便可直接取得所查记录。称这个对应关系 f 为散列函数,按这个思想建立的表为哈希表(散列表)。
3+
4+
哈希查找第一步就是使用哈希函数将键映射成索引,这种映射函数就是`哈希(散列)函数`。哈希函数需要易于计算并且能够均匀分布所有键。一个好的哈希函数必须在理论上非常的快、稳定并且是可确定的。常用的哈希函数一般基于常见的运算,比如加法、乘法和移位运算,如以下方法:
5+
6+
1. 直接定址法:取关键字或关键字的某个线性函数值为散列地址。即或hash(k) = k 或者 hash(k) = a*k +b,其中a, b为常数(这种散列函数叫做自身函数)
7+
2. 数字分析法:假设关键字是以r为基的数,并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。
8+
3. 平方取中法:取关键字平方后的中间几位为哈希地址。通常在选定哈希函数时不一定能知道关键字的全部情况,取其中的哪几位也不一定合适,而一个数平方后的中间几位数和数的每一位都相关,由此使随机分布的关键字得到的哈希地址也是随机的。取的位数由表长决定。
9+
4. 折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。
10+
5. 除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。对p的选择很重要,一般取素数或m,若p选择不好,容易产生冲突。
11+
12+
DEK:Knuth在《编程的艺术 第三卷》的第六章排序和搜索中给出一个 Hash 函数如下:
13+
14+
long DEKHash(string str)
15+
{
 long hash = str.length();
16+
for(int i = 0; i < str.length(); i++)
17+
{
18+
hash = ((hash << 5) ^ (hash >> 27)) ^ str[i];
19+
}
20+
return hash;
21+
}

22+
对不同的关键字可能得到同一散列地址,即k1 != k2,而f(k1)=f(k2),这种现象称为冲突(Collision),避免hash碰撞碰撞的方法有:
23+
24+
* `拉链法`:将大小为M的数组的每一个元素指向一个条链表,链表中的每一个节点都存储散列值为该索引的键值对。
25+
* `开放定址法`:使用大小为M的数组来保存N个键值对,其中M>N,使用数组中的空位解决碰撞冲突。其中最简单的是线性探测法,当碰撞发生时即一个键的散列值被另外一个键占用时,直接检查散列表中的下一个位置即将索引值加1。
26+
* `再散列`:在上次散列计算发生冲突时,利用该次冲突的散列函数地址产生新的散列函数地址,直到冲突不再发生。
27+
* 建立一个公共溢出区。
28+
29+
为什么一般hashtable的桶数会取一个`素数`
30+
31+
首先来说假如关键字是随机分布的,那么无所谓一定要模质数。但在实际中往往关键字有某种规律,例如大量的等差数列,那么公差和模数不互质的时候发生碰撞的概率会变大,而用质数就可以很大程度上回避这个问题。
332

433

Heap/README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
#
1+
堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。在队列中,调度程序反复提取队列中第一个作业并运行,因为实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权。堆即为解决此类问题设计的一种数据结构。
22

3+
简单地说堆就是一种有序队列,普通的队列是先入先出,而二叉堆是:最小(最大)先出。
34

5+
# 更多内容
6+
7+
[数据结构系列——堆](http://vickyqi.com/2015/11/19/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E7%B3%BB%E5%88%97%E2%80%94%E2%80%94%E5%A0%86/)
48

Images/Graph_1.png

66.7 KB
Loading

Images/Tree_1.jpg

32.8 KB
Loading

Images/Tree_2.jpg

44.9 KB
Loading

Tree/README.md

+81-15
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,52 @@
1-
树是一种基本的、应用十分广泛的数据结构。
1+
树(Tree)是n(n≥0)个有限数据元素的集合。当n=0 时,称这棵树为空树。在一棵非空树T 中:
22

3-
# 树的起源
3+
1. 有一个特殊的数据元素称为树的根结点,根结点没有前驱结点。
4+
2. 除根结点之外的其余数据元素被分成m(m>0)个互不相交的集合T1,T2,…,Tm,其中每一个集合Ti(1≤i≤m)本身又是一棵树。树T1,T2,…,Tm 为这个根结点的子树(subtree)。
45

6+
树具有以下特点:
57

6-
# 树的实现
8+
1. 每个节点有零个或多个子节点。
9+
2. 每个非根节点只有一个父节点。
10+
3. 没有父节点的节点称为根节点。
711

12+
相关术语(结点、孩子结点等术语忽略):
813

9-
# 树的操作
14+
* 祖先结点: 从根到该结点的所经分支上的所有结点子孙结点:以某结点为根的子树中任一结点都称为该结点的子孙;
15+
* 结点层:规定树的根结点的层数为1,其余结点的层数等于它的双亲结点的层数加1;
16+
* 结点的``:结点子树的个数。
1017

11-
树的操作基本上都有递归和非递归两个版本。
18+
# 二叉树
19+
20+
二叉树是`每个节点最多有两个子树`的树结构。二叉树的每个结点至多只有二棵子树,二叉树的子树有左右之分,次序不能颠倒。
21+
22+
图论中二叉树的定义如下:二叉树是一个连通无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。
23+
24+
二叉树的一些不是那么明显的性质:
25+
26+
1. 对任何一棵二叉树T,度为2的结点数为m,则叶子结点数为:m+1。
27+
2. 给定N个节点,能构成h(N)种不同的二叉树,其中h(N)为`卡特兰数`的第N项。h(n)=C(2*n,n)/(n+1)。
28+
29+
几种常用的二叉树:
1230

31+
* 满二叉树:一棵深度为k,且有2^k - 1个节点的二叉树;
32+
* 完全二叉树:深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时。
33+
* 二叉堆:它一棵完全的二叉树,二叉堆一般分为两种:最大堆和最小堆。
1334

14-
## 遍历
35+
* 最大(小)堆中的最大(小)元素值出现在根结点(堆顶);
36+
* 堆中每个父节点的元素值都大(小)于等于其孩子结点(如果存在)。
37+
* 二叉排序树:是一棵空树,或者是具有下列性质的二叉树:
38+
39+
* 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
40+
* 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
41+
* 左、右子树也分别为二叉排序树;
42+
* 没有键值相等的节点。
43+
* 平衡二叉树(AVL树):它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
44+
45+
## 二叉树的遍历
1546

1647
深度优先:
1748

18-
前根遍历
49+
前根遍历
1950
中根遍历
2051

2152

@@ -43,23 +74,55 @@
4374
广度优先搜索
4475
116, 117
4576

46-
## 构建
77+
## 树与二叉树的转换
4778

79+
如果设定一定规则,就可用二叉树结构表示树,这样对树的操作实现就可以借助二叉树存储,利用二叉树上的操作来实现。
4880

49-
# 二叉树
81+
`树转换为二叉树`:将一棵树转换为二叉树的方法是:
82+
83+
* 树中所有相邻兄弟之间加一条连线。
84+
* 对树中的每个结点,只保留它与第一个孩子结点之间的连线,删去它与其它孩子结点之间的连线。
85+
* 以树的根结点为轴心,将整棵树顺时针转动一定的角度,使之结构层次分明。
86+
87+
![][1]
5088

51-
## 完美二叉树
89+
二叉树转换为树或森林的过程如下:
5290

53-
## 二叉搜索树
91+
* 若某结点是其双亲的左孩子,则把该结点的右孩子、右孩子的右孩子……都与该结点的双亲结点用线连起来;
92+
* 删去原二叉树中所有的双亲结点与右孩子结点的连线;
93+
* 整理由(1)、(2)两步所得到的树或森林,使之结构层次分明。
5494

55-
## 平衡二叉搜索树
95+
![][2]
5696

57-
构建二叉树:递归构建,找到当前根,然后递归求出左子树的根和右子树的根,并建立父子关系。如下面题目:
97+
[二叉树与森林的转换](http://www.nowcoder.com/questionTerminal/fe30dbe0dfb1498183e832dcba5ed908)
5898

59-
108
99+
# 二叉查找树
60100

61-
恢复二叉树
101+
二叉查找树,也称排序二叉树,是指一棵空树或者具备下列性质的二叉树(每个结点都不能有多于两个儿子的树):
62102

103+
1. 若任意结点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
104+
2. 若任意结点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
105+
3. 任意结点的左、右子树也分别为二叉查找树;
106+
4. **没有键值相等的结点**
107+
108+
从其性质可知,定义排序二叉树的一种自然的方式是递归的方法,其算法的核心为递归过程,由于它的平均深度为O(logN),所以递归的操作树,一般不必担心栈空间被耗尽。
109+
110+
更多内容参考 [BS_Tree](https://github.com/xuelangZF/CS_Offer/blob/master/DataStructure/BS_Tree.md)
111+
112+
# 自平衡二叉搜索树
113+
114+
AVL树是最早提出的自平衡二叉树,它是一种特殊的二叉搜索树,任一节点的左子树深度和右子树深度相差不超过1,所以它也被称为高度平衡树。
115+
116+
AVL树的特性让二叉搜索树的节点实现平衡(balance):节点相对均匀分布,而不是偏向某一侧。因此,AVL树种查找、插入和删除在平均和最坏情况下都是O(log n),增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
117+
118+
119+
更多内容参考 [AVL_Tree](https://github.com/xuelangZF/CS_Offer/blob/master/DataStructure/AVL_Tree.md)
120+
121+
# 红黑树
122+
123+
红黑树是一种自平衡二叉查找树。它的统计性能要好于平衡二叉树(AVL树),因此,红黑树在很多地方都有应用。在C++ STL中,很多部分(目前包括set, multiset, map, multimap)应用了红黑树的变体。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除等操作。
124+
125+
详细内容参见 [RB_Tree](https://github.com/xuelangZF/CS_Offer/blob/master/DataStructure/RB_Tree.md)
63126

64127
# 题目
65128

@@ -75,3 +138,6 @@
75138
[The Tree Data Model](http://infolab.stanford.edu/~ullman/focs/ch05.pdf)
76139

77140

141+
[1]: ../image/Tree_1.jpg
142+
[2]: ../image/Tree_2.jpg
143+

0 commit comments

Comments
 (0)