├── 优先队列 ├── 堆.cpp └── stdafx.h ├── 排列组合 ├── 排列.cpp └── 洗牌问题.cpp ├── 排序 ├── 希尔排序.cpp ├── 归并排序.cpp ├── 快速排序.cpp ├── 插入排序.cpp ├── imgs │ ├── qsort1.jpg │ └── qsort2.jpg ├── 单链表的直接插入排序.cpp ├── README.md ├── 桶式排序.cpp ├── 冒泡排序.cpp ├── 堆排序.cpp └── 快速选择.py ├── pics └── logo.jpg ├── 单链表 ├── 表达式求值.cpp ├── 后缀表达式求值.cpp ├── 多项式简单操作.cpp └── 链表基本操作.cpp ├── 栈 ├── 用数组实现的栈.cpp └── 一个数组两个栈.cpp ├── 算法设计 ├── 排列组合.cpp └── 输出集合的子集.cpp ├── 图 ├── 图的遍历 │ ├── stdafx.h │ ├── 图的遍历.cpp │ ├── 栈操作.cpp │ └── 队列操作.cpp └── 优化拓扑排序.c ├── 队列 ├── 二叉树层次遍历.cpp └── 队列基本操作 │ ├── 队列.cpp │ └── stdafx.h ├── 哈希表 ├── imgs │ ├── hash1.jpg │ ├── hash2.jpg │ └── hash3.jpg ├── 分离链接法 │ ├── stdafx.h │ └── HashTable.cpp ├── 开放地址法(平方探测) │ ├── stdafx.h │ └── HashTable.cpp └── hash.md ├── 二叉树 ├── 二叉树非递归遍历 │ ├── stdafx.h │ └── 二叉树非递归遍历.cpp ├── 二叉平衡树 │ └── 二叉平衡树基本操作.cpp ├── 二叉排序树 │ └── 二叉排序树基本操作.cpp └── 哈夫曼树 │ └── huffman.py ├── 不相交集ADT ├── imgs │ ├── disjset1.jpg │ └── disjset2.jpg ├── DisjSet.md └── DisjSet.java ├── 查找 └── 二分查找.py └── README.md /优先队列/堆.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/优先队列/堆.cpp -------------------------------------------------------------------------------- /排列组合/排列.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排列组合/排列.cpp -------------------------------------------------------------------------------- /排序/希尔排序.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排序/希尔排序.cpp -------------------------------------------------------------------------------- /排序/归并排序.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排序/归并排序.cpp -------------------------------------------------------------------------------- /排序/快速排序.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排序/快速排序.cpp -------------------------------------------------------------------------------- /排序/插入排序.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排序/插入排序.cpp -------------------------------------------------------------------------------- /pics/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/pics/logo.jpg -------------------------------------------------------------------------------- /优先队列/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/优先队列/stdafx.h -------------------------------------------------------------------------------- /单链表/表达式求值.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/单链表/表达式求值.cpp -------------------------------------------------------------------------------- /排列组合/洗牌问题.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排列组合/洗牌问题.cpp -------------------------------------------------------------------------------- /栈/用数组实现的栈.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/栈/用数组实现的栈.cpp -------------------------------------------------------------------------------- /算法设计/排列组合.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/算法设计/排列组合.cpp -------------------------------------------------------------------------------- /单链表/后缀表达式求值.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/单链表/后缀表达式求值.cpp -------------------------------------------------------------------------------- /单链表/多项式简单操作.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/单链表/多项式简单操作.cpp -------------------------------------------------------------------------------- /单链表/链表基本操作.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/单链表/链表基本操作.cpp -------------------------------------------------------------------------------- /图/图的遍历/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/图/图的遍历/stdafx.h -------------------------------------------------------------------------------- /图/图的遍历/图的遍历.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/图/图的遍历/图的遍历.cpp -------------------------------------------------------------------------------- /图/图的遍历/栈操作.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/图/图的遍历/栈操作.cpp -------------------------------------------------------------------------------- /图/图的遍历/队列操作.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/图/图的遍历/队列操作.cpp -------------------------------------------------------------------------------- /队列/二叉树层次遍历.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/队列/二叉树层次遍历.cpp -------------------------------------------------------------------------------- /队列/队列基本操作/队列.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/队列/队列基本操作/队列.cpp -------------------------------------------------------------------------------- /哈希表/imgs/hash1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/哈希表/imgs/hash1.jpg -------------------------------------------------------------------------------- /哈希表/imgs/hash2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/哈希表/imgs/hash2.jpg -------------------------------------------------------------------------------- /哈希表/imgs/hash3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/哈希表/imgs/hash3.jpg -------------------------------------------------------------------------------- /哈希表/分离链接法/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/哈希表/分离链接法/stdafx.h -------------------------------------------------------------------------------- /排序/imgs/qsort1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排序/imgs/qsort1.jpg -------------------------------------------------------------------------------- /排序/imgs/qsort2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排序/imgs/qsort2.jpg -------------------------------------------------------------------------------- /排序/单链表的直接插入排序.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/排序/单链表的直接插入排序.cpp -------------------------------------------------------------------------------- /队列/队列基本操作/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/队列/队列基本操作/stdafx.h -------------------------------------------------------------------------------- /二叉树/二叉树非递归遍历/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/二叉树/二叉树非递归遍历/stdafx.h -------------------------------------------------------------------------------- /二叉树/二叉平衡树/二叉平衡树基本操作.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/二叉树/二叉平衡树/二叉平衡树基本操作.cpp -------------------------------------------------------------------------------- /二叉树/二叉排序树/二叉排序树基本操作.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/二叉树/二叉排序树/二叉排序树基本操作.cpp -------------------------------------------------------------------------------- /哈希表/分离链接法/HashTable.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/哈希表/分离链接法/HashTable.cpp -------------------------------------------------------------------------------- /不相交集ADT/imgs/disjset1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/不相交集ADT/imgs/disjset1.jpg -------------------------------------------------------------------------------- /不相交集ADT/imgs/disjset2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/不相交集ADT/imgs/disjset2.jpg -------------------------------------------------------------------------------- /二叉树/二叉树非递归遍历/二叉树非递归遍历.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/二叉树/二叉树非递归遍历/二叉树非递归遍历.cpp -------------------------------------------------------------------------------- /哈希表/开放地址法(平方探测)/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/哈希表/开放地址法(平方探测)/stdafx.h -------------------------------------------------------------------------------- /哈希表/开放地址法(平方探测)/HashTable.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lucky4/Data-Structures-and-Algorithm-Analysis-in-C/HEAD/哈希表/开放地址法(平方探测)/HashTable.cpp -------------------------------------------------------------------------------- /排序/README.md: -------------------------------------------------------------------------------- 1 | ## 快速排序时间复杂度分析 2 |

3 |

-------------------------------------------------------------------------------- /不相交集ADT/DisjSet.md: -------------------------------------------------------------------------------- 1 | ## 不相交集ADT 2 | 3 | #### 等价关系 4 | 等价关系满足下列三个性质的关系: 5 | * 自反性 6 | * 对称性 7 | * 传递性 8 |
9 | 10 | #### 动态等价性问题 11 | 给定一个等价关系“~”,一个问题是对任意a和b,确定a~b。 12 | 13 | 一个等价类是全集S的一个子集,只需验证a和b是否都在一个等价类中。 14 | 15 | 输入数据是N个集合的类,每个集合有一个不同元素,使得这些集合不相交。 16 | 17 | 有两种运算: 18 | * Find:返回给定元素的集合(即等价类的名字)。复杂度O(N) 19 | * Union:把含有a和b两个等价类合并成一个新的等价类。 20 | 21 |

22 |

23 | -------------------------------------------------------------------------------- /排序/桶式排序.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 复杂度: 3 | * O(M+N) 4 | * 5 | * 思想: 6 | * 输入数据A1, A2, ... , An必须由小于M的整数组成,使用一个大小为M的Count数组,它被全部初始化为0,当读入Ai时Count[Ai]增1,最后扫描数组Count打印排序后的表。 7 | */ 8 | # define M 100 9 | void BucketSort(int A[], int N) 10 | { 11 | int i, j; 12 | int Count[M]; 13 | for(j = 0; j < N; j++) 14 | { 15 | Count[j] += 1; 16 | } 17 | for(i = 1; i < N; i ++)//没有对0排序 18 | for(j = 0; j < A[i]; j ++) 19 | if (i > 0) 20 | printf("%d ", i); 21 | } 22 | } -------------------------------------------------------------------------------- /排序/冒泡排序.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 复杂度: 3 | * O(N2) 4 | * 5 | * 优化: 6 | * 使用flag标记上次是否发生交换,未发生说明后面已经是有序的了,不需要再将程序进行下去了。 7 | */ 8 | void BubbleSort(int A[], int N) 9 | { 10 | int tmp, flag = 1; 11 | 12 | for (int i = N; i > 0 && flag; i--) { 13 | flag = 0; 14 | for (int j = 0; j < N - i - 1; j++) { 15 | if (A[j] > A[j + 1]) { 16 | tmp = A[j]; 17 | A[j] = A[j + 1]; 18 | A[j + 1] = tmp; 19 | 20 | flag = 1; 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /哈希表/hash.md: -------------------------------------------------------------------------------- 1 | ## 散列表 2 | 散列表是包含有关键字的具有固定大小的数组。 3 | 4 | 散列表的实现叫做散列,散列是一种用于常数平均时间插入、删除和查找的技术。但是,那些需要元素间任何排序信息的操作将不会得到有效的支持。 5 |
6 | 7 | #### 散列函数 8 | 每个关键字被映射到从0到TableSize-1这个范围中的某个数,并且被放到适当的单元中,这个映射较散列函数。 9 | 10 | 散列函数实现的几种方式: 11 | * 求模取余 12 | * 字符串ASCII码值相加 13 | * 多项式函数 14 |
15 | 16 | #### 解决冲突的方法 17 | 1. 分离链接法 18 |

19 | 20 | 分离链接散列算法的缺点是需要指针,由于给新单元分配地址需要时间,因此这就导致算法的速度有些慢,同时算法还需要对另一种数据结构的实现。 21 |
22 | 23 | #### 开发地址法 24 | 开放地址法的种类: 25 | * 线性探测,容易产生一次聚集。 26 |

27 | 28 | * 平方探测,容易产生二次聚集。 29 |

30 | 31 | * 在散列,需要额外的操作O(N)。 32 |
33 | 34 | #### 哈希与二叉树的对比 35 | 查找的平均时间: 36 | 37 | 哈希:O(1) 38 | 二叉树:O(NlogN) 39 | 40 | 查找的方式: 41 | 42 | 哈希:单纯的查找某个元素。 43 | 二叉树:提供查找最小元,查找某一范围内的所有项等例程。 44 |
45 | 46 | #### 应用 47 | * Python字典类型的底层支持。 48 | * 编译器的符号表,跟踪源代码中s声明的变量。 -------------------------------------------------------------------------------- /排序/堆排序.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 堆排序 3 | 4 | 思路:堆排序分为构建堆、删除最值、调整堆即下滤操作。 5 | 6 | 方法:使用数组代替ADT(抽象数据类型)的方式实现初始堆数组下标从零开始。 7 | 8 | 总结:时间复杂度为O(N*logN)。 9 | */ 10 | 11 | //下滤操作 12 | void PercDown(ElementType A[], int i, int N) //i为父节点下标 13 | { 14 | int replChild; 15 | ElementType tmp; 16 | 17 | for (tmp = A[i]; 2*i+1 < N; i = replChild) //i = replChild是在语句体执行之后执行的 18 | { 19 | replChild = 2*i; 20 | if (replChild != N - 1 && A[replChild + 1] < A[replChild]) 21 | replChild++; 22 | 23 | if (tmp > A[replChild]) 24 | A[i] = A[replChild]; 25 | else 26 | break; 27 | } 28 | A[i] = tmp; 29 | } 30 | 31 | //堆排序 32 | void HeapSort(ElementType A[], int N) 33 | { 34 | int i, temp;; 35 | 36 | //根据数组构建堆 37 | for (i = N / 2; i >= 0; i--) 38 | PercDown(A, i, N); 39 | 40 | for (i = N - 1; i > 0; i--) 41 | { //交换根与最后的节点数据 42 | temp = A[0]; 43 | A[0] = A[i]; 44 | A[i] = temp; 45 | 46 | PercDown(A, 0, i); 47 | } 48 | } 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | int main() 57 | { 58 | int i; 59 | int a[10] = { 2, 4, 67, 12, 43, 78, 5, 3, 8, 65 }; 60 | 61 | HeapSort(a, 10); 62 | 63 | for (i = 0; i < 10; i++) 64 | printf("%d,", a[i]); 65 | 66 | return 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /查找/二分查找.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | # 二分查找 5 | def binary_search(A, target): 6 | l = 0 7 | h = len(A) - 1 8 | m = -1 9 | 10 | while l <= h: 11 | if A[m] == target: 12 | return m 13 | 14 | if A[m] < target: 15 | l = m + 1 16 | continue 17 | 18 | if A[m] > target: 19 | h = m - 1 20 | continue 21 | 22 | return -1 23 | 24 | 25 | # 查找第一次出现的位置,还可用于查找查找第一个等于或者大于Key的元素。 26 | def search_first_equal(A, target): 27 | l = 0 28 | h = len(A) - 1 29 | m = -1 30 | while l < h: 31 | m = (l + h) / 2 32 | if A[m] >= target: 33 | h = m 34 | else: 35 | l = m + 1 36 | return l 37 | 38 | 39 | # 查找最后一次出现的位置,还可用于查找最后一个等于或者小于key的元素。 40 | def search_last_equal(A, target): 41 | l = 0 42 | h = len(A) - 1 43 | m = -1 44 | while l < h: 45 | m = (l + h) / 2 46 | if A[m] > target: 47 | h = m - 1 48 | else: 49 | l = m + 1 50 | return h 51 | 52 | 53 | if __name__ == '__main__': 54 | A = [1, 2, 2, 2, 3, 5, 5, 5, 5, 5] 55 | print search_first_equal(A, 5) 56 | print search_last_equal(A, 5) -------------------------------------------------------------------------------- /排序/快速选择.py: -------------------------------------------------------------------------------- 1 | # 算法步骤: 2 | # 前3步与快速排序一样,多一个第四步, 3 | # 如果k <= S1,那么第k小元素必然在S1内。 4 | # 如果k = 1 + |S1|,那么枢纽元就是第k小元素。 5 | # 否则第k小元素在S2中。 6 | # 7 | # 时间复杂度: 8 | # 快速选择节省了一次递归调用,最坏为O(N2),平均为O(N)。 9 | 10 | 11 | def QSort(A, k, Left, Right): 12 | if Left < Right: 13 | pivot = Median(A, Left, Right) 14 | i = Left 15 | j = Right - 1 16 | 17 | while True: 18 | while A[i] < pivot: 19 | i += 1 20 | 21 | while A[j] > pivot: 22 | j -= 1 23 | 24 | if i < j: 25 | tmp = A[i] 26 | A[i] = A[j] 27 | A[j] = tmp 28 | else: 29 | break 30 | 31 | tmp = A[i] 32 | A[i] = A[Right] 33 | A[Right] = tmp 34 | 35 | if k < i: 36 | QSort(A, k, Left, i-1) 37 | else: 38 | QSort(A, k, i+1, Right) 39 | 40 | 41 | def Median(A, Left, Right): 42 | Center = (Left + Right) / 2 43 | 44 | if A[Left] > A[Center]: 45 | tmp = A[Left] 46 | A[Left] = A[Center] 47 | A[Center] = tmp 48 | 49 | if A[Left] > A[Right]: 50 | tmp = A[Left] 51 | A[Left] = A[Right] 52 | A[Right] = tmp 53 | 54 | if A[Center] > A[Right]: 55 | tmp = A[Center] 56 | A[Center] = A[Right] 57 | A[Right] = tmp 58 | 59 | tmp = A[Center] 60 | A[Center] = A[Right] 61 | A[Right] = tmp 62 | 63 | return A[Right] 64 | 65 | 66 | if __name__ == '__main__': 67 | k = 2 68 | A = [3, 1, 6, 10, 2, 6] 69 | 70 | QSort(A, k, 0, 5) 71 | print A[k-1] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 | 12 | # 不经常看,但那是一段难忘的经历! 13 | 14 |
15 |
16 | 17 | ## 内容概览 18 | 19 | | :grapes: | :melon: | :watermelon: | :tangerine: | :lemon: | :banana: | :pineapple: | :apple: | :strawberry: | :peach: | 20 | | :--------: | :---------: | :---------: | :---------: | :---------: | :---------: | :-------: | :-------:| :------:| :------:| 21 | | 链表 | 栈 | 队列 | 二叉树 | 优先队列 | 排序 | 不相交集ADT | 哈希表 | 查找 | 图 | 22 |
23 | 24 | ## 目录 25 | 26 | * 链表 27 | * [单链表基本操作](./单链表/链表基本操作.cpp) 28 | 29 | * 栈 30 | * [栈的数组实现](./栈/用数组实现的栈.cpp) 31 | * [一个数组实现两个栈](./栈/一个数组两个栈) 32 | 33 | * 队列 34 | * [队列基本操作](./队列/队列基本操作/队列.cpp) 35 | * [二叉树层次遍历](./队列/二叉树层次遍历.cpp) 36 | 37 | * 二叉树 38 | * [二叉树的非递归遍历](./二叉树/二叉树非递归遍历/二叉树非递归遍历.cpp) 39 | * [哈夫曼树](./二叉树/哈夫曼树/huffman.py) 40 | 41 | * 优先队列 42 | * [优先队列的基本操作](./优先队列/堆.cpp) (构建堆、上滤、下滤) 43 | 44 | * 排序 45 | * [冒泡排序](./排序/冒泡排序.cpp) 46 | * [插入排序](./排序/插入排序.cpp) 47 | * [希尔排序](./排序/希尔排序.cpp) 48 | * [归并排序](./排序/归并排序.cpp) 49 | * [快速排序](./排序/快速排序.cpp) 50 | * [桶式排序](./排序/桶式排序.cpp) 51 | * [堆排序](./排序/堆排序.cpp) 52 | 53 | * 不相交集ADT 54 | * [不相交集ADT定义](./不相交集ADT/DisjSet.md) 55 | 56 | * 哈希表 57 | * [分离链接法](./哈希表/分离链接法/HashTable.cpp) 58 | * [开放地址法](./哈希表/开放地址法(平方探测)/HashTable.cpp) 59 | 60 | * 查找 61 | * [二叉平衡树](./二叉树/二叉平衡树/二叉平衡树基本操作.cpp) 62 | * [二分查找](./查找/二分查找.py) 63 | 64 | * 图 65 | * [图的遍历](./图/图的遍历/图的遍历.cpp) 66 |
67 | 68 | ## 表情 69 | [emoji](https://emojipedia.org/) 70 |
71 |
72 | 73 | ## logo 74 | [logomakr](https://logomakr.com/) 75 | -------------------------------------------------------------------------------- /算法设计/输出集合的子集.cpp: -------------------------------------------------------------------------------- 1 | // test.cpp : 定义控制台应用程序的入口点。 2 | // 3 | 4 | #include "stdafx.h" 5 | 6 | /* 7 | 网上的思路,利用将每个集合子集与二进制位相联系 8 | http://www.geeksforgeeks.org/power-set/ 9 | */ 10 | void printPowerSet(char *set, int set_size) 11 | { 12 | /*set_size of power set of a set with set_size 13 | n is (2**n -1)*/ 14 | int pow_set_size = pow(2, set_size); 15 | int counter, j; 16 | 17 | /*Run from counter 000..0 to 111..1*/ 18 | for (counter = 0; counter < pow_set_size; counter++) 19 | { 20 | for (j = 0; j < set_size; j++) 21 | { 22 | /* Check if jth bit in the counter is set 23 | If set then pront jth element from set */ 24 | if (counter & (1 << j)) 25 | printf("%c", set[j]); 26 | } 27 | printf("\n"); 28 | } 29 | } 30 | 31 | /* 32 | 思路链接:http://www.linuxidc.com/Linux/2014-02/96222.htm 33 | */ 34 | int SIZE = 5; 35 | void printPowerSet2(char *set, int set_size) 36 | { 37 | //递归出口,当当前集合不能够在分解为下一个子集的时候输出所有集合元素 38 | if (set_size == 0) 39 | { 40 | printf("{"); 41 | for (int i = 0; i < SIZE; i++) 42 | if (set[i] != ' ') 43 | printf("%c", set[i]); 44 | printf("}"); 45 | printf("\n"); 46 | } 47 | else 48 | { 49 | //直接递归,递归生成当前集合的所有下一个状态 50 | printPowerSet2(set, set_size - 1); 51 | 52 | //动态生成子集合存储空间,通过使用空白字符替换每个位置的方式生成当前元素个数的每个子集 53 | //递归的在生成子集中继续查找子集 54 | if (set_size > 0) 55 | { 56 | char *sub_set = (char *)malloc(sizeof(char)*set_size); 57 | strcpy(sub_set, set); 58 | sub_set[set_size - 1] = ' '; 59 | printPowerSet2(sub_set, set_size - 1); 60 | } 61 | } 62 | } 63 | 64 | 65 | 66 | 67 | 68 | 69 | int main() 70 | { 71 | char set[] = { 'a','b','c' }; 72 | printPowerSet(set, 3); 73 | char *set2 = "abcd"; 74 | printPowerSet2(set2, 4); 75 | 76 | 77 | getchar(); 78 | return 0; 79 | } -------------------------------------------------------------------------------- /不相交集ADT/DisjSet.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.util.Iterator; 3 | import java.util.Map; 4 | 5 | 6 | public class ADT { 7 | public Map S; 8 | public int[] relations; 9 | 10 | public ADT(Map S) { 11 | this.S = S; 12 | this.relations = new int[10]; 13 | 14 | Iterator entries = this.S.entrySet().iterator(); 15 | 16 | while (entries.hasNext()) { 17 | Map.Entry entry = (Map.Entry) entries.next(); 18 | Integer key = (Integer) entry.getKey(); 19 | Integer value = (Integer) entry.getValue(); 20 | this.UnionEnhace(key, value); 21 | } 22 | } 23 | 24 | public void Initialize() { 25 | for (int i = 0; i < this.relations.length; i++) { 26 | this.relations[i] = 0; 27 | } 28 | } 29 | 30 | public void Union(int elem1, int elem2) { 31 | this.relations[elem1] = elem2; 32 | } 33 | 34 | public void UnionEnhace(int elem1, int elem2) { 35 | if (this.relations[elem1] > this.relations[elem2]) { 36 | this.relations[elem1] = elem2; 37 | } else { 38 | if (this.relations[elem1] == this.relations[elem2]) { 39 | this.relations[elem2] -= 1; 40 | } 41 | this.relations[elem1] = elem2; 42 | } 43 | } 44 | 45 | public int Find(int elem) { 46 | if (this.relations[elem] <= 0) { 47 | return elem; 48 | } else { 49 | return Find(this.relations[elem]); 50 | } 51 | } 52 | 53 | public static void main(String args[]) { 54 | Map S = new HashMap(); 55 | S.put(6, 5); 56 | S.put(8, 7); 57 | S.put(7, 5); 58 | S.put(4, 5); 59 | 60 | ADT obj = new ADT(S); 61 | 62 | System.out.println(obj.Find(4)); 63 | System.out.println(obj.Find(5)); 64 | System.out.println(obj.Find(6)); 65 | System.out.println(obj.Find(7)); 66 | System.out.println(obj.Find(8)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /二叉树/哈夫曼树/huffman.py: -------------------------------------------------------------------------------- 1 | # Huffman编码是贪婪算法的应用,称为文件压缩,构造trie树后,向左是0,向右是1。 2 | # 这些字符代码的长度是否重要并不要紧,只要没有字符代码是别的字符代码的前缀即可,又叫做前缀码。 3 | # 哈夫曼树根据集合中权值最小的两颗树构建一个新树。 4 | 5 | class TreeNode(object): 6 | def __init__(self, weight, chr=''): 7 | self.weight = weight 8 | self.chr = chr 9 | self.left = None 10 | self.right = None 11 | 12 | 13 | class Huffman(object): 14 | def __init__(self, encode_str): 15 | self.encode_str = encode_str 16 | self.chr_times_dict = {} 17 | 18 | def make_tree(self): 19 | # Count chr times. 20 | for i in self.encode_str: 21 | if i not in self.chr_times_dict: 22 | self.chr_times_dict[i] = 1 23 | else: 24 | self.chr_times_dict[i] += 1 25 | 26 | # Make chrs to TreeNode list. 27 | son_node_list = [] 28 | for j in self.chr_times_dict: 29 | node = TreeNode(self.chr_times_dict[j], j) 30 | son_node_list.append(node) 31 | 32 | # Compare function. 33 | cmp = lambda x, y : 1 if x.weight > y.weight else -1 34 | 35 | # Make the huffman tree. 36 | while len(son_node_list) > 1: 37 | son_node_list.sort(cmp=cmp) 38 | son1 = son_node_list.pop(0) 39 | son2 = son_node_list.pop(0) 40 | son3 = TreeNode(son1.weight + son2.weight) 41 | son3.left = son1 42 | son3.right = son2 43 | son_node_list.append(son3) 44 | 45 | return son_node_list[0] # root 46 | 47 | def get_encode_res(self, root): 48 | res = {} 49 | for i in self.encode_str: 50 | l = [] 51 | 52 | def get_encode_str(i, root, l): 53 | found = False 54 | if root.chr == i: 55 | return True 56 | 57 | if not found and root.left != None: 58 | l.append('0') 59 | found = get_encode_str(i, root.left, l) 60 | 61 | if not found and root.right != None: 62 | l.append('1') 63 | found = get_encode_str(i, root.right, l) 64 | 65 | if not found: 66 | l.pop() 67 | return found 68 | 69 | get_encode_str(i, root, l) 70 | l.reverse() 71 | res[i] = ''.join(l) 72 | return res 73 | 74 | 75 | if __name__ == '__main__': 76 | try: 77 | while True: 78 | encode_str = raw_input().strip() 79 | if not encode_str: 80 | break 81 | 82 | h = Huffman(encode_str) 83 | tree = h.make_tree() 84 | encode = h.get_encode_res(tree) 85 | 86 | res = 0 87 | for i in encode: 88 | res += len(encode[i]) * h.chr_times_dict[i] 89 | print res 90 | except EOFError: 91 | pass 92 | -------------------------------------------------------------------------------- /栈/一个数组两个栈.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | 用一个数组实现两个栈 3 | **********************************************************************/ 4 | #include "stdafx.h" 5 | #include 6 | #include 7 | 8 | 9 | typedef struct StackRecord 10 | { 11 | int capcity; 12 | int topOfStack1; //自底向上的栈顶指针 13 | int topOfStack2; //自顶向下的栈顶指针 14 | int *array; 15 | }*Stack; //栈指针变量 16 | 17 | 18 | 19 | /* 20 | 释放栈例程 21 | */ 22 | void dispose_stack(Stack S) 23 | { 24 | if (NULL != S) 25 | { 26 | free(S->array); 27 | free(S); 28 | } 29 | } 30 | 31 | /* 32 | 判断栈bottom栈是否为空例程 33 | */ 34 | int is_bottom_empty(Stack S) 35 | { 36 | return S->topOfStack1 == -1; 37 | } 38 | 39 | /* 40 | 判断栈top栈是否为空例程 41 | */ 42 | int is_top_empty(Stack S) 43 | { 44 | return S->topOfStack2 == S->capcity; 45 | } 46 | 47 | /* 48 | 创建bottom空栈历程 49 | */ 50 | void make_bottom_empty(Stack S) 51 | { 52 | S->topOfStack1 = -1; 53 | } 54 | 55 | /* 56 | 创建top空栈历程 57 | */ 58 | void make_top_empty(Stack S) 59 | { 60 | S->topOfStack2 = S->capcity; 61 | } 62 | 63 | /* 64 | 判断栈满的历程 65 | */ 66 | int is_full(Stack S) 67 | { 68 | return (S->topOfStack1 + 1) == S->topOfStack2; 69 | } 70 | 71 | /* 72 | 使用一个数组实现两个栈 73 | 只需设置两个栈顶指针 74 | */ 75 | Stack create_statck(int maxElements) 76 | { 77 | Stack s; 78 | 79 | //申请栈空间 80 | s = (Stack)malloc(sizeof(struct StackRecord)); 81 | if (NULL == s) 82 | { 83 | printf("Out of space.\n"); 84 | exit(-1); 85 | } 86 | 87 | //申请栈数组空间,栈初始化 88 | s->array = (int*)malloc(sizeof(int) * maxElements); 89 | if (NULL == s->array) 90 | { 91 | printf("Out of space.\n"); 92 | exit(-1); 93 | } 94 | s->capcity = maxElements; 95 | make_bottom_empty(s); 96 | make_top_empty(s); 97 | 98 | return s; 99 | } 100 | 101 | /* 102 | bottom栈进栈例程 103 | */ 104 | void push_bottom(int x, Stack S) 105 | { 106 | if (is_full(S)) 107 | printf("Full stack.\n"); 108 | else 109 | S->array[++S->topOfStack1] = x; 110 | } 111 | 112 | /* 113 | top栈进栈例程 114 | */ 115 | void push_top(int x, Stack S) 116 | { 117 | if (is_full(S)) 118 | printf("Full stack.\n"); 119 | else 120 | S->array[--S->topOfStack2] = x; 121 | } 122 | 123 | 124 | /* 125 | bottom栈返回栈顶例程 126 | */ 127 | int top_bottom(Stack S) 128 | { 129 | if (!is_bottom_empty(S)) 130 | return S->array[S->topOfStack1]; 131 | printf("Empty stack.\n"); 132 | 133 | return 0; 134 | } 135 | 136 | /* 137 | top栈返回栈顶例程 138 | */ 139 | int top_top(Stack S) 140 | { 141 | if (!is_top_empty(S)) 142 | return S->array[S->topOfStack2]; 143 | printf("Empty stack.\n"); 144 | 145 | return 0; 146 | } 147 | 148 | 149 | /* 150 | bottom栈出栈例程 151 | */ 152 | void pop_bottom(Stack S) 153 | { 154 | if (is_bottom_empty(S)) 155 | printf("Empty stack.\n"); 156 | else 157 | S->topOfStack1--; 158 | } 159 | 160 | /* 161 | top栈出栈例程 162 | */ 163 | void pop_top(Stack S) 164 | { 165 | if (is_top_empty(S)) 166 | printf("Empty stack.\n"); 167 | else 168 | S->topOfStack2++; 169 | } 170 | 171 | /* 172 | bottom栈给出元素并弹栈例程 173 | */ 174 | int b_top_and_pop(Stack S) 175 | { 176 | if (!is_bottom_empty(S)) 177 | return S->array[S->topOfStack1--]; 178 | printf("Empty stack.\n"); 179 | 180 | return 0; 181 | } 182 | 183 | /* 184 | top栈给出元素并弹栈例程 185 | */ 186 | int t_top_and_pop(Stack S) 187 | { 188 | if (!is_top_empty(S)) 189 | return S->array[S->topOfStack1++]; 190 | printf("Empty stack.\n"); 191 | 192 | return 0; 193 | } 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | int main() 202 | { 203 | int capcity; 204 | int choose = 0; 205 | int value; 206 | Stack S; 207 | 208 | //初始化栈 209 | printf("请输入栈容量:\n"); 210 | scanf("%d", &capcity); 211 | S = create_statck(capcity); 212 | 213 | while (1) 214 | { 215 | printf("请输入操作:\n"); 216 | printf("1.bottom进栈\n"); 217 | printf("2.bottom出栈\n"); 218 | printf("3.top进栈\n"); 219 | printf("4.top出栈\n"); 220 | printf("q.退出\n"); 221 | switch (scanf("%d", &choose)) 222 | { 223 | case 1: 224 | printf("请输入bottom进栈元素:\n"); 225 | scanf("%d", &value); 226 | push_bottom(value, S); 227 | break; 228 | 229 | case 2: 230 | printf("请输入bottom出栈元素:\n"); 231 | pop_bottom(S); 232 | break; 233 | 234 | case 3: 235 | printf("请输入top进栈元素:\n"); 236 | scanf("%d", &value); 237 | push_top(value, S); 238 | break; 239 | 240 | case 4: 241 | printf("请输入top出栈元素:\n"); 242 | pop_top(S); 243 | break; 244 | 245 | default: 246 | int i; 247 | for (i = 0; i < S->capcity; i++) 248 | { 249 | printf("栈中元素为:%d\t", S->array[i]); 250 | } 251 | return 0; 252 | } 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /图/优化拓扑排序.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_VERTEX_NUM 7 // 图的最大节点数 5 | 6 | int TopNum[7]; // 入度数组 7 | 8 | typedef struct EdgeNode // 邻接顶点 9 | { 10 | int adjvertex; 11 | struct EdgeNode *next; 12 | }EdgeNode; 13 | 14 | typedef struct VertexNode // 顶点 15 | { 16 | int vertex; 17 | EdgeNode *firstEdge; 18 | }VertexNode, HeadCellArray[MAX_VERTEX_NUM]; 19 | 20 | typedef struct Graph // 图结构 21 | { 22 | int numVertex, numEdge; 23 | HeadCellArray headCellArray; 24 | }Graph; 25 | 26 | typedef struct QueueRecord // 队列结构(数组) 27 | { 28 | int capacity; 29 | int rear; 30 | int front; 31 | int size; 32 | int *array; 33 | }Queue, *QueueLink; 34 | 35 | int IsEmpty(Queue Q) // 判断队列是否为空 36 | { 37 | return Q.size==0; 38 | } 39 | 40 | int IsFull(Queue Q) 41 | { 42 | return Q.size==Q.capacity; // 判断队列是否已满 43 | } 44 | 45 | void MakeEmpty(Queue Q) // 清空队列 46 | { 47 | Q.size=0; 48 | Q.rear=0; 49 | Q.front=1; 50 | } 51 | 52 | Queue CreateQueue(int numVertex) // 创建队列 53 | { 54 | Queue Q; 55 | 56 | Q=*(Queue*)malloc(sizeof(struct QueueRecord)); 57 | Q.capacity=numVertex; 58 | Q.array=(int*)malloc(sizeof(int)*numVertex); 59 | MakeEmpty(Q); 60 | 61 | return Q; 62 | } 63 | 64 | void Enqueue(int x, Queue Q) // 入队 65 | { 66 | if(IsFull(Q)) 67 | { 68 | printf("队列已满\n"); 69 | exit(1); 70 | } 71 | 72 | Q.size++; 73 | // printf("size=%d", Q.size); 74 | 75 | if(++Q.rear==Q.capacity) 76 | Q.rear=0; 77 | 78 | Q.array[Q.rear]=x; 79 | printf("Q.array=%d\n", Q.array[Q.rear]); 80 | 81 | printf("入队成功\n"); 82 | 83 | return; 84 | } 85 | 86 | int FrontAndDequeue(Queue Q) // 出队并且返回 87 | { 88 | int result; 89 | 90 | if(IsEmpty(Q)) 91 | { 92 | printf("队列已空\n"); 93 | exit(1); 94 | } 95 | 96 | result=Q.array[Q.front]; 97 | Q.array[Q.front]=100; // 已经出队的元素标志为100 98 | Q.front++; 99 | if(Q.front==Q.capacity) 100 | Q.front=0; 101 | Q.size--; 102 | 103 | return result; 104 | } 105 | 106 | void DisposeQueue(Queue Q) // 销毁队列 107 | { 108 | QueueLink p=&Q; 109 | 110 | if(p != NULL) 111 | { 112 | free(p->array); 113 | free(p); 114 | } 115 | 116 | return; 117 | } 118 | 119 | int * MakeIndegree(Graph G) 120 | { 121 | int i; 122 | int *indegree; 123 | EdgeNode *p; 124 | 125 | indegree=(int*)malloc(sizeof(int)*G.numVertex); 126 | 127 | for (i=0;iadjvertex])++; 133 | p = p->next; 134 | } 135 | } 136 | 137 | return indegree; 138 | } 139 | 140 | void Topsort(Graph G) 141 | { 142 | int i, v, w; 143 | int counter=0; 144 | int *indegree; 145 | Queue Q; 146 | EdgeNode *p; 147 | 148 | Q=CreateQueue(7); 149 | indegree=MakeIndegree(G); 150 | 151 | for(i=0;i<7;i++) 152 | { 153 | if(indegree[i]==0) 154 | { 155 | printf("Has a indegree zero\n"); 156 | Enqueue(i ,Q); 157 | } 158 | } 159 | 160 | while(IsEmpty(Q)!=1) 161 | { 162 | printf("开始循环"); 163 | v=FrontAndDequeue(Q); 164 | TopNum[v]=++counter; 165 | 166 | p=G.headCellArray[v].firstEdge; 167 | while(p) 168 | { 169 | w=p->adjvertex; 170 | indegree[w]=indegree[w]-1; 171 | 172 | printf("\n"); 173 | printf("w=%d", indegree[w]); 174 | printf("\n"); 175 | 176 | if(indegree[w]==0) 177 | Enqueue(w, Q); 178 | p=p->next; 179 | } 180 | } 181 | 182 | // if(counter != 7) 183 | // { 184 | // printf("counter=%d\n", counter); 185 | // printf("Graph has a cycle"); 186 | // exit(1); 187 | // } 188 | 189 | // DisposeQueue(Q); 190 | 191 | return; 192 | } 193 | 194 | Graph InitGraph() 195 | { 196 | Graph G; 197 | EdgeNode *p; 198 | int i, u, v; 199 | 200 | printf("请输入节点数和边数:\n"); 201 | scanf("%d%d", &G.numVertex, &G.numEdge); 202 | 203 | for (i=0;iv\n"); 213 | scanf("%d%d", &u, &v); 214 | 215 | p=(EdgeNode*)malloc(sizeof(EdgeNode)); 216 | p->adjvertex=v; 217 | p->next=G.headCellArray[u].firstEdge; 218 | G.headCellArray[u].firstEdge=p; 219 | } 220 | 221 | return G; 222 | } 223 | 224 | void PrintGraph(Graph G) 225 | { 226 | int i; 227 | EdgeNode *p; 228 | 229 | for(i=0;i%3d", p->adjvertex); 236 | p=p->next; 237 | } 238 | printf("\n"); 239 | } 240 | } 241 | 242 | void main() 243 | { 244 | int i, *p, temp; 245 | Graph G; 246 | 247 | G=InitGraph(); 248 | PrintGraph(G); 249 | 250 | /* 251 | p=MakeIndegree(G); 252 | for(i=0;i<7;i++) 253 | printf("%4d", p[i]); 254 | */ 255 | /* 256 | temp=FindNewVertexOfIndegreeZero(p, 7); 257 | printf("%d\n", temp); 258 | */ 259 | Topsort(G); 260 | for(i=0;i