├── Notes ├── 01 基本概念.md ├── 02.1 线性结构.md ├── 02.2 堆栈.md ├── 02.3 队列.md ├── 3.1 树与树的表示.md ├── 4.二叉搜索树与平衡二叉树.md ├── 5 堆 哈夫曼树.md ├── 6 图.md ├── 7 最短路径.md ├── 8 排序.md ├── AVL Tree.c ├── Binary Search Tree.c ├── Graph.c ├── Heap.c ├── HuffmanTree.c ├── MST.c ├── Queue.c ├── Shortest path.c ├── Sort.c ├── Stack.c ├── TopSort.c ├── Union and Find.c └── kmp.c ├── PTA_Exercise ├── 01-复杂度1 最大子列和.c ├── 01-复杂度2 Maximum Subsequence Sum.c ├── 02-线性结构1 两个有序链表序列的合并 版本2.c ├── 02-线性结构1 两个有序链表序列的合并.c ├── 02-线性结构2 一元多项式的乘法与加法运算.c ├── 02-线性结构3 Reversing Linked List.c ├── 02-线性结构4 Pop Sequence.c ├── 03-树1 树的同构.c ├── 03-树2 List Leaves.c ├── 03-树3 Tree Traversals Again .c ├── 04-树4 是否同一棵二叉搜索树.c ├── 04-树5 Root of AVL Tree.c ├── 04-树6 Complete BST.c ├── 04-树7 二叉搜索树的操作集.c ├── 05-树7 堆中的路径.c ├── 05-树8 File Transfer.c ├── 05-树9 Huffman Codes.c ├── 06-图1 列出连通集.c ├── 06-图2 Saving James Bond - Easy Version.c ├── 06-图2 Saving James Bond - Hard Version.c ├── 06-图3 六度空间.c ├── 07-图4 哈利·波特的考试.c ├── 07-图6 旅游规划.c ├── 08-图7 公路村村通 .c ├── 08-图8 How Long Does It Take.c ├── 08-图9 关键活动.c ├── 09-排序2 Insert or Merge.c ├── 09-排序3 Insertion or Heap Sort .c ├── 1-复杂度3 二分查找.c ├── 10-排序4 统计工龄.c ├── 10-排序5 PAT Judge.c ├── 10-排序6 Sort with Swap.c ├── 11-散列1 电话聊天狂人.c ├── 11-散列2 Hashing.c ├── 11-散列3 QQ帐户的申请与登陆 - 排序法.c ├── 11-散列3 QQ帐户的申请与登陆 - 散列法.c ├── 11-散列4 Hashing - Hard Version 方法二.c ├── 11-散列4 Hashing - Hard Version.c └── KMP 串的模式匹配.c ├── README.md └── ppt ├── 1.1 什么是数据结构.pdf ├── 1.2 什么是算法.pdf ├── 1.3 应用实例.pdf ├── 10.1 快速排序.pdf ├── 10.2 表排序.pdf ├── 10.3 基数排序.pdf ├── 10.4 排序算法的比较.pdf ├── 2.1 线性表及其实现.pdf ├── 2.2 堆栈.pdf ├── 2.3 队列.pdf ├── 2.4 应用实例--多项式加法运算.pdf ├── 2.5 小白专场:一元多项式的加法乘法实现.pdf ├── 3.1 树与树的表示.pdf ├── 3.2 二叉树及存储结构.pdf ├── 3.3 二叉树的遍历(1).pdf ├── 3.4 小白专场:树的同构.pdf ├── 4.1 二叉搜索树.pdf ├── 4.2 平衡二叉树.pdf ├── 4.3 小白专场:是否同一棵二叉搜索树.pdf ├── 4.4 习题选讲-Reversing Linked List.pdf ├── 5.1 堆.pdf ├── 5.2 哈夫曼树与哈夫曼编码.pdf ├── 5.3 集合及运算.pdf ├── 5.4 小白专场:堆中的路径.pdf ├── 5.5 小白专场:File Transfer.pdf ├── 6.1 什么是图.pdf ├── 6.2 图的遍历.pdf ├── 6.3 拯救007.pdf ├── 6.4 六度空间.pdf ├── 6.5 小白专场:如何建立图.pdf ├── 7.0.1 习题选讲-Tree Traversals Again.pdf ├── 7.0.2 习题选讲-Complete Binary Search Tree.pdf ├── 7.0.3 习题选件-Huffman Code.pdf ├── 7.1 最短路径问题.pdf ├── 7.2 小白专场:哈利•波特的考试.pdf ├── 8.1 最小生成树.pdf ├── 8.2 拓扑排序.pdf ├── 8.3 习题选讲-旅游规划.pdf ├── 9.1 简单排序.pdf ├── 9.2 希尔排序.pdf ├── 9.3 堆排序.pdf ├── 9.4 归并排序.pdf └── readme.md /Notes/01 基本概念.md: -------------------------------------------------------------------------------- 1 | # 基本概念 2 | * 空间使用 3 | 函数PrintN,使得传入一个正整数为N的参数后,打印从1到N的全部正整数。 4 | ```c 5 | // 方法一:循环实现 6 | void PrintN_1(int N) 7 | { 8 | for (int i=N; i>=0; i--) 9 | { 10 | printf("%d\n", i); 11 | } 12 | return; 13 | } 14 | // 方法二:递归实现 15 | void PrintN(int N) 16 | { 17 | if (N) 18 | { 19 | PrintN(N - 1); 20 | printf("%d\n", N); 21 | } 22 | return; 23 | } 24 | ``` 25 | * 算法效率 26 | 多项式 f(x) = a0 + a1*x^1 +... +an * x^n 27 | ```c 28 | // 方法一 29 | double f1(int n, double a[], double x) 30 | { 31 | int i; 32 | double p = a[0]; 33 | for (i = 1; i <= n; i++) 34 | { 35 | p += (a[i] * pow(x, i)); 36 | } 37 | return p; 38 | } 39 | // 方法二 40 | double f2(int n, double a[], double x) 41 | { 42 | int i; 43 | double p = a[n]; 44 | for (i = n; i > 0; i--){ 45 | p = a[i - 1] + x * p; // f(x) = a0+ x(a1+x(...(an-1 + x(an))...)) 46 | } 47 | return p; 48 | } 49 | ``` 50 | 计时 51 | CLK_TCK 为常数,机器始终每秒所走的打点数 Use CLOCKS_PER_SEC instead of CLK_TCK on mac 52 | include 53 | ```c 54 | #include 55 | #include 56 | #include 57 | #define MAXN 10 // 9阶多项式的最大项数 58 | 59 | clock_t start, stop; //clock()返回的变量类型是 clock_t 60 | double duration; //秒 61 | double f1(int n, double a[], double x); 62 | double f2(int n, double a[], double x); 63 | 64 | int main(int argc, char const *argv[]) 65 | { 66 | int i; 67 | double a[MAXN]; 68 | for(i=0; i 0; i--){ 101 | p = a[i - 1] + x * p; // f(x) = a0+ x(a1+x(...(an-1 + x(an))...)) 102 | } 103 | return p; 104 | } 105 | ``` 106 | 107 | # 抽象数据类型 Abstract Data Type 108 | 数据类型,包含:数据对象集、数据集合相关联操作集。 109 | 110 | 抽象指,描述数据类型的方法不依赖于具体实现。 与存放数据的机器、物理结、编程语言构等无关。 111 | 112 | 113 | * 类型名称:矩阵 114 | * 数据对象集:M*N 115 | * 操作集:... 116 | 117 | # 算法 118 | 119 | 空间复杂度S(n) 120 | 时间复杂度T(n) 121 | 多项式算法一: 122 | (1+2+3+...+n) = (n^2 + n) /2 123 | T(n) = C1n^2 + c2n 124 | 方法二: T(n) = Cn 125 | 126 | 最坏情况负责度 127 | 平均复杂度 128 | 129 | 复杂度渐进表示 130 | 上界:T(n) = O(f(n)), 存在T(n) <= Cf(n) 131 | 下界: T(n) = Omega(g(n)), 存在T(n) >= Cg(n) 132 | 133 | # 实例: 最大子列和问题 134 | 135 | ### 算法一: 136 | 举例{1,2,3,4} 137 | sum = 1 138 | sum = 1 + 2 139 | sum = 1 + 2 + 3 140 | sum = 1 + 2 + 3 + 4 141 | sum = 2 142 | sum = 2 + 3 143 | sum = 2 + 3 + 4 144 | sum = 3 145 | sum = 3 + 4 146 | sum = 4 147 | ```c 148 | int MaxSubseqSum1( int A[], int N ) 149 | { 150 | int ThisSum, MaxSum = 0; 151 | int i, j, k; 152 | for( i = 0; i < N; i++ ) 153 | { 154 | for( j = i; j < N; j++ ) 155 | { 156 | ThisSum = 0; 157 | for( k = i; k <= j; k++ ) 158 | ThisSum += A[k]; 159 | if( ThisSum > MaxSum ) 160 | MaxSum = ThisSum; 161 | } 162 | } 163 | return MaxSum; 164 | } 165 | ``` 166 | T(N) = O(N^3) 167 | ### 算法二, 去掉K这个循环 168 | 举例{1,2,3,4} 169 | sum = 1 170 | sum = sum_previous + 2 171 | sum = sum_previous + 3 172 | sum = sum_previous + 4 173 | sum = 2 174 | sum = sum_previous + 3 175 | sum = sum_previous + 4 176 | sum = 3 177 | sum = sum_previous + 4 178 | sum = 4 179 | ```c 180 | int MaxSubseqSum2( int A[], int N ) 181 | { 182 | int ThisSum, MaxSum = 0; 183 | int i, j; 184 | for( i = 0; i < N; i++ ) 185 | { 186 | ThisSum = 0; 187 | for( j = i; j < N; j++ ) 188 | { 189 | ThisSum += A[j]; 190 | if( ThisSum > MaxSum ) 191 | MaxSum = ThisSum; 192 | } 193 | } 194 | return MaxSum; 195 | } 196 | ``` 197 | T(N) = O(N^2) 198 | 199 | ### 算法三: **分而治之** 200 | T(N) = O(NlogN) 201 | ```c 202 | int Max3( int A, int B, int C ) 203 | { /* 返回3个整数中的最大值 */ 204 | return A > B ? A > C ? A : C : B > C ? B : C; 205 | } 206 | 207 | int DivideAndConquer( int List[], int left, int right ) 208 | { /* 分治法求List[left]到List[right]的最大子列和 */ 209 | int MaxLeftSum, MaxRightSum; /* 存放左右子问题的解 */ 210 | int MaxLeftBorderSum, MaxRightBorderSum; /*存放跨分界线的结果*/ 211 | 212 | int LeftBorderSum, RightBorderSum; 213 | int center, i; 214 | 215 | if( left == right ) 216 | { /* 递归的终止条件,子列只有1个数字 */ 217 | if( List[left] > 0 ) 218 | { 219 | // printf("List[left]=%d\n", List[left]); 220 | return List[left]; 221 | } 222 | else return 0; 223 | } 224 | 225 | /* 下面是"分"的过程 */ 226 | // printf("left=%d\n", left); 227 | // printf("right=%d\n", right); 228 | center = ( left + right ) / 2; /* 找到中分点 */ 229 | // printf("center=%d\n", center); 230 | /* 递归求得两边子列的最大和 */ 231 | MaxLeftSum = DivideAndConquer( List, left, center ); 232 | // printf("MaxLeftSum=%d\n", MaxLeftSum); 233 | MaxRightSum = DivideAndConquer( List, center+1, right ); 234 | // printf("MaxRightSum=%d\n", MaxRightSum); 235 | 236 | /* 下面求跨分界线的最大子列和 */ 237 | MaxLeftBorderSum = 0; LeftBorderSum = 0; 238 | for( i=center; i>=left; i-- ) 239 | { /* 从中线向左扫描 */ 240 | LeftBorderSum += List[i]; 241 | // printf("LeftBorderSum=%d\n", LeftBorderSum); 242 | if( LeftBorderSum > MaxLeftBorderSum ) 243 | { 244 | MaxLeftBorderSum = LeftBorderSum; 245 | // printf("MaxLeftBorderSum=%d\n", MaxLeftBorderSum); 246 | } 247 | } /* 左边扫描结束 */ 248 | 249 | MaxRightBorderSum = 0; RightBorderSum = 0; 250 | for( i=center+1; i<=right; i++ ) 251 | { /* 从中线向右扫描 */ 252 | RightBorderSum += List[i]; 253 | // printf("RightBorderSum=%d\n", RightBorderSum); 254 | if( RightBorderSum > MaxRightBorderSum ) 255 | { 256 | MaxRightBorderSum = RightBorderSum; 257 | // printf("MaxRightBorderSum=%d\n", MaxRightBorderSum); 258 | 259 | } 260 | 261 | } /* 右边扫描结束 */ 262 | 263 | /* 下面返回"治"的结果 */ 264 | int Max = Max3( MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum); 265 | // printf("Max=%d\n", Max); 266 | return Max; 267 | } 268 | 269 | int MaxSubseqSum3( int List[], int N ) 270 | { /* 保持与前2种算法相同的函数接口 */ 271 | return DivideAndConquer( List, 0, N-1 ); 272 | } 273 | ``` 274 | 275 | ### 算法四: **在线处理** 276 | 每一个数据进行即时处理,在任何一个地方输入种植,都给出当前的解。 277 | ```c 278 | int MaxSubseqSum4( int A[], int N ) 279 | { 280 | int ThisSum, MaxSum; 281 | int i; 282 | ThisSum = MaxSum = 0; 283 | for( i = 0; i < N; i++ ) { 284 | ThisSum += A[i]; /* 向右累加 */ 285 | if( ThisSum > MaxSum ) 286 | MaxSum = ThisSum; /* 发现更大和则更新当前结果 */ 287 | else if( ThisSum < 0 ) /* 如果当前子列和为负 */ 288 | ThisSum = 0; /* 则不可能使后面的部分和增大,抛弃之 */ } 289 | return MaxSum; 290 | } 291 | ``` 292 | 293 | -------------------------------------------------------------------------------- /Notes/02.1 线性结构.md: -------------------------------------------------------------------------------- 1 | # 线性结构 2 | 一元多项式 3 | 4 | $$f(x) = a_0 + a_1x+...+a_nx$$ 5 | 6 | 方法一:顺序存储结构直接表示 7 | a[i]: 系数 8 | 9 | 方法二:顺序存储表示非零项 10 | 用结构数组表示:系数与指数的二元组 11 | 12 | 方法三:链表结构存储非零项 13 | coef expon link; 14 | ```c 15 | typedef struct PolyNode *polynomial; 16 | truct PolyNode{ 17 | int coef; 18 | int expon; 19 | polynomial link; 20 | } 21 | ``` 22 | ## 线性表 Linear List 23 | 同类型数据元素构成有序序列的线性结构。 24 | 数据对象集:n个元素构成的有序序列 25 | 操作集:线性表L属于List, 整数表示位置,元素x属于ElementType。操作: 26 | * List MakeEmpty(): 初始化一个空表 27 | * ElementType FindKth(int K, List L); 根据位序K,返回相应元素 28 | * int Find(ElementType x, List L); 在表中查找X第一次出现的位置 29 | * void insert(ElementType X, int i, List L); 插入 30 | * void Delete(int i, List l); 删除 31 | * int length(List L); 返回长度 32 | 33 | ## 线性存储序列的实现 34 | ```c 35 | typedef struct LNode *List; 36 | struct LNode{ 37 | ElementType Data[MAXSIZE]; 38 | int Last; 39 | }; 40 | struct LNode L; 41 | List PtrL; 42 | ``` 43 | 访问元素:L.Data[i] or PtrL->Data[i] 44 | 线性表的长度:L.Last+1 或 PtrL->Last+1 (last代表位置,因为从零开始所以是n-1) 45 | * 初始化 46 | ```c 47 | List MakeEmpty( ) 48 | { 49 | List PtrL; 50 | PtrL = (List )malloc( sizeof(struct LNode) ); 51 | PtrL->Last = -1; //last若为0 则表示表里有一个元素在0号位置 52 | return PtrL; 53 | } 54 | ``` 55 | * 查找 56 | ```c 57 | int Find( ElementType X, List PtrL ) { 58 | int i = 0; 59 | while( i <= PtrL->Last && PtrL->Data[i]!= X ) 60 | i++; 61 | if (i > PtrL->Last) return -1; 62 | /* 如果没找到,返回-1(因破坏第一个条件而跳出循环) */ 63 | else return i; /* 找到后返回的是存储位置 */ } 64 | } 65 | ``` 66 | 平均查找次数(n +1)/2,平均时间性能为 O(n) 67 | 68 | * 插入 69 | 第 i (1≤i≤n+1)个位置上插入一个值为X的新元素(其实是插在数组的第i-1个位置,因为数组从0开始标)先移动再插入,n挪到n+1,n-1挪到n, ...,i-1挪到i 70 | 在链表L中的第一个位置插入元素X,如下,MAXSIZE代表链表的size 71 | ```c 72 | void Insert( ElementType X, int i, List PtrL ) { 73 | int j; 74 | /* 表空间已满,不能插入*/ 75 | if ( PtrL->Last == MAXSIZE-1 ) 76 | { 77 | printf("表满"); 78 | return; 79 | } 80 | /*检查插入位置的合法性*/ 81 | if ( i < 1 || i > PtrL->Last+2) 82 | { 83 | printf("位置不合法"); 84 | return; 85 | } 86 | /* 开始挪位子,从最后的一位last开始直到i-1 */ 87 | for ( j = PtrL->Last; j >= i-1; j-- ) 88 | PtrL->Data[j+1] = PtrL->Data[j]; 89 | 90 | PtrL->Data[i-1] = X; /*新元素插入*/ 91 | PtrL->Last++; /*Last仍指向最后元素*/ 92 | return; 93 | } 94 | ``` 95 | 平均移动次数为 n /2, 96 | /*检查插入位置的合法性*/ 平均时间性能为 O(n) 97 | 98 | 99 | * 删除 100 | 删除第i个位置上的元素,i在1到n之间,对应数组下表0到n-1 101 | 删掉下表为i-1的元素,下标i的元素挪到i-1... 102 | ```c 103 | void Delete( int i, List PtrL ) 104 | { 105 | intj; 106 | /*检查空表及删除位置的合法性*/ 107 | if( i < 1 || i > PtrL->Last+1 ) 108 | { 109 | printf (“不存在第%d个元素”, i ); 110 | return ; 111 | } 112 | /*将 ai+1~ an顺序向前移动, 从第i位开始,到last */ 113 | for ( j = i; j <= PtrL->Last; j++ ) 114 | PtrL->Data[j-1] = PtrL->Data[j]; 115 | 116 | PtrL->Last--; /*Last仍指向最后元素*/ 117 | return; 118 | } 119 | 120 | ``` 121 | 平均移动次数为 (n-1) /2 122 | 平均时间性能为 O(n) 123 | 124 | ## 链式存储的实现 125 | 一个线性表用数组存储的时候,相邻的元素不仅逻辑上不仅逻辑上相邻,物理上也是相邻的。而链表通过链连接,建立数据元素的逻辑关系。 126 | ```c 127 | typedef struct LNode *List; 128 | struct LNode 129 | { 130 | ElementType Data; 131 | List Next; 132 | }; 133 | struct Lnode L; 134 | List PtrL; 135 | ``` 136 | * 求表长 137 | 用临时指针p指向链表头Ptrl,然后遍历,直到null 138 | ```c 139 | int Length ( List PtrL ) 140 | { 141 | List p = PtrL; /* p指向表的第一个结点*/ 142 | int j=0; 143 | while ( p ) 144 | { 145 | p = p->Next; 146 | j++; /* 当前p指向的是第 j 个结点*/ 147 | } 148 | return j; 149 | } 150 | ``` 151 | * 查找 152 | 1. 按序号查找 根据位序K,返回相应元素 FindKth(int K, List L) 153 | ```c 154 | List FindKth( int K, List PtrL ) 155 | { 156 | List p = PtrL; 157 | int i=1; // i代表第几给元素。因为一开始p指向第一个元素,所以i=1 158 | while (p !=NULL && i < K ) 159 | { 160 | p = p->Next; 161 | i++; 162 | } 163 | if ( i == K ) /* 找到第K个,返回指针 */ 164 | return p; 165 | else return NULL; /* 没找到第K个,循环因为 p=NULL 而退出 */ 166 | } 167 | ``` 168 | 2. 按值查找:Find(ElementType x, List L) 169 | ```c 170 | List Find( ElementType X, List PtrL ) 171 | { 172 | List p = PtrL; 173 | while ( p!=NULL && p->Data != X ) // 条件1表不空,条件2没找到X,就继续 174 | p = p->Next; 175 | return p; //找到了:返回节点p。没找到返回p = NULL 176 | } 177 | ``` 178 | * 插入 179 | 在第 i-1 (1≤i≤n+1) 个结点后插入一个值为X的新结点 180 | 1. 先构造一个新结点,用s指向; mallo 181 | 2. 再找到链表的第 i-1个结点,用p指向; 182 | 3. 然后修改指针,插入结点 ( p之后插入新结点是 s) 183 | ```c 184 | s-> next = p -> next; 185 | p -> next = s 186 | ``` 187 | 实现 188 | ```c 189 | List Insert( ElementType X, int i, List PtrL ) 190 | { 191 | List p, s; 192 | if ( i == 1 ) /* 新结点插入在表头 */ 193 | { 194 | s = (List)malloc(sizeof(struct LNode)); /*申请、填装结点s */ 195 | s->Data = X; 196 | s->Next = PtrL; 197 | return s; // s成为新的head,返回出去 198 | } 199 | p = FindKth( i-1, PtrL ); /* 查找第i-1个结点 */ 200 | if ( p == NULL ) 201 | { 202 | printf("参数i错"); 203 | return NULL; 204 | } 205 | else 206 | { 207 | s = (List)malloc(sizeof(struct LNode)); /*申请、填装结点*/ 208 | s->Data = X; 209 | s->Next = p->Next; /*新结点插入在第i-1个结点的后面*/ 210 | p->Next = s; 211 | return PtrL; 212 | } 213 | } 214 | ``` 215 | * 删除 216 | 删除链表的第 i (1≤i≤n) 个位置上的节点 217 | 1. 先找到链表的第 i-1个结点,用p指向; 218 | 2. 再用指针s指向要被删除的结点(p的下一个结点); 219 | 3. 然后修改指针,删除s所指结点; `p->next = s->next` 220 | 4. 最后释放s所指结点的空间。 221 | 实现 222 | ```c 223 | List Delete( int i, List PtrL ) 224 | { 225 | List p, s; 226 | if ( i == 1 ) 227 | { /* 若要删除的是表的第一个结点 */ 228 | s = PtrL; /*s指向第1个结点*/ 229 | if (PtrL!=NULL) 230 | PtrL = PtrL->Next; /*从链表中删除*/ 231 | else 232 | return NULL; // 如果本身就是空链表,return NULL 233 | free(s); 234 | return PtrL; 235 | } 236 | p = FindKth( i-1, PtrL ); /*查找第i-1个结点*/ 237 | if ( p == NULL ) 238 | { 239 | printf(“第%d个结点不存在”, i-1); 240 | } 241 | else if ( p->Next == NULL ) 242 | { 243 | printf(“第%d个结点不存在”, i); 244 | }else 245 | { 246 | s = p->Next; /*s指向第i个结点*/ 247 | p->Next = s->Next; /*从链表中删除*/ 248 | free(s); /*释放被删除结点 */ 249 | return PtrL; 250 | } 251 | } 252 | ``` 253 | 254 | # 广义表 Generalized List 255 | 256 | 二元多项式 257 | 可以将上述二元多项式看成关于x 的一元多项式 258 | 矩阵可以用二维数组表示,但二维数组表示有两个缺陷: 259 | 1. 一是数组的大小需要事先确定 260 | 2. 对于“稀疏矩阵 ”,将造成大量的存储空间浪费。 261 | 采用一种典型的多重链表——十字链表来存储稀疏矩阵 262 | * 只存储矩阵非0元素项 结点的数据域:行坐标Row、列坐标Col、数值Value 263 | * 每个结点通过两个指针域,把同行、同列串起来 264 | * 行指针(或称为向右指针)Right 265 | * 列指针(或称为向下指针)Down 266 | 267 | Term 代表非0项 268 | 特殊Term A 代表4行5列,7个非零项 269 | 270 | -------------------------------------------------------------------------------- /Notes/02.2 堆栈.md: -------------------------------------------------------------------------------- 1 | # 堆栈 Stack 2 | 具有一定操作约束的线性表,只在一端(栈顶,Top)做 插入、删除 3 | 操作集:长度为MaxSize的堆栈S 属于 Stack,堆栈元素item 属于 ElementType 4 | 1. Stack CreateStack( int MaxSize ): 生成空堆栈,其最大长度为MaxSize; 5 | 2. int IsFull( Stack S, int MaxSize ):判断堆栈S是否已满; 6 | 3. void Push( Stack S, ElementType item ):将元素item压入堆栈; 7 | 4. int IsEmpty ( Stack S ):判断堆栈S是否为空; 8 | 5. ElementType Pop( Stack S ):删除并返回栈顶元素; 9 | 10 | ## 栈的顺序存储实现 11 | 栈的顺序存储结构通常由一个一维数组和一个记录.栈顶元素位置的变量组成。 12 | ```c 13 | #define MaxSize <储存数据元素的最大个数> 14 | typedef struct SNode *Stack; //结构指针 15 | struct SNode{ 16 | ElementType Data[MaxSize]; //数组 17 | int Top; // 栈顶位置的数组下标 18 | }; 19 | ``` 20 | 21 | * 入栈 Push 22 | ```c 23 | void Push( Stack PtrS, ElementType item ) // stack这个类型的指针 24 | { 25 | if ( PtrS->Top == MaxSize-1 ) // 判断满不满。从 0 到 MaxSize-1 26 | { 27 | printf(“堆栈满”); 28 | return; 29 | }else 30 | { 31 | PtrS->Data[++(PtrS->Top)] = item; 32 | /* 相当于: 33 | (PtrS->Top)++; 34 | PtrS->Data[PtrS->Top] = item; 35 | */ 36 | return; 37 | } 38 | } 39 | ``` 40 | 41 | * 出栈 Top 42 | ```c 43 | ElementType Pop( Stack PtrS ) 44 | { 45 | if ( PtrS->Top == -1 ) 46 | { 47 | printf(“堆栈空”); 48 | return ERROR; //ERROR是ElementType的特殊值,标志错误 49 | } else 50 | { 51 | return ( PtrS->Data[(PtrS->Top)--] ); // return 出下标为top的这个值,同时Top-1 52 | } 53 | } 54 | ``` 55 | [例] 请用一个数组实现两个堆栈,要求最大地利用数组空间,使 数组只要有空间入栈操作就可以成功。 56 | 【分析】 一种比较聪明的方法是使这两个栈分别从数组的两头开始 向中间生长;当两个栈的栈顶指针相遇时,表示两个栈都满了。 57 | ```c 58 | #define MaxSize <存储数据元素的最大个数> 59 | 60 | struct DStack { 61 | ElementType Data[MaxSize]; 62 | int Top1; /* 堆栈1的栈顶指针 */ 63 | int Top2; /* 堆栈2的栈顶指针 */ 64 | } S; 65 | 66 | S.Top1 = -1; // 左边这个设为空 67 | S.Top2 = MaxSize; // 右边设为空(已经超出了MaxSize -1) 68 | ``` 69 | 入栈 70 | ```c 71 | void Push( struct DStack *PtrS, ElementType item, int Tag ) 72 | { /* Tag作为区分两个堆栈的标志,取值为1和2 */ 73 | if ( PtrS->Top2 – PtrS->Top1 == 1) /* 堆栈满, 两个指针相邻啦 */ 74 | { 75 | printf(“堆栈满”); 76 | return ; 77 | } 78 | if ( Tag == 1 ) /* 对第一个堆栈操作 */ 79 | PtrS->Data[++(PtrS->Top1)] = item; // 放在第一个元素后面一位 80 | else /* 对第二个堆栈操作 */ 81 | PtrS->Data[--(PtrS->Top2)] = item; // 放在最后一个元素的前面一位 82 | } 83 | ``` 84 | 出栈 85 | ```c 86 | ElementType Pop( struct DStack *PtrS, int Tag ) 87 | { /* Tag区分两个堆栈*/ 88 | if(Tag==1) /*对第一个堆栈操作 */ 89 | { 90 | if ( PtrS->Top1 == -1 ) /*堆栈1空 */ 91 | { 92 | printf(“堆栈1空”); 93 | return NULL; 94 | } else 95 | return PtrS->Data[(PtrS->Top1)--]; // 先抛出再对top-1 96 | } else /* 对第二个堆栈操作 */ 97 | { 98 | if ( PtrS->Top2 == MaxSize ) /*堆栈2空 */ 99 | { 100 | printf(“堆栈2空”); 101 | return NULL; 102 | } 103 | else 104 | return PtrS->Data[(PtrS->Top2)++]; // 先抛出再对top+1 105 | } 106 | } 107 | ``` 108 | ## 堆栈的链式存储实 109 | 栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删 除操作只能在链栈的栈顶进行。 110 | ```c 111 | typedef struct SNode *Stack; struct SNode{ 112 | ElementType Data; 113 | struct SNode *Next; 114 | }; 115 | ``` 116 | 初始化(建立空栈) 117 | ```c 118 | Stack CreateStack() 119 | { /* 构建一个堆栈的头结点,返回指针 */ 120 | Stack S; 121 | S =(Stack)malloc(sizeof(struct SNode)); 122 | S->Next = NULL; 123 | return S; 124 | } 125 | ``` 126 | 判断堆栈S是否为空 127 | ```c 128 | int IsEmpty(Stack S) /*判断堆栈S是否为空,若为空函数返回1,否则返回0 */ 129 | { 130 | return ( S->Next == NULL ); 131 | } 132 | ``` 133 | 134 | * 入栈 Push 135 | ```c 136 | void Push( ElementType item, Stack S) /* 将元素item压入堆栈S */ 137 | { 138 | struct SNode *TmpCell; 139 | TmpCell=(struct SNode *)malloc(sizeof(struct SNode)) 140 | TmpCell->Element = item; 141 | TmpCell->Next = S->Next; // 插到头结点的后面 142 | S->Next = TmpCell; 143 | } 144 | ``` 145 | * 出栈 Top 146 | ```c 147 | ElementType Pop(Stack S) /* 删除并返回堆栈S的栈顶元素 */ 148 | { 149 | struct SNode *FirstCell; 150 | ElementType TopElem; 151 | if( IsEmpty( S ) ) 152 | { 153 | printf(“堆栈空”); 154 | return NULL; 155 | } 156 | else 157 | { 158 | FirstCell = S->Next; 159 | S->Next = FirstCell->Next; 160 | TopElem = FirstCell ->Element; // 获得被删除的这个值,return出去 161 | free(FirstCell); 162 | return TopElem; 163 | } 164 | } 165 | ``` 166 | ## 应用:表达式求值 167 | * 运算数相对顺序不变 168 | * 运算符号顺序发生改变: 需要存储“等待中”的运算符号,要将当前运算符号与“等待中”的最后一个运算符号比较 169 | * 如果最后一个符号的优先级比较高,则出栈 170 | * 如果最后一个符号的优先级更低,则等待 171 | 172 | 括号怎么办? 173 | 左括号(优先级比乘号*高.但左括号(在堆栈中优先级就降到最低, 左括号(优先级比加号+低. 174 | 碰到右括号)后,括号内的计算结束,把堆栈内的抛出来,直到遇到左括号(. 175 | -------------------------------------------------------------------------------- /Notes/02.3 队列.md: -------------------------------------------------------------------------------- 1 | # 队列 Queue 2 | FIFO 3 | 操作集:长度为MaxSize的队列Q  Queue,队列元素item  ElementType 4 | 1. Queue CreatQueue( int MaxSize ):生成长度为MaxSize的空队列; 5 | 2. int IsFullQ( Queue Q, int MaxSize ):判断队列Q是否已满; 6 | 3. void AddQ( Queue Q, ElementType item ): 将数据元素item插入队列Q中; 7 | 4. int IsEmptyQ( Queue Q ): 判断队列Q是否为空; 8 | 5. ElementType DeleteQ( Queue Q ):将队头数据元素从队列中删除并返回。 9 | 10 | ## 队列的顺序存储实现 11 | 一个一维数组,队列头元素位置的变量front, 队列为元素位置的变量rear, 而堆栈由一个一位数组加上一个top. 12 | 队列的结构 13 | ```c 14 | #define MaxSize <储存数据元素的最大个数> 15 | struct QNode { 16 | ElementType Data[ MaxSize ]; 17 | int rear; 18 | int front; 19 | }; 20 | typedef struct QNode *Queue; 21 | ``` 22 | 循环队列 23 | 当front == rear时候, 空 24 | rear指向这个队列实际的最后一个元素的位置,front是第一个元素的前一个. 加入一个元素的时候rear + 1, 删除一个元素的时候front + 1 25 | 使用额外标记 size或者tag 26 | 仅使用n-1个数组空间 27 | * 创建队列 28 | ```c 29 | Queue CreateQueue(int Maxsize) 30 | { 31 | Queue Q = (Queue)malloc(sizeof(struct QNode)); 32 | Q->Data = (ElementType)malloc(Maxsize * sizeof(ElementType)); 33 | Q->front = Q->rear = 0; 34 | Q->Maxsize = Maxsize; 35 | return Q; 36 | } 37 | ``` 38 | 39 | * 入队列 40 | 用求余数函数,实现循环队列 例如 (5+1)%6 = 0, 放在第0位 41 | ```c 42 | void AddQ( Queue PtrQ, ElementType item) { 43 | if ( (PtrQ->rear+1) % MaxSize == PtrQ->front ) // front rear相邻 44 | { 45 | printf(“队列满”); 46 | return; 47 | } 48 | PtrQ->rear = (PtrQ->rear+1)% MaxSize; 49 | PtrQ->Data[PtrQ->rear] = item; 50 | } 51 | ``` 52 | 53 | * 出队 54 | ```c 55 | ElementType DeleteQ ( Queue PtrQ ) // front和rear相同 56 | { 57 | if ( PtrQ->front == PtrQ->rear ) 58 | { 59 | printf(“队列空”); 60 | return ERROR; 61 | } 62 | else 63 | { 64 | PtrQ->front = (PtrQ->front+1)% MaxSize; // front往后移一位指向第一个元素 65 | return PtrQ->Data[PtrQ->front]; 66 | } 67 | } 68 | ``` 69 | ## 队列的链式存储实现 70 | 链表结点结构 71 | ```c 72 | struct Node{ 73 | ElementType Data; 74 | struct Node *Next; 75 | }; 76 | ``` 77 | 链表队列结构 78 | ```c 79 | struct QNode 80 | { 81 | struct Node *rear; /* 指向队尾结点 */ 82 | struct Node *front; /* 指向队头结点 */ 83 | }; 84 | typedef struct QNode *Queue; 85 | Queue PtrQ; // 包含front和rear的这个结构的指针PtrQ 86 | ``` 87 | 88 | * 出队 89 | ```c 90 | ElementType DeleteQ ( Queue PtrQ ) 91 | { 92 | struct Node *FrontCell; 93 | ElementType FrontElem; 94 | 95 | if ( PtrQ->front == NULL) 96 | { 97 | printf(“队列空”); 98 | return ERROR; 99 | } 100 | FrontCell = PtrQ->front; // 找到队列的头个元素 101 | if ( PtrQ->front == PtrQ->rear) /* 若队列只有一个元素 */ 102 | PtrQ->front = PtrQ->rear = NULL; /* 删除后队列置为空 */ 103 | else 104 | PtrQ->front = PtrQ->front->Next; 105 | FrontElem = FrontCell->Data; 106 | free( FrontCell ); /* 释放被删除结点空间 */ 107 | return FrontElem; 108 | } 109 | ``` 110 | 111 | ## 应用: 多项式加法运算 112 | 算法思路: 113 | 两个指针P1和P2分别指向这两个多项式第一个结点,不断循环: 114 | * P1->expon==P2->expon相同: 系数相加,若结果不为0,则作为结果多项式对应项 115 | 的系数。同时,P1和P2都分别指向下一项; 116 | * P1->expon>P2->expon 这时p1大: 将P1的当前项存入结果多项式,并使P1指向下一项; 117 | * P1->exponexpon 这时p2大: 将P2的当前项存入结果多项式,并使P2指向下一项; 118 | * 当某一多项式处理完时,将另一个多项式的所有结点依次复制到结果多项式中去。 119 | 120 | ```c 121 | struct PolyNode //结构类型 122 | { 123 | int coef; // 系数 124 | int expon; // 指数 125 | struct PolyNode *link; // 指向下一个节点的指针 126 | } 127 | typedef struct PolyNode *Polynomial; 128 | Polynomial P1, P2; // p1 p2都是这种结构的指针 129 | ``` 130 | 实现 131 | 132 | ```c 133 | Polynomial PolyAdd (Polynomial P1, Polynomial P2) 134 | { 135 | Polynomial front, rear, temp; // 结构多项式的头 尾. 136 | int sum; 137 | 138 | // 临时空结点点作为结果多项式的表头, front rear都指向这个空间点 139 | rear = (Polynomial) malloc(sizeof(struct PolyNode)); 140 | front = rear; /* 由front 记录结果多项式链表头结点 */ 141 | 142 | while ( P1 && P2 ) /* 当两个多项式都有非零项(都不空)待处理时 */ 143 | switch ( Compare(P1->expon, P2->expon) ) // 比较两个指数 144 | { 145 | case 1: // p1大 146 | // 系数和指素接到rear的后面 147 | Attach( P1->coef, P1->expon, &rear); 148 | P1 = P1->link; 149 | break; 150 | case -1: // p2大 151 | Attach(P2->coef, P2->expon, &rear); 152 | P2 = P2->link; 153 | break; 154 | case 0: //p1 = p2 155 | sum = P1->coef + P2->coef; 156 | // 判断sum不等于0 157 | if ( sum ) Attach(sum, P1->expon, &rear); 158 | P1 = P1->link; 159 | P2 = P2->link; 160 | break; 161 | } 162 | /* 将未处理完的另一个多项式的所有节点依次复制到结果多项式中去 */ 163 | // p1不空 164 | for ( ; P1; P1 = P1->link ) 165 | Attach(P1->coef, P1->expon, &rear); 166 | // p2 不空 167 | for ( ; P2; P2 = P2->link ) 168 | Attach(P2->coef, P2->expon, &rear); 169 | 170 | // rear 指向结果多项式的最后一项,现在结束了,把link设为NULL 171 | rear->link = NULL; 172 | // 释放临时结点 173 | temp = front; 174 | front = front->link; /*令front指向结果多项式第一个非零项 */ 175 | free(temp); /* 释放临时空表头结点 */ 176 | return front; 177 | } 178 | ``` 179 | 其中attach函数 180 | ```c 181 | //传入系数和指数,以及最后一个结点的指针位置(指针的指针),于在本函数中需要改变当前结果表达式尾项指针的值,所以函数传递进来的是结点指针的地址,*pRear指向尾项 182 | void Attach( int c, int e, Polynomial *pRear ) 183 | { 184 | Polynomial P; 185 | /* 申请新结点 */ 186 | P =(Polynomial)malloc(sizeof(struct PolyNode)); 187 | P->coef = c; /* 对新结点赋值 */ 188 | P->expon = e; 189 | P->link=NULL; 190 | /* 将P指向的新结点插入到当前结果表达式尾项的后面 */ 191 | (*pRear)->link = P; 192 | *pRear = P; /* 修改pRear值 */ 193 | } 194 | ``` 195 | 196 | -------------------------------------------------------------------------------- /Notes/3.1 树与树的表示.md: -------------------------------------------------------------------------------- 1 | # 树与树的表示 2 | 查找 Searching 3 | * 静态查找 集合是固定的,没有插入和删除 4 | * 动态查找 集合中的记录是动态变化的,可以插入和删除 5 | 6 | ### 静态查找 Sequential Search 7 | 结构体: 8 | ```c 9 | typedef struct Lnode *List; 10 | struct Lnode{ 11 | ElementType Element[MAXSIZE]; 12 | int length; 13 | } 14 | ``` 15 | 函数: 16 | ```c 17 | int SequentialSearch(List tb1, ElementType K){ 18 | int i; 19 | tb1->Element[0] = K; // 建立哨兵 20 | for(i = tb1->length; tb1->Element[i] != K; i--); //从下往上循环直到K 21 | return i; // 成功返回下标,不成功返回0 22 | } 23 | ``` 24 | 顺序查找算法的时间复杂度为O(n) 25 | 26 | ### 二分查找 Binary Search 27 | 函数: 28 | ```c 29 | int BinarySearch ( StaticTable * Tb1, ElementType K) 30 | { /*在表Tbl中查找关键字为K的数据元素*/ 31 | int left, right, mid, NoFound=-1; 32 | left = 1; 33 | right = Tb1->Length; 34 | while ( left <= right ) 35 | { 36 | mid = (left+right)/2; 37 | if( K < Tb1->Element[mid]) right = mid-1; 38 | else if( K > Tb1->Element[mid]) left = mid+1; 39 | else return mid; /*查找成功,返回数据元素的下标*/ 40 | } 41 | return NotFound; /*查找不成功,返回-1*/ 42 | } 43 | ``` 44 | 二分查找算法具有对数的时间复杂度O(logN) 45 | 判定树: 46 | 判定树上每个结点需要的查找次数刚好 为该结点所在的层数. 47 | n个结点的判定树的深度 为[log2n]+1. 48 | 49 | ## 树 Tree 50 | 定义:n(n≥0)个结点构成的有限集合 51 | 子树是不相交的,除了根结点外,每个结点有且仅有一个父结点 52 | 结点的度(Degree):结点的子树个数 53 | 树的度:树的所有结点中最大的度数 54 | 结点的层次(Level):规定根结点在1层, 其它任一结点的层数是其父结点的层数加1。 55 | 树的深度(Depth):树中所有结点中的最 大层次是这棵树的深度。 56 | 57 | ### 二叉树 58 | 度为2的树,可以为空.若不为空由根节点和左子树和右子树 59 | * 一个二叉树第 i 层的最大结点数为:2^(i-1) 60 | * 深度为k的二叉树有最大结点总数为: 2^k -1 61 | * 对任何非空二叉树T,若$n_0$表示叶结点的个数、$n_2$是度为2的非叶结点个数,那么两者满足关系$n_0 = n_2 +1$ 62 | 证明: 总边数=总节点数-1 (因为根没有向上的边) 63 | 总边数= n0 + n1 +n2 -1 64 | 总边数 = 0*n0 + 1*n1 + 2*n2 (往下看) 65 | 66 | 二叉树的存储结构 67 | 1. 顺序存储结构 68 | 完全二叉树 69 | 父节点:i/2 70 | 左子节点: 2i 71 | 右子节点: 2i+1 72 | 2. 链表存储 73 | ```c 74 | typedef struct TreeNode * BinTree; 75 | typedef BinTree Position; 76 | struct TreeNode 77 | { 78 | ElementType Data; 79 | BinTree Left; 80 | BinTree Right; 81 | } 82 | ``` 83 | 84 | ### 二叉树的遍历 85 | 1. 先序遍历 PreOrder Traversal 86 | 根节点->左子树->右子树 87 | ```c 88 | void PreOrderTraversal( BinTree BT ) 89 | { 90 | if( BT ) // BT不空 91 | { 92 | printf(“%d”, BT->Data); 93 | PreOrderTraversal( BT->Left ); 94 | PreOrderTraversal( BT->Right ); 95 | } 96 | } 97 | ``` 98 | 2. 中序遍历 InOrderT Traversal 99 | 左子树->根节点->右子树 100 | 101 | 3. 后序遍历 Post-Order Traversal 102 | 左子树->右子树->根节点 103 | 104 | 二叉树的非递归遍历 105 | 中序遍历的非递归算法实现 106 | ```c 107 | void InOrderTraversal( BinTree BT ) 108 | { 109 | BinTree T=BT; 110 | Stack S = CreatStack( MaxSize ); /*创建并初始化堆栈S*/ 111 | while( T || !IsEmpty(S) ) 112 | { //IsEmpty是判断堆栈空不空 113 | while(T){ /*一直向左并将沿途结点压入堆栈*/ \ 114 | Push(S,T); 115 | T = T->Left; 116 | } 117 | if(!IsEmpty(S)){ 118 | T = Pop(S); /*结点弹出堆栈*/ 119 | printf(“%5d”, T->Data); /*(访问)打印结点*/ 120 | T = T->Right; /*转向右子树*/ 121 | } 122 | } 123 | } 124 | ``` 125 | 126 | ### 层序遍历 127 | 队列实现:遍历从根结点开始,首先将根结点入队,然后开始执 行循环:结点出队、访问该结点、其左右儿子入队 128 | 算法实现: 129 | ```c 130 | void LevelOrderTraversal ( BinTree BT ) 131 | { 132 | Queue Q; BinTree T; 133 | if ( !BT ) return; /* 若是空树则直接返回 */ 134 | Q = CreatQueue( MaxSize ); /*创建并初始化队列Q*/ 135 | AddQ( Q, BT ); // 把根节点放到队列里去 136 | while ( !IsEmptyQ( Q ) ) { 137 | T = DeleteQ( Q ); // pop出一个元素,产生的元素赋给 T指针 138 | printf(“%d\n”, T->Data); /*访问取出队列的结点*/ 139 | if ( T->Left ) AddQ( Q, T->Left ); 140 | if ( T->Right ) AddQ( Q, T->Right ); 141 | } 142 | } 143 | ``` 144 | 145 | ### 输出二叉树叶子节点 146 | ```c 147 | void PreOrderPrintLeaves( BinTree BT ) 148 | { 149 | if( BT ) { 150 | if ( !BT->Left && !BT->Right ) // 如果没有左右子树,就打印出来 151 | printf(“%d”, BT->Data ); 152 | PreOrderPrintLeaves ( BT->Left ); 153 | PreOrderPrintLeaves ( BT->Right ); 154 | } 155 | } 156 | ``` 157 | 158 | ### 求二叉树的高度 159 | ```c 160 | int PostOrderGetHeight( BinTree BT ) 161 | { 162 | int HL, HR, MaxH; 163 | if( BT ) 164 | { 165 | HL = PostOrderGetHeight(BT->Left); /*求左子树的深度*/ 166 | HR = PostOrderGetHeight(BT->Right); /*求右子树的深度*/ 167 | MaxH = (HL > HR)? HL : HR; /*取左右子树较大的深度*/ 168 | return ( MaxH + 1 ); /*返回树的深度*/ 169 | } 170 | else return 0; /* 空树深度为0 */ 171 | } 172 | ``` 173 | 174 | ### 层序生成二叉树 175 | ```c 176 | typedef int ElementType; //假设是int 177 | #define NoInfo 0; 178 | 179 | typedef struct TreeNode * BinTree; 180 | typedef BinTree Position; 181 | struct TreeNode 182 | { 183 | ElementType Data; 184 | BinTree Left; 185 | BinTree Right; 186 | } 187 | 188 | BinTree CreateBinTree() 189 | { 190 | ElementType Data; 191 | BinTree BT, T; 192 | Q = CreateQueue(); 193 | 194 | // 读入第一个检点,即根节点 195 | scanf("%d", &Data); 196 | if (Data != NoInfo) 197 | { // 不为空, 分配根节点单元,并将节点地址入队 198 | BT = (BinTree)mallo(sizeof(Struct Tnode)); 199 | BT->Data = Data; 200 | Bt->Left = BT->Right = NULL; 201 | AddQ(Q, BT); 202 | }else return NULL; //若第一个数据0,则返回空树 203 | 204 | while(!IsEmpty(Q)){ 205 | T->DeleteQ(Q); //从队列中取出一节点地址 206 | // 读左孩子 207 | scanf("%d", &Data); 208 | if(Data != NoInfo) 209 | T->Left = NULL; 210 | else // 分配新节点,作为出队节点的左孩子,分配的新节点入队 211 | { 212 | T->Left = (BinTree)mallo(sizeof(Struct Tnode)); 213 | T->Left->Data = Data; 214 | T->Left->Left = T->Left->Right = NULL; 215 | AddQ(Q, T->Left); 216 | } 217 | 218 | // 读右孩子 219 | scanf("%d", &Data); 220 | if(Data != NoInfo) 221 | T->Right = NULL; 222 | else // 分配新节点,作为出队节点的右孩子,分配的新节点入队 223 | { 224 | T->Right = (BinTree)mallo(sizeof(Struct Tnode)); 225 | T->Right->Data = Data; 226 | T->Right->Left = T->Right->Right = NULL; 227 | AddQ(Q, T->Left); 228 | } 229 | }// while循环结束 230 | return BT; 231 | } 232 | -------------------------------------------------------------------------------- /Notes/4.二叉搜索树与平衡二叉树.md: -------------------------------------------------------------------------------- 1 | # 二叉搜索树 Binary Search Tree 2 | 1. 非空左子树所有键值小于根节点的键值 3 | 2. 非空右子树所有键值大于根节点的键值 4 | 3. 左右子树都是二叉搜索树 5 | 6 | 操作的函数: 7 | 1. Position Find( ElementType X, BinTree BST ):从二叉搜索树BST 中查找元素X,返回其所在结点的地址; 8 | 2. Position FindMin( BinTree BST ):从二叉搜索树BST中查找并返回 最小元素所在结点的地址; 9 | 3. Position FindMax( BinTree BST ) :从二叉搜索树BST中查找并返回 最大元素所在结点的地址。 10 | 4. BinTree Insert( ElementType X, BinTree BST ) 插入 11 | 5. BinTree Delete( ElementType X, BinTree BST ) 删除 12 | 13 | 14 | ## 查找 15 | 递归实现 16 | ```c 17 | Position Find( ElementType X, BinTree BST ) { 18 | if( !BST ) return NULL; /*查找失败*/ 19 | if( X > BST->Data ) 20 | return Find( X, BST->Right ); /*在右子树中继续查找*/ 21 | Else if( X < BST->Data ) 22 | return Find( X, BST->Left ); /*在左子树中继续查找*/ 23 | else 24 | /* X == BST->Data */ 25 | return BST; /*查找成功,返回结点的找到结点的地址*/ 26 | } 27 | ``` 28 | 迭代实现 29 | ```c 30 | Position IterFind( ElementType X, BinTree BST ) { 31 | while( BST ) 32 | { 33 | if( X > BST->Data ) 34 | BST = BST->Right; /*向右子树中移动,继续查找*/ 35 | else if( X < BST->Data ) 36 | BST = BST->Left; /*向左子树中移动,继续查找*/ 37 | else /* X == BST->Data */ 38 | return BST; /*查找成功,返回结点的找到结点的地址*/ 39 | } 40 | return NULL; /*查找失败*/ 41 | } 42 | ``` 43 | 44 | ## 返回最大值/最小值 45 | 最大元素一定在最右分支的端点上 46 | ```c 47 | Position FindMax( BinTree BST ) 48 | { 49 | if(BST ) // 结点不空 50 | { 51 | while( BST->Right ) // 右儿子不空 52 | BST = BST->Right; // 则往右 53 | } 54 | return BST; 55 | } 56 | ``` 57 | 最小元素在最左段上 58 | 递归法: 59 | ```c 60 | Position FindMin( BinTree BST ) 61 | { 62 | if( !BST ) return NULL;/*空的二叉搜索树,返回NULL*/ 63 | else if( !BST->Left ) 64 | return BST; /*找到最左叶结点并返回*/ 65 | else 66 | return FindMin( BST->Left ); /*沿左分支继续查找*/ 67 | ``` 68 | 69 | ## 插入 70 | ```c 71 | BinTree Insert( ElementType X, BinTree BST ) { 72 | if( !BST ) /*若原树为空,生成并返回一个结点的二叉搜索树*/ 73 | { 74 | BST = malloc(sizeof(struct TreeNode)); 75 | BST->Data = X; 76 | BST->Left = BST->Right = NULL; 77 | } 78 | else /*开始找要插入元素的位置*/ 79 | { 80 | if( X < BST->Data ) 81 | BST->Left = Insert( X, BST->Left); /*递归插入左子树*/ 82 | else if( X > BST->Data ) 83 | BST->Right = Insert( X, BST->Right); /*递归插入右子树*/ 84 | /* else X已经存在,什么都不做 */ 85 | } 86 | return BST; 87 | } 88 | ``` 89 | 90 | ## 删除 91 | 1. 删除的是叶结点 92 | 2. 删除的只有一个孩子的结点 93 | 3. 要删除的结点右左右两棵子树,则: 94 | * 右子树最小元素替代 95 | * 左子树最大元素替代 96 | 97 | 实现 98 | ```c 99 | BinTree Delete( BinTree BST, ElementType X ) 100 | { 101 | Position Tmp; 102 | 103 | if( !BST ) 104 | printf("要删除的元素未找到"); 105 | else { 106 | if( X < BST->Data ) 107 | BST->Left = Delete( BST->Left, X ); /* 从左子树递归删除 */ 108 | else if( X > BST->Data ) 109 | BST->Right = Delete( BST->Right, X ); /* 从右子树递归删除 */ 110 | else { /* BST就是要删除的结点 */ 111 | /* 如果被删除结点有左右两个子结点 */ 112 | if( BST->Left && BST->Right ) { 113 | /* 从右子树中找最小的元素填充删除结点 */ 114 | Tmp = FindMin( BST->Right ); 115 | BST->Data = Tmp->Data; 116 | /* 从右子树中删除最小元素 */ 117 | BST->Right = Delete( BST->Right, BST->Data ); 118 | } 119 | else { /* 被删除结点有一个或无子结点 */ 120 | Tmp = BST; 121 | if( !BST->Left ) /* 只有右孩子或无子结点 */ 122 | BST = BST->Right; 123 | else /* 只有左孩子 */ 124 | BST = BST->Left; 125 | free( Tmp ); 126 | } 127 | } 128 | } 129 | return BST; 130 | } 131 | ``` 132 | # 平衡二叉树 Balanced Binary Tree 133 | 平均查找长度ASL 134 | 平衡因子(Balance Factor,简称BF): BF(T) = hL-hR, 135 | |BF(T)| <= 1 136 | 平衡二叉树的高度 137 | n_h: 高度为h的平衡二叉树最少结点数 138 | n_h = n_h-1 + n_h-2 + 1 139 | = F_h+2 - 1 140 | 给定结点数为 n的AVL树的 最大高度为O(log2n)! 141 | 142 | ## 调整 143 | 平衡二叉树是搜索树 144 | 右单旋 145 | 麻烦结点在发现者(被破坏者)的右子树的右子树上,因而RR插入,需要RR旋转 146 | 左单旋 147 | 麻烦结点在发现者(被破坏者)的左子树的左子树上,因而LL旋转 148 | 左右旋转 149 | 麻烦结点在发现者(被破坏者)的左子树的右子树上, LR旋转 150 | 151 | 习题: 是否同一颗二叉搜索树 152 | 1. 根据两个序列分别建树,再判别树是否一样 153 | 2. 不建树的判别方法 154 | 3. 建一棵树,再判别其他序列是否与该树一致 155 | -------------------------------------------------------------------------------- /Notes/5 堆 哈夫曼树.md: -------------------------------------------------------------------------------- 1 | # 堆 Heap 2 | 优先队列(Priority Queue) 3 | 结构性:用 *数组* 表示的完全二叉树; 4 | 有序性:任一结点的关键字是其子树所有结点的最大值(或最小值) 5 | * “最大堆(MaxHeap)”,也称“大顶堆”:最大值 6 | * “最小堆(MinHeap)”,也称“小顶堆” :最小值 7 | 8 | 主要操作有: 9 | • MaxHeap Create( int MaxSize ):创建一个空的最大堆。 10 | • Boolean IsFull( MaxHeap H ):判断最大堆H是否已满。 11 | • Insert( MaxHeap H, ElementType item ):将元素item插入最大堆H。 12 | • Boolean IsEmpty( MaxHeap H ):判断最大堆H是否为空。 13 | • ElementType DeleteMax( MaxHeap H ):返回H中最大元素(高优先级)。 14 | 15 | ## 结构 16 | ```c 17 | typedef struct HNode *MaxHeap; 18 | struct HNode { 19 | ElementType *Elements; // 存储堆元素的数组 20 | int Size; // 堆的当前元素的个数 21 | int Capacity // 堆的最大容量 22 | } 23 | 24 | ``` 25 | 26 | ## 创建 27 | ```c 28 | MaxHeap CreateHeap(int Maxsize) 29 | { 30 | MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode)); 31 | H->Elements = malloc((MaxSize+1) * sizeof(ElementType)); // 因为这里是一个数组,需要分配空间 32 | H->Size = 0; // 当前是空的 33 | H->Capacity = MaxSize; // 堆的最大容量 34 | H->Elements[0] = MaxSize; /* 定义“哨兵”为大于堆中所有可能元素的值,便于以后操作 */ 35 | return H; 36 | } 37 | ``` 38 | 39 | ## 插入 40 | 将新增结点插入到从其父结点到根结点的有序序列中 41 | 将新item放在最后的位置Size+1, 然后跟他的父节点i/2比较,不断把父节点往下(子节点)移动,直到其父节点大于item 42 | ```c 43 | void InsertHeap(MaxHeap H, ElementType item) 44 | { 45 | int i; 46 | if (IsFull(H)){ 47 | printf("FULL\n"); 48 | return; 49 | } 50 | i = ++H->Size; // H->Size++; i = H->Size; 把新增元素放在末尾H->Size++的位置上 51 | for(; H->Elements[i/2] < item; i/=2){ // 其父节点小于它 52 | H->Elements[i] = H->Elements[i/2]; // 把它的父节点,向下过滤, 插入的item向上过滤 53 | } 54 | // 当它的父结点[i/2]比它大的时候, 跳出循环 55 | H->Elements[i] = item; // 填上item 56 | } 57 | 58 | 59 | ``` 60 | 61 | # 删除 62 | 取出根结点(最大值)元素,同时删除堆的一个结点。 63 | * 最后的元素替补根的位置 64 | * 有序化, 父结点和更大的那个子结点比较,将子结点不断往上移, 直到父结点不子结点大 65 | ```c 66 | ElementType DeleteMax(MaxHeap H) 67 | { 68 | int parent, child; 69 | ElementType MaxItem, temp; 70 | if(IsEmpty(H)){ 71 | printf("Empty\n"); 72 | return; 73 | } 74 | 75 | MaxItem = H->Elements[1]; // 取出最大值 76 | /* 用最大堆中最后一个元素从根节点开始向上过滤下层节点 */ 77 | temp = H->Elements[Size]; // 把堆中最后一个值,交给temp 78 | Size--; 79 | 80 | for(parent=1; parent*2 <= H->Size; parent=child) 81 | { 82 | child = parent*2 // 左儿子 83 | 84 | /* child=左右儿子中大的那个, 当右儿子存在,且右儿子的值比左儿子大时,让child=右儿子 */ 85 | if((child!= H->Size) && 86 | (H->Elements[child] < H->Elements[child+1])) 87 | child++; 88 | 89 | /* 当temp比child的值大时跳出循环 */ 90 | if (temp >= Elements[child]) 91 | break; 92 | else 93 | H->Elements[parent] = H->Elements[child]; //当parent < child,这个parent位置上变为child的值 94 | } 95 | H->Elements[parent] = temp; 96 | return MaxItem; 97 | } 98 | ``` 99 | 100 | # 堆排序 101 | 方法1:通过插入操作,将N个元素一个个相继插入到一个初 始为空的堆中去,其时间代价最大为O(N logN)。 102 | 103 | 方法2:在线性时间复杂度下建立最大堆。O(N) 104 | (1)将N个元素按输入顺序存入,先满足完全二叉树的结构特性 105 | (2)调整各结点位置,以满足最大堆的有序特性。 106 | ```c 107 | void BuildHeap(MaxHeap H){ 108 | int i; 109 | for(i = H->Size/2; i>0; i--) 110 | {// 从最后一个结点的父节点开始,到根节点为止 111 | PercDown(H, i); 112 | } 113 | } 114 | 115 | // 下滤函数, 将Maxheap中以H->Data[p]为根的子堆调整为最大堆 116 | void PercDown( MaxHeap H, int p) 117 | { 118 | int parent, child; 119 | 120 | X = H->Data[p]; // 取出根节点的值 121 | for(parent = p; parent*2 <= H->Size; parent = child) 122 | { 123 | child = parent * 2; 124 | if( (child != H->Size) && (H->Data[child] < H->Data[child+1])) 125 | { 126 | child++; 127 | } 128 | if (X > H->Data[child]) 129 | break; 130 | else // 将X下滤 131 | H->Data[parent] = H->Data[child]; 132 | } 133 | H->Data(parent) = X; 134 | } 135 | ``` 136 | 137 | # 哈夫曼树与哈夫曼编码 138 | 带权路径WPL Weighted Path Length)长度最小, 最优二叉树. 139 | 数据结构: 140 | ```c 141 | typedef struct TreeNode *HuffmanTree; 142 | struct TreeNode{ 143 | int Weight; 144 | HaffmanTree left; 145 | HaffmantREE Right; 146 | } 147 | ``` 148 | 利用最小堆进行构造: 149 | ```c 150 | HuffmanTree Huffman(MinHeap H) 151 | { 152 | int i; 153 | HuffmanTree T; 154 | BuildMinHeap(H); // 将H->Elements[]按照权重调整为最小堆 155 | for(i=1; i < H->Size; i++) // 做size-1次合并 156 | { 157 | T = malloc(sizeof(struct TreeNode)); // 建立新结点 158 | /*从最小堆中删除一个结点,作为新T的左子结点*/ 159 | T->Left = DeleteMin(H); 160 | T->Right = DeleteMin(H); 161 | /*计算新权值*/ 162 | T->Weight = T->Left->Weight+T->Right->Weight; 163 | Insert( H, T ); /*将新T插入最小堆*/ 164 | } 165 | T = Deletemin(H); // 最小堆中的最后一个元素就是指向Huffman树根节点的指针 166 | return T; 167 | } 168 | ``` 169 | 哈夫曼树的特点: 170 | 1. 没有度为1的结点 171 | 2. n个叶子结点的哈夫曼树共有2n-1个结点; 172 | 因为: n2= n0 -1, 173 | 总结点数 = n0 + n2 = 2n0 - 1 174 | 3. 哈夫曼树的任意非叶节点的左右子树交换后仍是哈夫曼树; 175 | 4. 对同一组权值{w1 ,w2 , ...... , wn},存在不同构的两 176 | 177 | # 集合及运算 178 | 双亲表示法: 孩子指向父节点 179 | 数据结构 180 | ```c 181 | typedef struct 182 | { 183 | ElementType Data; 184 | int Parent; // 其父节点的下标 185 | } SetType; 186 | ``` 187 | ## 查找某个元素所在的集合 188 | 用根节点表示 189 | ```c 190 | int Find(SetType S[], ElementType X) 191 | { 192 | /* 在数组S中查找值为X的元素所属的集合, MaxSize为数组最大长度 */ 193 | int i; 194 | for(i=0; i= MaxSize) // 未找到 196 | return -1; 197 | for(; S[i].Parent >= 0; i = s[i].Parent); // 向上找它的父节点 198 | return i; 199 | } 200 | ``` 201 | ## 集合的并运算 202 | 如果它们不同根,则将其中一个根结点的父结点指针设置成 203 | 另一个根结点的数组下标。 204 | ```c 205 | void Union( SetType S[], ElementType X1, ElementType X2 ) 206 | { 207 | int Root1, Root2; 208 | Root1 = Find(S, X1); 209 | Root2 = Find(S, X2); 210 | if( Root1 != Root2 ) 211 | S[Root2].Parent = Root1; 212 | } 213 | ``` 214 | 为了使树更矮,合并时按秩合并 215 | 直接用一个数组表示,不用之前的数据结构了 216 | ```c 217 | #define MAXN 1000 /* 集合最大元素个数 */ 218 | typedef int ElementType; /* 默认元素可以用非负整数表示 */ 219 | typedef int SetName; /* 默认用根结点的下标作为集合名称 */ 220 | typedef ElementType SetType[MAXN]; /* 假设集合元素下标从0开始 */ 221 | 222 | SetName Find(SetType S, ElementType X){ 223 | for(; S[X] > 0; X=S[X]); 224 | return X. 225 | } 226 | void OldUnion(SetType S, SetName Root1, SetName Root2){ 227 | S[Root2] = Root1; 228 | } 229 | 230 | void Union( SetType S, SetName Root1, SetName Root2 ) 231 | { /* 这里默认Root1和Root2是不同集合的根结点 */ 232 | /* 保证小集合并入大集合 */ 233 | if ( S[Root2] < S[Root1] ) { /* 如果集合2比较大 */ 234 | S[Root2] += S[Root1]; /* 集合1并入集合2 */ 235 | S[Root1] = Root2; 236 | } 237 | else { /* 如果集合1比较大 */ 238 | S[Root1] += S[Root2]; /* 集合2并入集合1 */ 239 | S[Root2] = Root1; 240 | } 241 | } 242 | ``` 243 | 路径压缩 244 | ```c 245 | SetName Find( SetType S, ElementType X ) 246 | { 247 | if ( S[X] < 0 ) /* 找到集合的根 */ 248 | return X; 249 | else 250 | return S[X] = Find( S, S[X] ); /* 路径压缩 */ 251 | } 252 | ``` 253 | -------------------------------------------------------------------------------- /Notes/6 图.md: -------------------------------------------------------------------------------- 1 | # 图 Graph 2 | 顶点的集合 V (Vertex) 3 | 边的集合 E (Edge) 4 | * 邻接矩阵 5 | 用一个长度为N(N+1)/2的1维数组A存储 6 | O(N^2) 7 | * 邻接表 8 | G[N]为指针数组,对应矩阵每行一个链表, 只存非0元素 9 | O(N+E) 10 | 11 | ## 建立图 12 | 邻接矩阵 13 | ```c 14 | // 用全局变量建图 15 | int G[MAXN][MAXN], Nv, Ne; 16 | void BuildGraph() 17 | { 18 | int i,j,v1,v2,w; 19 | scanf("%d", &Nv); 20 | /* CreateGraph */ 21 | for (i=0; iAdjV */ 63 | for( W=Graph->G[V].FirstEdge; W; W=W->Next ) 64 | if ( !Visited[W->AdjV] ) 65 | DFS( Graph, W->AdjV, Visit ); 66 | } 67 | ``` 68 | 69 | ### 广度优先搜索(Breadth First Search, BFS) 70 | 层序遍历 71 | ```c 72 | // 伪码 73 | void BFS ( Vertex V ) 74 | { 75 | visited[V] = true; 76 | Enqueue(V, Q); 77 | while(!IsEmpty(Q)){ 78 | V = Dequeue(Q); 79 | for ( V 的每个邻接点 W ) 80 | if ( !visited[W] ) 81 | { 82 | visited[W] = true; 83 | Enqueue(W, Q); 84 | } 85 | } 86 | } 87 | 88 | ``` 89 | 实现 邻接矩阵存储的图 - BFS 90 | ```c 91 | /* IsEdge(Graph, V, W)检查是否图Graph中的一条边,即W是否V的邻接点。 */ 92 | 93 | bool IsEdge( MGraph Graph, Vertex V, Vertex W ) 94 | { 95 | return Graph->G[V][W]Nv; W++ ) /* 对图中的每个顶点W */ 115 | /* 若W是V的邻接点并且未访问过 */ 116 | if ( !Visited[W] && IsEdge(Graph, V, W) ) { 117 | /* 访问顶点W */ 118 | Visit( W ); 119 | Visited[W] = true; /* 标记W已访问 */ 120 | AddQ(Q, W); /* W入队列 */ 121 | } 122 | } /* while结束*/ 123 | } 124 | ``` 125 | 126 | 127 | -------------------------------------------------------------------------------- /Notes/7 最短路径.md: -------------------------------------------------------------------------------- 1 | # 最短路径 2 | 在网络中,求两个不同顶点之间的所有路径 中,边的权值之和最小的那一条路径 3 | 4 | ## 无权图的单源最短路算法 5 | 按照递增(非递减)的顺序找出到各个顶 点的最短路 6 | 伪码描述: 7 | ```c 8 | void Unweighted ( Vertex S ) 9 | { 10 | Enqueue(S, Q); 11 | while(!IsEmpty(Q)){ 12 | V = Dequeue(Q); 13 | for ( V 的每个邻接点 W ) 14 | if(dist[W]==-1 ){ 15 | dist[W] = dist[V]+1; 16 | path[W] = V; 17 | Enqueue(W, Q); 18 | } 19 | } 20 | } 21 | ``` 22 | 实现 23 | 无权图的单源最短路算法 - 邻接表存储 24 | dist[] path[]全部初始化为-1 25 | ```c 26 | void Unweighted(LGraph Graph, int dist[], int path[], Vertex S){ 27 | Queue Q; 28 | Vertex V; 29 | PtrAdjVNode W; 30 | 31 | Q = CreateQueue(Graph->Nv); // 创建空队列,MaxSize为外部定义的常数 32 | dist[S] = 0; // 初始化源点 33 | AddQ(Q, S); 34 | 35 | while (IsEmpty(Q)) 36 | { 37 | V = DeleteQ(Q); 38 | for( W = Graph.G[V].FirstEdge; W; W=W->Next) // 对V的每个邻接点W->AdjV 39 | if (dist[W->AdjV] == -1) 40 | { // W->AdjV 未被访问过 41 | dist[W->AdjV] =dist[V] + 1; /* W->AdjV到S的距离更新 */ 42 | path[W->AdjV] = V; /* 将V记录在S到W->AdjV的路径上 */ 43 | AddQ(Q, W->AdjV); 44 | } 45 | } 46 | } 47 | ``` 48 | 49 | ## 有权图的单源最短路算法 50 | Dijkstra 算法 51 | 按照递增的顺序找出到各个顶点的最短路 52 | * 真正的最短路必须只经过S中的顶点 53 | * 每次从未收录的顶点中选一个dist最小的收录 54 | * 增加一个v进入S,可能影响另外一个w的dist值 55 | * dist[w] = min{dist[w], dist[v] + 的权重} 56 | 57 | 伪码 58 | ```c 59 | void Dijkstra( Vertex s ) 60 | { 61 | while (1){ 62 | V = 未收录顶点中dist最小者; 63 | if ( 这样的V不存在 ) 64 | break; 65 | collected[V] = true; 66 | for ( V 的每个邻接点 W ){ 67 | if ( collected[W] == false ){ 68 | if ( dist[V]+E < dist[W] ) { 69 | dist[W] = dist[V] + E ; 70 | path[W] = V; 71 | } 72 | } 73 | } 74 | } 75 | } 76 | ``` 77 | 算法实现 78 | 邻接矩阵存储 - 有权图的单源最短路算法 79 | ```c 80 | // 返回未被收录顶点中dist最小值 81 | Vertex FindMinDist(MGraph Graph, int dist[], int collected[]){ 82 | Vertex MinV, V; 83 | int MinDist = INFINITY; 84 | 85 | for(V=0; VNv; V++){ 86 | if (collected[V] = false && dist[V]< MinDist){ /* 若V未被收录,且dist[V]更小 */ 87 | MinDist = dist[V]; 88 | MinV = V; /* 更新对应顶点 */ 89 | } 90 | 91 | } 92 | if (MinDist < INFINITY) /* 若找到最小dist */ 93 | return MinV; /* 返回对应的顶点下标 */ 94 | else return ERROR; /* 若这样的顶点不存在,返回错误标记 */ 95 | } 96 | 97 | 98 | bool Dijkstra(MGraph Graph, int dist[], int path[], Vertex S) 99 | { 100 | int collected[MaxVertexNum]; 101 | Vertex V, W; 102 | 103 | // 初始化dist[]和path[],邻接矩阵中不存在边的标记为INFINITY 104 | for(V=0; VNv; V++){ 105 | dist[V] = Graph->G[S][V]; 106 | if (dist[V]Nv; W++){ // 对图中的每个顶点W 123 | if(collected[W] == false && Graph->G[V][W]G[V][W]<0 ) /* 若有负边 */ 126 | return false; /* 不能正确解决,返回错误标记 */ 127 | 128 | /* 若收录V使得dist[W]变小 */ 129 | if ( dist[V]+Graph->G[V][W] < dist[W] ) { 130 | dist[W] = dist[V]+Graph->G[V][W]; /* 更新dist[W] */ 131 | path[W] = V; /* 更新S到W的路径 */ 132 | } 133 | } 134 | } // for循环结束, 每个V的邻接点W遍历完 135 | }// while结束 136 | return true; 137 | } 138 | ``` 139 | 140 | ## 多源最短路算法 141 | Floyd 算法 142 | ```c 143 | bool Floyd( MGraph Graph, WeightType D[][MaxVertexNum], Vertex path[][MaxVertexNum] ) 144 | { 145 | Vertex i, j, k; 146 | 147 | /* 初始化 */ 148 | for ( i=0; iNv; i++ ) 149 | for( j=0; jNv; j++ ) { 150 | D[i][j] = Graph->G[i][j]; 151 | path[i][j] = -1; 152 | } 153 | 154 | for( k=0; kNv; k++ ) 155 | for( i=0; iNv; i++ ) 156 | for( j=0; jNv; j++ ) 157 | if( D[i][k] + D[k][j] < D[i][j] ) { 158 | D[i][j] = D[i][k] + D[k][j]; 159 | if ( i==j && D[i][j]<0 ) /* 若发现负值圈 */ 160 | return false; /* 不能正确解决,返回错误标记 */ 161 | path[i][j] = k; 162 | } 163 | return true; /* 算法执行完毕,返回正确标记 */ 164 | } 165 | ``` 166 | -------------------------------------------------------------------------------- /Notes/AVL Tree.c: -------------------------------------------------------------------------------- 1 | // AVL Tree 2 | #define ElementType int 3 | 4 | typedef struct AVLNode *Position; 5 | typedef Position AVLTree; 6 | struct AVLNode 7 | { 8 | ElementType Data; 9 | AVLTree Left; 10 | AVLTree Right; 11 | int Height; 12 | }; 13 | 14 | int Max(int a, int b){ 15 | return a>b? a:b; 16 | } 17 | 18 | // 高度函数 19 | int GetHeight(AVLTree T){ 20 | int HL, HR; 21 | if(T){ 22 | HL = GetHeight(T->Left); 23 | HR = GetHeight(T->Right); 24 | T->Height = Max(HL, HR) + 1; 25 | } 26 | else return 0; 27 | return T->Height; 28 | } 29 | 30 | // 左单旋函数LL 31 | AVLTree LL(AVLTree A){ 32 | // 新结点插入在A(Root)的左孩子B的左子树中 33 | AVLTree B = A->Left; // 根变成A的左孩子B 34 | A->Left = B->Right; // A的左孩子变成B的右孩子 35 | B->Right = A; //B的右孩子变成A 36 | A->Height = Max( GetHeight(A->Left), GetHeight(A->Right)) + 1; 37 | B->Height = Max( GetHeight(B->Left), A->Height) + 1; 38 | 39 | return B; 40 | } 41 | 42 | 43 | // 右单旋函数RR 44 | AVLTree RR(AVLTree A){ 45 | // 新结点插入在A(Root)的右孩子B的右子树中 46 | AVLTree B = A->Right; 47 | A->Right = B->Left; 48 | B->Left = A; 49 | A->Height = Max( GetHeight(A->Left), GetHeight(A->Right)) + 1; 50 | B->Height = Max( GetHeight(B->Right), A->Height) + 1; 51 | 52 | return B; 53 | } 54 | 55 | 56 | // 左右双旋函数LR 57 | AVLTree LR(AVLTree A){ 58 | // 新结点插在A的左子树B的右子树C中 59 | A->Left = RR(A->Left); // 对A的左子树B做一次右单旋RR 60 | return LL(A); //再对A做一次左单旋LL,返回根节点C 61 | } 62 | 63 | 64 | // 右左双旋函数RL 65 | AVLTree RL(AVLTree A){ 66 | // 新结点插入在A(Root)的右孩子B的左子树中 67 | A->Right = LL(A->Right); // 对A的右孩子B做一次左单旋RR 68 | return RR(A); //再对A做一次右单旋LL,返回根节点C 69 | } 70 | 71 | 72 | //将X插入AVL树中,并且返回调整后的平衡树 73 | AVLTree Insert(AVLTree T, ElementType X){ 74 | if(!T) 75 | { //若插入空树,就新建包含一个结点的树 76 | T=(AVLTree)malloc(sizeof(struct AVLNode)); 77 | T->Data = X; 78 | T->Left = T->Right = NULL; 79 | T->Height = 1; 80 | } 81 | 82 | else if(X < T->Data) 83 | { 84 | T->Left = Insert(T->Left, X); // 插入左子树 85 | if((GetHeight(T->Left) - GetHeight(T->Right)) == 2) //需要做LL旋转或LR 86 | { 87 | if(X < T->Left->Data) // 新结点插入在A(Root)的左孩子的左子树中 88 | T = LL(T); 89 | else // 新结点插在A的左子树的右子树中 90 | T = LR(T); 91 | } 92 | } 93 | 94 | else if(X > T->Data) 95 | { 96 | T->Right = Insert(T->Right, X); // 插入左子树 97 | if((GetHeight(T->Right) - GetHeight(T->Left)) == 2) //需要做RR旋转或者RL 98 | { 99 | if(X > T->Right->Data) 100 | T = RR(T); // 新结点插入在A(Root)的右孩子B的右子树中 101 | else // 新结点插入在A(Root)的右孩子B的左子树中 102 | T = RL(T); 103 | } 104 | } 105 | 106 | // else T->Data == X 无需插入 107 | 108 | T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1; // 更新树的高度,左右高度的最大值+1 109 | 110 | return T; 111 | } 112 | 113 | 114 | -------------------------------------------------------------------------------- /Notes/Binary Search Tree.c: -------------------------------------------------------------------------------- 1 | // 搜索树 Binary Search Tree 2 | 3 | // 链表存储 结点 4 | typedef struct TreeNode *BinTree; 5 | typedef BinTree Position; 6 | struct TreeNode 7 | { 8 | ElementType Data; 9 | BinTree Left; 10 | BinTree Right; 11 | } 12 | 13 | // 查找 Find 14 | Position IterFind( ElementType X, BinTree BST ) { 15 | while( BST ) 16 | { 17 | if( X > BST->Data ) 18 | BST = BST->Right; /*向右子树中移动,继续查找*/ 19 | else if( X < BST->Data ) 20 | BST = BST->Left; /*向左子树中移动,继续查找*/ 21 | else /* X == BST->Data */ 22 | return BST; /*查找成功,返回结点的找到结点的地址*/ 23 | } 24 | return NULL; /*查找失败*/ 25 | } 26 | 27 | // 返回最大值(非递归法) 28 | Position FindMax( BinTree BST ) 29 | { 30 | if(BST ) // 结点不空 31 | { 32 | while( BST->Right ) // 右儿子不空 33 | BST = BST->Right; // 则往右 34 | } 35 | return BST; 36 | } 37 | 38 | // 返回最小值 (递归法) 39 | Position FindMin( BinTree BST ) 40 | { 41 | if( !BST ) return NULL;/*空的二叉搜索树,返回NULL*/ 42 | else if( !BST->Left ) 43 | return BST; /*找到最左叶结点并返回*/ 44 | else 45 | return FindMin( BST->Left ); /*沿左分支继续查找*/ 46 | } 47 | 48 | // 插入 Insert 49 | BinTree Insert( ElementType X, BinTree BST ) { 50 | if( !BST ) /*若原树为空,生成并返回一个结点的二叉搜索树*/ 51 | { 52 | BST = malloc(sizeof(struct TreeNode)); 53 | BST->Data = X; 54 | BST->Left = BST->Right = NULL; 55 | } 56 | else /*开始找要插入元素的位置*/ 57 | { 58 | if( X < BST->Data ) 59 | BST->Left = Insert( X, BST->Left); /*递归插入左子树*/ 60 | else if( X > BST->Data ) 61 | BST->Right = Insert( X, BST->Right); /*递归插入右子树*/ 62 | /* else X已经存在,什么都不做 */ 63 | } 64 | return BST; 65 | } 66 | 67 | // 删除 Delete 68 | /* 1. 删除的是叶结点 69 | 2. 删除的只有一个孩子的结点 70 | 3. 要删除的结点右左右两棵子树,则: 71 | * 右子树最小元素替代 72 | * 左子树最大元素替代 */ 73 | BinTree Delete( BinTree BST, ElementType X ) 74 | { 75 | Position Tmp; 76 | 77 | if( !BST ) 78 | printf("要删除的元素未找到"); 79 | else { 80 | if( X < BST->Data ) 81 | BST->Left = Delete( BST->Left, X ); /* 从左子树递归删除 */ 82 | else if( X > BST->Data ) 83 | BST->Right = Delete( BST->Right, X ); /* 从右子树递归删除 */ 84 | else { /* BST就是要删除的结点 */ 85 | /* 如果被删除结点有左右两个子结点 */ 86 | if( BST->Left && BST->Right ) { 87 | /* 从右子树中找最小的元素填充删除结点 */ 88 | Tmp = FindMin( BST->Right ); 89 | BST->Data = Tmp->Data; 90 | /* 从右子树中删除最小元素 */ 91 | BST->Right = Delete( BST->Right, BST->Data ); 92 | } 93 | else { /* 被删除结点有一个或无子结点 */ 94 | Tmp = BST; 95 | if( !BST->Left ) /* 只有右孩子或无子结点 */ 96 | BST = BST->Right; 97 | else /* 只有左孩子 */ 98 | BST = BST->Left; 99 | free( Tmp ); 100 | } 101 | } 102 | } 103 | return BST; 104 | } 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /Notes/Graph.c: -------------------------------------------------------------------------------- 1 | 2 | // Graph 3 | #include 4 | #include 5 | #include 6 | #define MaxVertexNum 100 7 | #define INFINITY 65535 8 | 9 | typedef int Vertex; // 用顶点下标表示顶点,为整形 10 | typedef int WeightType; // 边的权值设为int 11 | 12 | /* ********************* MGraph *******************/ 13 | typedef char DataType; 14 | 15 | 16 | // Graph struct 17 | typedef struct GNode * PtrGNode; 18 | struct GNode 19 | { 20 | int Nv; 21 | int Ne; 22 | WeightType G[MaxVertexNum][MaxVertexNum]; 23 | // DataType Data[MAX]; // 存顶点的数据 24 | }; 25 | typedef PtrGNode MGraph; 26 | 27 | // Edge struct 28 | typedef struct ENode *PtrENode; 29 | struct ENode 30 | { 31 | Vertex V1, V2; 32 | WeightType Weight; 33 | }; 34 | typedef PtrENode Edge; 35 | 36 | // 初始化有VertexNum个顶点但没有边的图 37 | MGraph CreateGraph(int VertexNum) 38 | { 39 | MGraph Graph; 40 | Vertex v,w; 41 | Graph = (MGraph)malloc(sizeof(struct GNode)); 42 | Graph->Nv = VertexNum; 43 | Graph->Ne = 0; 44 | 45 | for(v=0; vG[v][w] = 0; 48 | } 49 | } 50 | return Graph; 51 | } 52 | 53 | 54 | // 插入边 55 | void InsertEdge(MGraph Graph, Edge E){ 56 | // 插入 57 | Graph ->G[E->V1][E->V2] = E->Weight; 58 | //若是无向图,还要插入 59 | Graph->G[E->V2][E->V1] = E->Weight; 60 | } 61 | 62 | // 建图 63 | MGraph BuildGraph(){ 64 | MGraph Graph; 65 | Edge E; 66 | Vertex V; 67 | int Nv, i; 68 | 69 | scanf("%d", &Nv); 70 | Graph = CreateGraph(Nv); 71 | scanf("%d", &(Graph->Ne)); 72 | 73 | if (Graph->Ne != 0) 74 | { 75 | E = (Edge)malloc(sizeof(struct ENode)); // 创建边结点 76 | for (i=0; iNe; i++) 77 | { 78 | scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); 79 | InsertEdge(Graph, E); 80 | } 81 | } 82 | /* 如果顶点有数据的话,读入数据 83 | for (V=0; VNv; V++) 84 | scanf(" %c", &(Graph->Data[V])); 85 | */ 86 | return Graph; 87 | } 88 | 89 | // 用全局变量建图 90 | int G[MaxVertexNum][MaxVertexNum], Nv, Ne; 91 | void NBuildGraph() 92 | { 93 | int i,j,v1,v2,w; 94 | scanf("%d", &Nv); 95 | /* CreateGraph */ 96 | for (i=0; iNv = VertexNum; 154 | Graph->Ne = 0; 155 | 156 | for(v=0; vNv; v++) 157 | Graph->G[v].FirstEdge = NULL; // 每一个顶点v的FirstEdge都是空的, 编号从0到 Graph->Nv-1 158 | return Graph; 159 | } 160 | 161 | // 插入一条边 162 | void InsertEdge (LGraph Graph, Edge E) /* 插入边 */ 163 | { 164 | PtrAdjVNode NewNode; 165 | 166 | /* 为V2建立新的邻接点 */ 167 | NewNode = (PtrAdjVNode)malloc(sizeof(struct AdjVNode)); 168 | NewNode->AdjV = E->V2; 169 | NewNode->Weight = E->Weight; 170 | /* 将V2插入V1的表头, 在头上插入 */ 171 | NewNode->Next = Graph->G[E->V1].FirstEdge; 172 | Graph->G[E->V1].FirstEdge = NewNode; 173 | 174 | /********** 若是无向图,还要插入边 **********/ 175 | /* 为V1建立新的邻接点 */ 176 | NewNode = (PtrAdjVNode)malloc(sizeof(struct AdjVNode)); 177 | NewNode->AdjV = E->V1; 178 | NewNode->Weight = E->Weight; 179 | /* 将V1插入V2的表头 */ 180 | NewNode->Next = Graph->G[E->V2].FirstEdge; 181 | Graph->G[E->V2].FirstEdge = NewNode; 182 | } 183 | 184 | 185 | // 建图 186 | LGraph BuildGraph(){ 187 | LGraph Graph; 188 | Edge E; 189 | Vertex V; 190 | int Nv, i; 191 | 192 | scanf("%d", &Nv); 193 | Graph = CreateGraph(Nv); 194 | 195 | scanf("%d", &(Graph->Ne)); 196 | if (Graph->Ne != 0) 197 | { 198 | E = (Edge)malloc(sizeof(struct ENode)); // 创建边结点 199 | for (i=0; iNe; i++) 200 | { 201 | /* 读入边,格式为 起点 终点 权重 */ 202 | scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); 203 | InsertEdge(Graph, E); 204 | } 205 | } 206 | /* 如果顶点有数据的话,读入数据 207 | for (V=0; VNv; V++) 208 | scanf(" %c", &(Graph->Data[V])); 209 | */ 210 | return Graph; 211 | } 212 | 213 | 214 | 215 | /* ********************* DFS *******************/ 216 | // 邻接表深度优先DFS遍 217 | bool Visited[MaxVertexNum] = {false}; // 全局变量初始化为false 218 | 219 | void Visit( Vertex V ) 220 | { 221 | printf("正在访问顶点%d\n", V); 222 | } 223 | 224 | void DFS( LGraph Graph, Vertex V, void (*Visit)(Vertex) ) 225 | { 226 | PtrAdjVNode W; 227 | Visit( V ); 228 | Visited[V] = true; 229 | /* 对V的每个邻接点W->AdjV */ 230 | for( W=Graph->G[V].FirstEdge; W; W=W->Next ) 231 | if ( !Visited[W->AdjV] ) 232 | DFS( Graph, W->AdjV, Visit ); 233 | } 234 | 235 | // 邻接矩阵深度优先DFS遍 236 | bool IsEdge(MGraph Graph, Vertex V, Vertex W){ 237 | return Graph->G[V][W]AdjV */ 246 | for( W=0; WNv; W++ ) // 对图中的每个顶点遍历 247 | if ( !Visited[W] && IsEdge(Graph, V, W)) 248 | DFS( Graph, W, Visit ); 249 | } 250 | 251 | /* ********************* BFS *******************/ 252 | // // 邻接矩阵深度优先BFS遍 253 | bool IsEdge( MGraph Graph, Vertex V, Vertex W ) 254 | { 255 | return Graph->G[V][W]Nv; W++ ) /* 对图中的每个顶点W */ 272 | /* 若W是V的邻接点并且未访问过 */ 273 | if ( !Visited[W] && IsEdge(Graph, V, W) ) { 274 | Visit( W ); 275 | Visited[W] = true; /* 标记W已访问 */ 276 | AddQ(Q, W); /* W入队列 */ 277 | } 278 | } /* while结束*/ 279 | } 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | -------------------------------------------------------------------------------- /Notes/Heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define MaxSize 101 5 | #define ElementType int 6 | #define ERROR 999 7 | 8 | /* ***************************** MaxHeap ***********************/ 9 | 10 | // struct 11 | typedef struct HNode *MaxHeap; 12 | struct HNode { 13 | ElementType *Data; // 存储堆元素的数组 14 | int Size; // 堆的当前元素的个数 15 | int Capacity; // 堆的最大容量 16 | }; 17 | 18 | 19 | 20 | // Create a heap 21 | MaxHeap CreateHeap(int Maxsize) 22 | { 23 | MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode)); 24 | H->Data = (ElementType*)malloc((MaxSize+1) * sizeof(ElementType)); // 因为这里是一个数组,需要分配空间 25 | H->Size = 0; // 当前是空的 26 | H->Capacity = MaxSize; // 堆的最大容量 27 | H->Data[0] = MaxSize; /* 定义“哨兵”为大于堆中所有可能元素的值,便于以后操作 */ 28 | return H; 29 | } 30 | 31 | // Full 32 | bool IsHeapFull(MaxHeap H){ 33 | return (H->Size == H->Capacity); 34 | } 35 | 36 | // Empty 37 | bool IsHeapEmpty(MaxHeap H){ 38 | return (H->Size == 0); 39 | } 40 | 41 | // Insert a node to a maxheap 42 | void InsertMaxHeap(MaxHeap H, ElementType item) 43 | { 44 | int i; 45 | if (IsHeapFull(H)){ 46 | printf("FULL\n"); 47 | return; 48 | } 49 | i = ++H->Size; // H->Size++; i = H->Size; 把新增元素放在末尾H->Size++的位置上 50 | for(; H->Data[i/2] < item; i/=2){ // 其父节点小于它 51 | H->Data[i] = H->Data[i/2]; // 把它的父节点,向下过滤, 插入的item向上过滤 52 | } 53 | // 当它的父结点[i/2]比它大的时候, 跳出循环 54 | H->Data[i] = item; // 填上item 55 | } 56 | 57 | 58 | 59 | // Delete the root(the maximum) from a maxheap 60 | ElementType DeleteMax(MaxHeap H) 61 | { 62 | int parent, child; 63 | ElementType MaxItem, temp; 64 | if(IsHeapEmpty(H)){ 65 | printf("Empty\n"); 66 | return ERROR; 67 | } 68 | 69 | MaxItem = H->Data[1]; // 取出最大值 70 | /* 用最大堆中最后一个元素从根节点开始向上过滤下层节点 */ 71 | temp = H->Data[H->Size]; // 把堆中最后一个值,交给temp 72 | H->Size--; 73 | 74 | for(parent=1; parent*2 <= H->Size; parent=child) 75 | { 76 | child = parent*2; // 左儿子 77 | 78 | /* child=左右儿子中大的那个, 当右儿子存在,且右儿子的值比左儿子大时,让child=右儿子 */ 79 | if((child!= H->Size) && 80 | (H->Data[child] < H->Data[child+1])) 81 | child++; 82 | 83 | /* 当temp比child的值大时跳出循环 */ 84 | if (temp >= H->Data[child]) 85 | break; 86 | else 87 | H->Data[parent] = H->Data[child]; //当parent < child,这个parent位置上变为child的值 88 | } 89 | H->Data[parent] = temp; 90 | return MaxItem; 91 | } 92 | 93 | 94 | // 堆的排序(建立最大堆) 把一个完全二叉树调整为最大堆 95 | void PercDown( MaxHeap H, int p) 96 | {// 下滤函数, 将Maxheap中以H->Data[p]为根的子堆调整为最大堆 97 | int parent, child; 98 | ElementType X; 99 | 100 | X = H->Data[p]; // 取出根节点的值 101 | for(parent = p; parent*2 <= H->Size; parent = child) 102 | { 103 | child = parent * 2; 104 | if( (child != H->Size) && (H->Data[child] < H->Data[child+1])) 105 | { 106 | child++; 107 | } 108 | if (X > H->Data[child]) 109 | break; 110 | else // 将X下滤 111 | H->Data[parent] = H->Data[child]; 112 | } 113 | H->Data[parent] = X; 114 | } 115 | 116 | void BuildMaxHeap(MaxHeap H){ // 调整H->Data[]中的元素,使满足最大堆的有序新,这里假设H->Size个元素已经存在H->Data中了 117 | int i; 118 | for(i = H->Size/2; i>0; i--) 119 | {// 从最后一个结点的父节点(Size/2)开始,到根节点(1)为止 120 | PercDown(H, i); 121 | } 122 | } 123 | 124 | 125 | 126 | /* *************************** MinHeap ************************/ 127 | 128 | // 数据结构 129 | typedef struct HNode *MinHeap; 130 | struct HNode { 131 | ElementType *Data; // 存储堆元素的数组 132 | int Size; // 堆的当前元素的个数 133 | int Capacity; // 堆的最大容量 134 | }; 135 | 136 | 137 | // Create a heap 138 | MinHeap CreateHeap(void) 139 | { 140 | MinHeap H = (MinHeap)malloc(sizeof(struct HNode)); 141 | H->Data = (ElementType*)malloc((MaxSize+1) * sizeof(ElementType)); // 因为这里是一个数组,需要分配空间 142 | H->Size = 0; // 当前是空的 143 | H->Capacity = MaxSize; // 堆的最大容量 144 | H->Data[0] = - INFINITY; /* 定义“哨兵”为小于堆中所有可能元素的值,便于以后操作 */ 145 | return H; 146 | } 147 | 148 | // Full 149 | bool IsHeapFull(MinHeap H){ 150 | return (H->Size == H->Capacity); 151 | } 152 | 153 | // Empty 154 | bool IsHeapEmpty(MinHeap H){ 155 | return (H->Size == 0); 156 | } 157 | 158 | // Insert a node to a maxheap 159 | void InsertMinHeap(MinHeap H, ElementType item) 160 | { 161 | int i; 162 | if (IsHeapFull(H)){ 163 | printf("FULL\n"); 164 | return; 165 | } 166 | i = ++H->Size; // H->Size++; i = H->Size; 把新增元素放在末尾H->Size++的位置上 167 | if (i > 1){ 168 | for(; H->Data[i/2] > item; i/=2){ // 其父节点大于它 169 | H->Data[i] = H->Data[i/2]; // 把它的父节点,向下过滤, 插入的item向上过滤 170 | } 171 | } 172 | // 当它的父结点[i/2]比它小的时候, 符合条件,跳出循环 173 | H->Data[i] = item; // 填上item 174 | } 175 | 176 | 177 | 178 | // Delete the root(the minimum) from a minheap 179 | ElementType DeleteMin(MinHeap H) 180 | { 181 | int parent, child; 182 | ElementType MinItem, temp; 183 | if(IsHeapEmpty(H)){ 184 | printf("Empty\n"); 185 | return ERROR; 186 | } 187 | 188 | MinItem = H->Data[1]; // 取出最小值 189 | /* 用最小堆中最后一个元素从根节点开始向上过滤下层节点 */ 190 | temp = H->Data[H->Size]; // 把堆中最后一个值,交给temp 191 | H->Size--; 192 | 193 | for(parent=1; parent*2 <= H->Size; parent=child) 194 | { 195 | child = parent*2; // 左儿子 196 | 197 | /* child=左右儿子中小的那个, 当右儿子存在,且右儿子的值比左儿子小时,让child=右儿子 */ 198 | if((child!= H->Size) && 199 | (H->Data[child] > H->Data[child+1])) 200 | child++; 201 | 202 | /* 当temp比child的值小时跳出循环 */ 203 | if (temp <= H->Data[child]) 204 | break; 205 | else 206 | H->Data[parent] = H->Data[child]; //当parent < child,这个parent位置上变为child的值 207 | } 208 | H->Data[parent] = temp; 209 | return MinItem; 210 | } 211 | 212 | 213 | // 堆的排序(建立最小堆) 把一个完全二叉树调整为最小堆 214 | void PercDown( MinHeap H, int p) 215 | {// 下滤函数, 将Minheap中以H->Data[p]为根的子堆调整为最小堆 216 | int parent, child; 217 | ElementType X; 218 | 219 | X = H->Data[p]; // 取出根节点的值 220 | for(parent = p; parent*2 <= H->Size; parent = child) 221 | { 222 | child = parent * 2; 223 | if( (child != H->Size) && (H->Data[child] > H->Data[child+1])) 224 | { 225 | child++; 226 | } 227 | if (X <= H->Data[child]) 228 | break; 229 | else // 将X下滤 230 | H->Data[parent] = H->Data[child]; 231 | } 232 | H->Data[parent] = X; 233 | } 234 | 235 | void BuildMinHeap(MinHeap H){ // 调整H->Data[]中的元素,使满足最小堆的有序新,这里假设H->Size个元素已经存在H->Data中了 236 | int i; 237 | for(i = H->Size/2; i>0; i--) 238 | {// 从最后一个结点的父节点(Size/2)开始,到根节点(1)为止 239 | PercDown(H, i); 240 | } 241 | } 242 | 243 | /* ********************************************************* */ 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | -------------------------------------------------------------------------------- /Notes/HuffmanTree.c: -------------------------------------------------------------------------------- 1 | //05-树9 Huffman Codes 2 | #include 3 | #include 4 | #include 5 | #define MaxSize 1001 6 | #define ElementType HuffmanTree 7 | #define ERROR NULL 8 | #define INFINITY 1000 9 | 10 | /* ********* HuffmanTree ********************/ 11 | // 数据结构 12 | typedef struct HTNode *HuffmanTree; 13 | struct HTNode{ 14 | int Weight; // 结点的权值 15 | HuffmanTree Left; 16 | HuffmanTree Right; 17 | }; 18 | 19 | /* ********* MinHeap ************************/ 20 | 21 | // 数据结构 22 | typedef struct HNode *MinHeap; 23 | struct HNode { 24 | ElementType *Data; // 存储堆元素的数组 25 | int Size; // 堆的当前元素的个数 26 | int Capacity; // 堆的最大容量 27 | }; 28 | 29 | HuffmanTree mini; 30 | 31 | 32 | // Create a heap 33 | MinHeap CreateHeap(void) 34 | { 35 | MinHeap H = (MinHeap)malloc(sizeof(struct HNode)); 36 | H->Data = (ElementType*)malloc((MaxSize+1) * sizeof(ElementType)); // 因为这里是一个数组,需要分配空间 37 | H->Size = 0; // 当前是空的 38 | H->Capacity = MaxSize; // 堆的最大容量 39 | H->Data[0] = mini; /* 定义“哨兵”为小于堆中所有可能元素的值,便于以后操作 */ 40 | return H; 41 | } 42 | 43 | // Full 44 | bool IsHeapFull(MinHeap H){ 45 | return (H->Size == H->Capacity); 46 | } 47 | 48 | // Empty 49 | bool IsHeapEmpty(MinHeap H){ 50 | return (H->Size == 0); 51 | } 52 | 53 | // Insert a node to a minheap 54 | void InsertMinHeap(MinHeap H, ElementType item) 55 | { 56 | int i; 57 | if (IsHeapFull(H)){ 58 | printf("FULL\n"); 59 | return; 60 | } 61 | i = ++H->Size; // H->Size++; i = H->Size; 把新增元素放在末尾H->Size++的位置上 62 | 63 | // if (i > 1){ // 如果哨兵设置为NULL的话,在这里改一下, 当i=1的时候,直接让Data[1] = item; 64 | for(; H->Data[i/2]->Weight > item->Weight; i/=2){ // 其父节点大于它 65 | H->Data[i] = H->Data[i/2]; // 把它的父节点,向下过滤, 插入的item向上过滤 66 | } 67 | // } 68 | // 当它的父结点[i/2]比它小的时候, 符合条件,跳出循环 69 | H->Data[i] = item; // 填上item 70 | } 71 | 72 | 73 | 74 | // Delete the root(the minimum) from a minheap 75 | ElementType DeleteMin(MinHeap H) 76 | { 77 | int parent, child; 78 | ElementType MinItem, temp; 79 | if(IsHeapEmpty(H)){ 80 | printf("Empty\n"); 81 | return ERROR; 82 | } 83 | 84 | MinItem = H->Data[1]; // 取出最小值 85 | /* 用最小堆中最后一个元素从根节点开始向上过滤下层节点 */ 86 | temp = H->Data[H->Size]; // 把堆中最后一个值,交给temp 87 | H->Size--; 88 | 89 | for(parent=1; parent*2 <= H->Size; parent=child) 90 | { 91 | child = parent*2; // 左儿子 92 | 93 | /* child=左右儿子中小的那个, 当右儿子存在,且右儿子的值比左儿子小时,让child=右儿子 */ 94 | if((child!= H->Size) && 95 | (H->Data[child]->Weight > H->Data[child+1]->Weight)) 96 | child++; 97 | 98 | /* 当temp比child的值小时跳出循环 */ 99 | if (temp->Weight <= H->Data[child]->Weight) 100 | break; 101 | else 102 | H->Data[parent] = H->Data[child]; //当parent < child,这个parent位置上变为child的值 103 | } 104 | H->Data[parent] = temp; 105 | return MinItem; 106 | } 107 | 108 | 109 | // 堆的排序(建立最小堆) 把一个完全二叉树调整为最小堆 110 | void PercDown( MinHeap H, int p) 111 | {// 下滤函数, 将Minheap中以H->Data[p]为根的子堆调整为最小堆 112 | int parent, child; 113 | ElementType X; 114 | 115 | X = H->Data[p]; // 取出根节点的值 116 | for(parent = p; parent*2 <= H->Size; parent = child) 117 | { 118 | child = parent * 2; 119 | if( (child != H->Size) && (H->Data[child]->Weight > H->Data[child+1]->Weight)) 120 | { 121 | child++; 122 | } 123 | if (X->Weight <= H->Data[child]->Weight) 124 | break; 125 | else // 将X下滤 126 | H->Data[parent] = H->Data[child]; 127 | } 128 | H->Data[parent] = X; 129 | } 130 | 131 | void BuildMinHeap(MinHeap H){ // 调整H->Data[]中的元素,使满足最小堆的有序新,这里假设H->Size个元素已经存在H->Data中了 132 | int i; 133 | for(i = H->Size/2; i>0; i--) 134 | {// 从最后一个结点的父节点(Size/2)开始,到根节点(1)为止 135 | PercDown(H, i); 136 | } 137 | } 138 | 139 | 140 | 141 | /* ********* HuffmanTree *************/ 142 | // 数据结构 143 | // typedef struct HTNode *HuffmanTree; 144 | // struct HTNode{ 145 | // int Weight; // 结点的权值 146 | // HuffmanTree Left; 147 | // HuffmanTree Right; 148 | // }; 149 | 150 | // 初始化 151 | HuffmanTree CreateHuffman(){ 152 | HuffmanTree HFT; 153 | HFT = (HuffmanTree) malloc(sizeof(struct HTNode)); 154 | HFT->Left = NULL; 155 | HFT->Right = NULL; 156 | return HFT; 157 | } 158 | 159 | // Create 160 | HuffmanTree Huffman(MinHeap H) 161 | { // 这里最小堆的元素类型ElementType为HuffmanTree 162 | // 假设 H->Size个权值已经存在在 H->Data[]->Weight里了 163 | int i, N; 164 | HuffmanTree T; 165 | BuildMinHeap(H); // 将H->Data[]按照权重调整为最小堆 166 | N = H->Size; 167 | for(i=1; i < N; i++) // 做size-1次合并 168 | { 169 | T = (HuffmanTree)malloc(sizeof(struct HTNode)); // 建立新结点 170 | 171 | T->Left = DeleteMin(H);/*从最小堆中删除一个结点,作为新T的左子结点*/ 172 | T->Right = DeleteMin(H); 173 | /*计算新权值*/ 174 | T->Weight = (T->Left->Weight) + (T->Right->Weight); 175 | InsertMinHeap( H, T ); /*将新T插入最小堆*/ 176 | } 177 | T = DeleteMin(H); // 最小堆中的最后一个元素就是指向Huffman树根节点的指针 178 | return T; 179 | } 180 | /* ************************************* */ 181 | 182 | int main(int argc, char const *argv[]) 183 | { 184 | int N, i,f[MaxSize]; 185 | char c[MaxSize]; 186 | HuffmanTree HFT; 187 | // 设置哨兵,创建最小堆 188 | mini = CreateHuffman(); 189 | mini->Weight = - INFINITY; 190 | MinHeap H = CreateHeap(); 191 | 192 | scanf("%d", &N); 193 | H->Size = N; 194 | 195 | 196 | for(i=1; i<=N; i++){ 197 | getchar(); // 读掉空格和回车 198 | scanf("%c %d", &c[i], &f[i]); 199 | HFT = (HuffmanTree) malloc(sizeof(struct HTNode)); 200 | HFT->Left = NULL; 201 | HFT->Right = NULL; 202 | HFT->Weight = f[i]; 203 | H->Data[i] = HFT; 204 | } 205 | 206 | // for(i=1; i<=N; i++){ 207 | // printf("%d ", H->Data[i]->Weight); 208 | // } 209 | // printf("\n"); 210 | 211 | HFT = Huffman(H); // 获得根节点的weight值 212 | 213 | printf("%d\n", HFT->Weight); 214 | 215 | return 0; 216 | } 217 | 218 | 219 | -------------------------------------------------------------------------------- /Notes/MST.c: -------------------------------------------------------------------------------- 1 | // minimum spanning tree MST 最小生成树 2 | # define ERROR -1; 3 | #include 4 | #include 5 | #include 6 | #define MaxVertexNum 100 7 | #define INFINITY 65535 8 | 9 | typedef int Vertex; 10 | typedef char DataType; 11 | typedef int WeightType; 12 | 13 | /* ********************* Prim ********************* */ 14 | /* 返回未被收录顶点中dist最小者 */ 15 | Vertex FindMinDist(MGraph Graph, WeightType dist[]){ 16 | Vertex MinV, V; 17 | WeightType MinDist = INFINITY; 18 | 19 | for(V=0;, V< Graph->Nv; V++){ 20 | if (dist[v] != 0 && dist[V] < MinDist) /* 若V未被收录,且dist[V]更小 */ 21 | { 22 | MinDist = dist[V]; 23 | MinV = V; 24 | } 25 | } 26 | if (MinDist < INFINITY) 27 | return MinV; 28 | else 29 | return ERROR; 30 | } 31 | 32 | 33 | // 用邻接矩阵存储图,用邻接表存储最小生成树(因为是稀疏图) 34 | int Prim(MGraph Graph, LGraph MST){ // 返回最小权重和 35 | WeightType dist[MaxVertexNum], TotalWeight; 36 | Vertex parent[MaxVertexNum], V, W; 37 | int VCount; 38 | Edge E; 39 | 40 | // 初始化, 默认起点下标为0, 无边定义为INFINITY 41 | for(V=0; VNv; V++){ 42 | dist[V] = Graph->G[0][V]; 43 | parent[V] = 0; // 暂定所有顶点的父节点为0 44 | } 45 | 46 | TotalWeight = 0; 47 | VCount = 0; // 初始收录的定点数 48 | 49 | // 创建MST的邻接表,包含所有顶点,没有边 50 | MST = CreateGraph(Graph->Nv); 51 | // 创建空的边结点 52 | E = (Edge)mallo(sizeof(struct ENode)); 53 | 54 | // 将起点0收录MST 55 | dist[0] = 0; 56 | VCount++; 57 | parent[0] = -1; // 当前树根是起点0 58 | 59 | while(1){ 60 | V = FindMinDist(Graph, dist); /* V = 未被收录顶点中dist最小者 */ 61 | if (V == ERROR) 62 | break; 63 | 64 | /* 将V及相应的边收录进MST */ 65 | E->V1 = parent[V]; 66 | E->V2 = V; 67 | E->Weight = dist[V]; 68 | InsertEdge(MST, E); 69 | TotalWeight += dist[V]; 70 | dist[V] = 0; 71 | VCount++; 72 | 73 | for(W=0; WNv; W++){ 74 | if(dist[W] != 0 && Graph->G[V][W] < INFINITY){. /* 若W是V的邻接点并且未被收录 */ 75 | if (Graph->G[V][W] < dist[W]) /* 若收录V使得dist[W]变小 */ 76 | { 77 | dist[W] = Graph->G[V][W]; /* 更新dist[W] */ 78 | parent[W] = V;/* 更新树 */ 79 | } 80 | } 81 | } 82 | }/* while结束*/ 83 | if (VCount < Graph->Nv) 84 | { 85 | TotalWeight = ERROR; 86 | } 87 | return TotalWeight; /* 算法执行完毕,返回最小权重和或错误标记 */ 88 | 89 | } 90 | 91 | 92 | 93 | /* ********************* Kruskal ********************* */ 94 | typedef Vertex ElementType; // 默认元素用非负整数表示 95 | typedef Vertex SetName; // 用根节点下标作为结合名称 96 | typedef ElementType SetType[MaxVertexNum]; 97 | 98 | // 并查集 99 | // 初始化全为-1 100 | void InitializeVSet(SetType S, int N){ 101 | ElementType X; 102 | for (X=0; X S[Root2]){ 108 | S[Root1] += S[Root2]; 109 | S[Root2] = Root1; 110 | } 111 | else{ 112 | S[Root2] += S[Root1]; 113 | S[Root1] = Root2; 114 | } 115 | } 116 | 117 | SetName Find(SetType S, ElementType X){ 118 | if(S[X] < 0) // 找到集合的根 119 | return X; 120 | else 121 | return S[X] = Find(S,S[X]); 122 | } 123 | 124 | bool CheckCycle(SetType VSet, Vertex V1, Vertex V2){ 125 | Vertex Root1, Root2; 126 | Root1 = Find(VSet, V1); 127 | Root2 = Find(VSet, V2); 128 | 129 | if (Root1 == Root2) 130 | return false; 131 | else{ 132 | Union(VSet, Root1, Root2); 133 | return true; 134 | } 135 | 136 | } 137 | 138 | 139 | // 边的最小堆 140 | // 将N个元素的边数组以 ESet[p]为根的子堆调整为关于Weight的最小堆 141 | void PercDown(Edge ESet, int p, int N){ 142 | // 直接用数组,不用heap结构了 143 | int Parent, Child; 144 | struct ENode X; 145 | 146 | X =ESet[p]; 147 | for( Parent=p; (Parent*2+1) ESet[Child+1].Weight) ) 150 | Child++; 151 | if( X.Weight <= ESet[Child].Weight ) 152 | break; 153 | else /* 下滤X */ 154 | ESet[Parent] = ESet[Child]; 155 | } 156 | ESet[Parent] = X; 157 | } 158 | 159 | /* 将图的边存入数组ESet,并且初始化为最小堆 */ 160 | void InitializeESet(LGraph Graph, Edge ESet){ 161 | Vertex V; 162 | PtrAdjVNode W; 163 | int ECount = 0; 164 | 165 | /* 将图的边存入数组ESet */ 166 | for(V=0; VNv; V++){ 167 | for(W=Graph->G[V].FirstEdge; W; W = W->Next){ 168 | if (V < W->AdjV){ /* 避免重复录入无向图的边,只收V1AdjV; 171 | ESet[ECount].Weight = W->Weight; 172 | ECount++; 173 | } 174 | } 175 | } 176 | /* 调整为最小堆 从最后一个结点的父节点(Size/2)开始,到根节点(1)为止*/ 177 | for ( ECount=Graph->Ne/2; ECount>=0; ECount-- ) 178 | PercDown( ESet, ECount, Graph->Ne ); 179 | } 180 | 181 | void Swap(struct ENode *a, struct ENode *b){ 182 | struct ENode *c; 183 | c = a; 184 | a = b; 185 | b = c; 186 | } 187 | 188 | /* 给定当前堆的大小CurrentSize,将当前最小边位置弹出并调整堆 */ 189 | int GetEdge(Edge ESet, int CurrentSize){ 190 | Swap(&ESet[0], &ESet[CurrentSize-1]); /* 将最小边与当前堆的最后一个位置的边交换 */ 191 | PercDown( ESet, 0, CurrentSize-1 ); /* 将剩下的边继续调整成最小堆 */ 192 | 193 | return CurrentSize -1; /* 返回最小边所在位置 */ 194 | } 195 | 196 | 197 | int Kruskal(LGraph Graph, LGraph MST){ 198 | WeightType TotalWeight; 199 | int ECount, NextEdeg; 200 | SetType VSet; // 顶点数组 201 | Edge ESet; // 边数组 202 | 203 | InitializeVSet(VSet, Graph->Nv); // 初始化顶点并查集 204 | ESet = (Edge)malloc(sizeof(struct ENode) * Graph->Ne); // 分配边数组空间 205 | InitializeESet(Graph, ESet); // 初始化边的最小堆 206 | 207 | // 创建MSV图 208 | MST = CreateGraph(Graph->Nv); 209 | TotalWeight = 0; 210 | ECount = 0; 211 | 212 | NextEdeg = Graph->Ne; // 原始边集合的规模 213 | while(ECount < Graph->Nv -1 ){ // 当收集的边小于顶点数-1时 214 | NextEdeg = GetEdge(ESet, NextEdeg); 215 | if (NextEdeg < 0) // 边集已经空 216 | break; 217 | if(CheckCycle(VSet, ESet[NextEdeg].V1, ESet[NextEdeg].V2)) // 如果不构成回路 218 | { 219 | // 插入边到MST中 220 | InsertEdge(MST, ESet + NextEdeg); // 相当于 &ESet[NextEdge] 221 | TotalWeight += ESet[NextEdeg].Weight; 222 | ECount++; 223 | } 224 | }// while循环结束 225 | if (ECount < Graph->Nv-1) 226 | TotalWeight = -1; // 设置错误标志 227 | 228 | return TotalWeight; 229 | } 230 | 231 | 232 | -------------------------------------------------------------------------------- /Notes/Queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define MaxSize 101 5 | #define ElementType int 6 | #define ERROR 999 7 | 8 | 9 | /**************** Queue ******************/ 10 | struct QNode { 11 | ElementType *Data; 12 | int rear; 13 | int front; 14 | }; 15 | typedef struct QNode *Queue; 16 | 17 | // 创建队 18 | Queue CreateQueue(void) 19 | { 20 | Queue Q = (Queue)malloc(sizeof(struct QNode)); 21 | Q->Data = (ElementType*)malloc(MaxSize * sizeof(ElementType)); 22 | Q->front = Q->rear = 0; 23 | return Q; 24 | } 25 | 26 | // 空 27 | bool IsEmpty(Queue Q) 28 | { 29 | return(Q->front == Q->rear); 30 | } 31 | 32 | // 满 33 | bool IsFull(Queue Q) 34 | { 35 | return ((Q->rear+1) % MaxSize == Q->front ); 36 | } 37 | 38 | // 入队 39 | void AddQ( Queue PtrQ, ElementType item) { 40 | // if (IsFull(Q)) 41 | if ( (PtrQ->rear+1) % MaxSize == PtrQ->front ) 42 | { 43 | printf("队列满"); 44 | return; 45 | } 46 | PtrQ->rear = (PtrQ->rear + 1)% MaxSize; 47 | PtrQ->Data[PtrQ->rear] = item; 48 | } 49 | 50 | // 出队 51 | ElementType DeleteQ ( Queue PtrQ ) // front和rear相同 52 | { 53 | // if (IsEmpty(Q)) 54 | if ( PtrQ->front == PtrQ->rear ) 55 | { 56 | printf("队列空"); 57 | return ERROR; 58 | } 59 | else 60 | { 61 | PtrQ->front = (PtrQ->front+1)% MaxSize; // front往后移一位指向第一个元素 62 | return PtrQ->Data[PtrQ->front]; 63 | } 64 | } 65 | 66 | /* *********************************** */ 67 | 68 | -------------------------------------------------------------------------------- /Notes/Shortest path.c: -------------------------------------------------------------------------------- 1 | // 无权图的单源最短路 类似于BFS 2 | /* dist[W]: S到W的最短距离, 初始化为-1; 3 | path[W]: S到W的路上, W的父顶点, 初始化为-1' 4 | */ 5 | void Unweighted(LGraph Graph, int dist[], int path[], Vertex S){ 6 | Queue Q; 7 | Vertex V; 8 | PtrAdjVNode W; 9 | 10 | Q = CreateQueue(Graph->Nv); // 创建空队列,MaxSize为外部定义的常数 11 | dist[S] = 0; // 初始化源点 12 | AddQ(Q, S); 13 | 14 | while (IsEmpty(Q)) 15 | { 16 | V = DeleteQ(Q); 17 | for( W = Graph.G[V].FirstEdge; W; W=W->Next) // 对V的每个邻接点W->AdjV 18 | if (dist[W->AdjV] == -1)// W->AdjV 未被访问过 19 | { 20 | dist[W->AdjV] =dist[V] + 1; /* W->AdjV到S的距离更新 */ 21 | path[W->AdjV] = V; /* 将V记录在S到W->AdjV的路径上 */ 22 | AddQ(Q, W->AdjV); 23 | } 24 | } 25 | } 26 | 27 | 28 | // 有权图的单源最短路 Dijkstra算法 29 | 30 | /* 返回未被收录顶点中dist最小值 */ 31 | Vertex FindMinDist(MGraph Graph, int dist[], int collected[]){ 32 | Vertex MinV, V; 33 | int MinDist = INFINITY; 34 | 35 | for(V=0; V < Graph->Nv; V++){ 36 | if (collected[V] == false && dist[V]< MinDist){ /* 若V未被收录,且dist[V]更小 */ 37 | MinDist = dist[V]; 38 | MinV = V; /* 更新对应顶点 */ 39 | } 40 | } 41 | if (MinDist < INFINITY) /* 若找到最小dist */ 42 | return MinV; /* 返回对应的顶点下标 */ 43 | else 44 | return ERROR; /* 若这样的顶点不存在,返回错误标记 */ 45 | } 46 | 47 | 48 | bool Dijkstra(MGraph Graph, int dist[], int path[], Vertex S) 49 | { 50 | int collected[MaxVertexNum]; 51 | Vertex V, W; 52 | 53 | // 初始化dist[], path[]和collected[],邻接矩阵中不存在边的标记为INFINITY 54 | for(V=0; VNv; V++){ 55 | dist[V] = Graph->G[S][V]; 56 | if (dist[V] < INFINITY) // S到V有直接路径 57 | path[V] = S; 58 | else 59 | path[V] = -1; 60 | collected[V] = false; 61 | } 62 | // 先将起点收入到集合中 63 | dist[S] = 0; 64 | collected[S] = true; 65 | 66 | while(1) 67 | { 68 | V = FindMinDist(Graph, dist, collected); /* V = 未被收录顶点中dist最小者 */ 69 | if (V == ERROR) /* 若这样的V已经不存在 */ 70 | break; 71 | collected[V] = true; 72 | for(W=0; W < Graph->Nv; W++){ // 对图中的每个顶点W 73 | if(collected[W] == false && Graph->G[V][W] < INFINITY) // W未被访问,且边存在 74 | { 75 | if ( Graph->G[V][W]<0 ) /* 若有负边 */ 76 | return false; /* 不能正确解决,返回错误标记 */ 77 | 78 | /* 若收录V使得dist[W]变小 */ 79 | if ( dist[V]+ Graph->G[V][W] < dist[W] ) { 80 | dist[W] = dist[V] + Graph->G[V][W]; /* 更新dist[W] */ 81 | path[W] = V; /* 更新S到W的路径 */ 82 | } 83 | } 84 | } // for循环结束, 每个V的邻接点W遍历完 85 | }// while结束 86 | return true; 87 | } 88 | 89 | 90 | // 多源最短路 Floyd算法 91 | /* D[i][j]: Vi 到 Vj的最短路径, 初始值为Graph 92 | path[i][j]: Vi到Vj的最短路径上Vj的父顶点 93 | */ 94 | bool Floyd( MGraph Graph, WeightType D[][MaxVertexNum], Vertex path[][MaxVertexNum] ) 95 | { 96 | Vertex i, j, k; 97 | 98 | /* 初始化 */ 99 | for ( i=0; iNv; i++ ) 100 | for( j=0; j < Graph->Nv; j++ ) { 101 | D[i][j] = Graph->G[i][j]; 102 | path[i][j] = -1; 103 | } 104 | 105 | for( k=0; kNv; k++ ) 106 | for( i=0; iNv; i++ ) 107 | for( j=0; jNv; j++ ) 108 | if( D[i][k] + D[k][j] < D[i][j] ) { 109 | D[i][j] = D[i][k] + D[k][j]; 110 | if ( i==j && D[i][j]<0 ) /* 若发现负值圈 */ 111 | return false; /* 不能正确解决,返回错误标记 */ 112 | path[i][j] = k; 113 | } 114 | return true; 115 | } 116 | 117 | 118 | -------------------------------------------------------------------------------- /Notes/Stack.c: -------------------------------------------------------------------------------- 1 | 2 | #include "stack.h" 3 | 4 | /**************** Stack ******************/ 5 | 6 | typedef struct SNode *Stack; //结构指针 7 | struct SNode{ 8 | ElementType *Data; //数组 9 | int Top; // 栈顶位置的数组下标 10 | }; 11 | 12 | 13 | // 创建堆栈 14 | Stack CreateStack(void) 15 | { 16 | Stack S = (Stack)malloc(sizeof(struct SNode)); 17 | S->Data = (ElementType*)malloc(MaxSize* sizeof(ElementType)); 18 | S->Top = -1; 19 | 20 | return S; 21 | } 22 | 23 | // 入栈 24 | void Push( Stack PtrS, ElementType item ) // stack这个类型的指针 25 | { 26 | if ( PtrS->Top == MaxSize-1 ) // 判断满不满。从 0 到 MaxSize-1 27 | { 28 | printf("堆栈满\n"); 29 | return; 30 | }else 31 | { 32 | PtrS->Data[++(PtrS->Top)] = item; 33 | /* 相当于: 34 | (PtrS->Top)++; 35 | PtrS->Data[PtrS->Top] = item; 36 | */ 37 | return; 38 | } 39 | } 40 | 41 | // 空 42 | bool IsStackEmpty(Stack PtrS){ 43 | if ( PtrS->Top == -1 ) 44 | return true; 45 | else return false; 46 | } 47 | 48 | // 出栈 49 | ElementType Pop( Stack PtrS ) 50 | { 51 | if ( IsStackEmpty(PtrS) ) { 52 | printf("堆栈空\n"); 53 | return ERROR; 54 | } 55 | else 56 | return ( PtrS->Data[(PtrS->Top)--] ); // return 出下标为top的这个值,同时Top-1 57 | } 58 | /**************** Stack ******************/ -------------------------------------------------------------------------------- /Notes/TopSort.c: -------------------------------------------------------------------------------- 1 | // 拓扑排序 2 | #include 3 | #include 4 | #include 5 | #define MaxVertexNum 1000 6 | #define INFINITY 65535 7 | 8 | typedef int Vertex; // 用顶点下标表示顶点,为整形 9 | typedef char DataType; 10 | typedef int WeightType; // 边的权值设为int 11 | 12 | /* ********************* TopSort *******************/ 13 | /* 邻接表存储 - 拓扑排序算法 */ 14 | 15 | bool TopSort( LGraph Graph, Vertex TopOrder[] ) // TopOrder[]顺序存储排序后的顶点下标 */ 16 | { 17 | int Indegree[MaxVertexNum], cnt; 18 | Vertex V; 19 | PtrToAdjVNode W; 20 | Queue Q = CreateQueue( Graph->Nv ); 21 | 22 | /* 初始化Indegree[] */ 23 | for (V=0; VNv; V++) 24 | Indegree[V] = 0; 25 | 26 | /* 遍历图,得到Indegree[] */ 27 | for (V=0; VNv; V++) 28 | for (W=Graph->G[V].FirstEdge; W; W=W->Next) 29 | Indegree[W->AdjV]++; /* 对有向边AdjV>累计终点的入度 */ 30 | 31 | /* 将所有入度为0的顶点入列 */ 32 | for (V=0; VNv; V++) 33 | if ( Indegree[V]==0 ) 34 | AddQ(Q, V); 35 | 36 | /* 下面进入拓扑排序 */ 37 | cnt = 0; 38 | while( !IsEmpty(Q) ){ 39 | V = DeleteQ(Q); /* 弹出一个入度为0的顶点 */ 40 | TopOrder[cnt++] = V; /* 将之存为结果序列的下一个元素 */ 41 | /* 对V的每个邻接点W->AdjV */ 42 | for ( W=Graph->G[V].FirstEdge; W; W=W->Next ) 43 | if ( --Indegree[W->AdjV] == 0 )/* 若删除V使得W->AdjV入度为0 */ 44 | AddQ(Q, W->AdjV); /* 则该顶点入列 */ 45 | } /* while结束*/ 46 | 47 | if ( cnt != Graph->Nv ) 48 | return false; /* 说明图中有回路, 返回不成功标志 */ 49 | else 50 | return true; 51 | } 52 | -------------------------------------------------------------------------------- /Notes/Union and Find.c: -------------------------------------------------------------------------------- 1 | // Union and Find 2 | # define MAXN 1000 3 | typedef int ElementType; // 默认元素为非负整数0,1,2,3,... 4 | typedef int SetName; // 默认用根节点的下标作为集合的名称 5 | 6 | 7 | // 查找某个元素所在的集合,用根节点表示 8 | // 方法一 直接用数组 9 | typedef ElementType SetType[MAXN]; // 下标从0开始 10 | 11 | SetName Find(SetType S, ElementType X){ 12 | for(; S[X]>=0; X=S[X]); // 跳出时 S[X] = -1, X为根节点下标 13 | return X; 14 | } 15 | 16 | // 方法二, 定义一个数据结构 17 | typedef struct { 18 | ElementType Data; 19 | int Parent; // 其父节点的下标 20 | } SetType; 21 | 22 | int Find(SetType S[], ElementType X) 23 | { 24 | /* 在数组S中查找值为X的元素所属的集合, MAXN为数组最大长度 */ 25 | int i; 26 | for(i=0; i= MAXN) // 未找到 28 | return -1; 29 | for(; S[i].Parent >= 0; i = s[i].Parent); // 向上找它的父节点 30 | return i; 31 | } 32 | 33 | // 方法三, 路径压缩 34 | SetName Find( SetType S, ElementType X ) 35 | { 36 | if ( S[X] < 0 ) /* 找到集合的根 */ 37 | return X; 38 | else 39 | return S[X] = Find( S, S[X] ); /* 路径压缩 */ 40 | } 41 | 42 | 43 | 44 | 45 | // 并 46 | void Union( SetType S[], ElementType X1, ElementType X2 ) 47 | { 48 | int Root1, Root2; 49 | Root1 = Find(S, X1); 50 | Root2 = Find(S, X2); 51 | if( Root1 != Root2 ) 52 | S[Root2].Parent = Root1; 53 | } 54 | 55 | //// 并(按秩) 按方法一实现 56 | void Union( SetType S, SetName Root1, SetName Root2 ) 57 | { /* 这里默认Root1和Root2是不同集合的根结点 */ 58 | /* 保证小集合并入大集合 */ 59 | if ( S[Root2] < S[Root1] ) { /* 如果集合2比较大 */ 60 | S[Root2] += S[Root1]; /* 集合1并入集合2 */ 61 | S[Root1] = Root2; 62 | } 63 | else { /* 如果集合1比较大 */ 64 | S[Root1] += S[Root2]; /* 集合2并入集合1 */ 65 | S[Root2] = Root1; 66 | } 67 | } -------------------------------------------------------------------------------- /Notes/kmp.c: -------------------------------------------------------------------------------- 1 | // KMP 匹配算法 2 | #include 3 | #include 4 | #include 5 | #define MAXSTRING 1000001 6 | #define MAXPATTERN 100001 7 | #define NotFound -1 8 | 9 | void BuildMatch(char *pattern, int *match){ 10 | int i, j; 11 | int m = strlen(pattern); 12 | match[0] = -1; 13 | for (j=1; j=0 && (pattern[i+1] != pattern[j])) // 找到能对上的的pattern为止 16 | i = match[i]; 17 | if (pattern[i+1] == pattern[j]) 18 | match[j] = i+1; 19 | else 20 | match[j] = NotFound; 21 | } 22 | } 23 | 24 | int KMP(char *string, char *pattern){ 25 | int n = strlen(string); 26 | int m = strlen(pattern); 27 | int s, p; 28 | if (n < m) return NotFound; 29 | // match列表来放pattern的最大匹配值 30 | int *match; 31 | match = (int*)malloc(m * sizeof(int)); 32 | BuildMatch(pattern, match); 33 | 34 | s=p=0; 35 | while(s < n && p < m){ 36 | if (string[s] == pattern[p]){ 37 | s++; 38 | p++; 39 | } 40 | else if(p > 0) // p回撤到上一个match模块后一位, s不动,继续比较s和回撤后的p 41 | p = match[p-1] + 1; 42 | else s++; // p=0 pattern第一个就没有对上,移动s, p不动 43 | } 44 | return (p == m)? (s-m):NotFound; 45 | } 46 | 47 | int main(int argc, char const *argv[]) 48 | { 49 | char string[MAXSTRING]; 50 | scanf("%s", string); 51 | char pattern[MAXPATTERN]; 52 | int n; 53 | int p; 54 | scanf("%d", &n); 55 | for(int i=0; i 2 | 3 | int MaxSubseqSum4( int A[], int N ); 4 | 5 | int main(){ 6 | int N; 7 | scanf("%d", &N); 8 | int A[N]; 9 | for(int i = 0; i MaxSum ) 28 | MaxSum = ThisSum; /* 发现更大和则更新当前结果 */ 29 | else if( ThisSum < 0 ) /* 如果当前子列和为负 */ 30 | ThisSum = 0; /* 则不可能使后面的部分和增大,抛弃之 */ } 31 | return MaxSum; 32 | } 33 | -------------------------------------------------------------------------------- /PTA_Exercise/01-复杂度2 Maximum Subsequence Sum.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int MaxSubseqSum( int A[], int N, int *head, int *tail); 4 | 5 | int main(){ 6 | int N; 7 | scanf("%d", &N); 8 | int A[N]; 9 | for(int i = 0; i MaxSum ) 36 | { 37 | *head = i; 38 | *tail = j; 39 | MaxSum = ThisSum; 40 | } 41 | } /* j循环结束 */ 42 | } /* i循环结束 */ 43 | if (MaxSum < 0){ 44 | *head = 0; 45 | *tail = N-1; 46 | } 47 | return MaxSum; 48 | } 49 | -------------------------------------------------------------------------------- /PTA_Exercise/02-线性结构1 两个有序链表序列的合并 版本2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef int ElementType; 5 | typedef struct Node *PtrToNode; 6 | struct Node { 7 | ElementType Data; 8 | PtrToNode Next; 9 | }; 10 | typedef PtrToNode List; 11 | 12 | List Read(); 13 | void Print( List L ); 14 | 15 | List Merge( List L1, List L2 ); 16 | 17 | int main() 18 | { 19 | List L1, L2, L; 20 | L1 = Read(); 21 | L2 = Read(); 22 | L = Merge(L1, L2); 23 | Print(L); 24 | Print(L1); 25 | Print(L2); 26 | return 0; 27 | } 28 | 29 | void attach(int c, List* pList){ 30 | PtrToNode p = (PtrToNode)malloc(sizeof(struct Node)); 31 | p->Data = c; 32 | p->Next = NULL; 33 | PtrToNode last = *pList; // last指针指向pList的头指针所指向的 34 | if (last != 0){ // 如果链表不为空 35 | while( last-> Next != 0){ //就循环找到最后一个结点 36 | last = last-> Next; 37 | } 38 | last->Next = p; //跳出循环的时候last指向最后一个结点,接上p 39 | } 40 | else 41 | { 42 | *pList = p; // 如果本身就是空链表,则pList的头指针 接上p 43 | } 44 | } 45 | 46 | 47 | 48 | List Read(){ 49 | int N; 50 | scanf("%d", &N); 51 | int c; 52 | List list = (List)malloc(sizeof(struct Node)); 53 | list->Next = NULL; 54 | while(N--){ 55 | scanf("%d", &c); 56 | attach(c, &list); 57 | } 58 | return list; 59 | } 60 | 61 | 62 | 63 | void Print( List L ){ 64 | PtrToNode temp; 65 | if (L->Next == NULL){ 66 | printf("NULL\n"); 67 | return; 68 | } 69 | for (temp = L->Next; temp != NULL; temp = temp->Next){ 70 | printf("%d ", temp->Data); 71 | } 72 | printf("\n"); 73 | } 74 | 75 | 76 | 77 | List Merge( List L1, List L2 ){ 78 | 79 | List L = (List)malloc(sizeof(struct Node)); 80 | L->Next = NULL; 81 | List temp1 = L1->Next; 82 | List temp2 = L2->Next; 83 | 84 | while(temp1 && temp2) 85 | { 86 | if (temp1->Data <= temp2->Data){ 87 | attach(temp1->Data, &L); 88 | temp1 = temp1->Next; 89 | }else 90 | { 91 | attach(temp2->Data, &L); 92 | temp2 = temp2->Next; 93 | } 94 | } 95 | 96 | for(; temp1!=0; temp1 = temp1->Next){ 97 | attach(temp1->Data, &L); 98 | } 99 | 100 | for(; temp2!=0; temp2 = temp2->Next){ 101 | attach(temp2->Data, &L); 102 | } 103 | L1->Next = NULL; 104 | L2->Next = NULL; 105 | return L; 106 | 107 | } 108 | 109 | 110 | // List Merge( List L1, List L2 ){ 111 | // List L=(List)malloc(sizeof(struct Node)); 112 | // List head = L; 113 | // List tmpL1 = L1->Next; 114 | // List tmpL2 = L2->Next; 115 | // while(tmpL1 && tmpL2){ 116 | // if(tmpL1->Data < tmpL2->Data){ 117 | // L->Next=tmpL1; 118 | // tmpL1=tmpL1->Next; 119 | // }else{ 120 | // L->Next=tmpL2; 121 | // tmpL2=tmpL2->Next; 122 | // } 123 | // L=L->Next; 124 | // } 125 | // if(tmpL1) 126 | // L->Next=tmpL1; 127 | // if(tmpL2) 128 | // L->Next=tmpL2; 129 | // L1->Next = NULL; 130 | // L2->Next = NULL; 131 | // return head; 132 | // } 133 | 134 | -------------------------------------------------------------------------------- /PTA_Exercise/02-线性结构1 两个有序链表序列的合并.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef int ElementType; 5 | typedef struct Node *PtrToNode; 6 | struct Node { 7 | ElementType Data; 8 | PtrToNode Next; 9 | }; 10 | typedef PtrToNode List; 11 | 12 | List Read(); 13 | void Print( List L ); 14 | 15 | List Merge( List L1, List L2 ); 16 | 17 | int main() 18 | { 19 | List L1, L2, L; 20 | L1 = Read(); 21 | L2 = Read(); 22 | L = Merge(L1, L2); 23 | Print(L); 24 | Print(L1); 25 | Print(L2); 26 | return 0; 27 | } 28 | 29 | void attach(int c, List* pList){ 30 | PtrToNode p = (PtrToNode)malloc(sizeof(struct Node)); 31 | p->Data = c; 32 | p->Next = NULL; 33 | PtrToNode last = *pList; // last指针指向pList的头指针所指向的 34 | if (last != 0){ // 如果链表不为空 35 | while( last-> Next != 0){ //就循环找到最后一个结点 36 | last = last-> Next; 37 | } 38 | last->Next = p; //跳出循环的时候last指向最后一个结点,接上p 39 | } 40 | else 41 | { 42 | *pList = p; // 如果本身就是空链表,则pList的头指针 接上p 43 | } 44 | } 45 | 46 | 47 | 48 | List Read(){ 49 | int N; 50 | scanf("%d", &N); 51 | int c; 52 | List list = NULL; 53 | 54 | 55 | while(N--){ 56 | scanf("%d", &c); 57 | attach(c, &list); 58 | } 59 | return list; 60 | } 61 | 62 | 63 | 64 | void Print( List L ){ 65 | PtrToNode temp; 66 | if (!L){ 67 | printf("NULL\n"); 68 | return; 69 | } 70 | for (temp = L; temp != NULL; temp = temp->Next){ 71 | printf("%d ", temp->Data); 72 | } 73 | printf("\n"); 74 | } 75 | 76 | 77 | 78 | List Merge( List L1, List L2 ){ 79 | 80 | List L = NULL; 81 | while(L1&&L2) 82 | { 83 | if (L1->Data <= L2->Data){ 84 | attach(L1->Data, &L); 85 | L1 = L1->Next; 86 | }else 87 | { 88 | attach(L2->Data, &L); 89 | L2 = L2->Next; 90 | } 91 | } 92 | 93 | for(; L1!=0; L1 = L1->Next){ 94 | attach(L1->Data, &L); 95 | } 96 | 97 | for(; L2!=0; L2 = L2->Next){ 98 | attach(L2->Data, &L); 99 | } 100 | 101 | return L; 102 | 103 | } 104 | 105 | 106 | // List Merge( List L1, List L2 ){ 107 | // List L=(List)malloc(sizeof(struct Node)); 108 | // List head = L; 109 | // List tmpL1 = L1->Next; 110 | // List tmpL2 = L2->Next; 111 | // while(tmpL1 && tmpL2){ 112 | // if(tmpL1->Data < tmpL2->Data){ 113 | // L->Next=tmpL1; 114 | // tmpL1=tmpL1->Next; 115 | // }else{ 116 | // L->Next=tmpL2; 117 | // tmpL2=tmpL2->Next; 118 | // } 119 | // L=L->Next; 120 | // } 121 | // if(tmpL1) 122 | // L->Next=tmpL1; 123 | // if(tmpL2) 124 | // L->Next=tmpL2; 125 | // L1->Next = NULL; 126 | // L2->Next = NULL; 127 | // return head; 128 | // } 129 | 130 | -------------------------------------------------------------------------------- /PTA_Exercise/02-线性结构2 一元多项式的乘法与加法运算.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef int ElementType; 5 | typedef struct PolyNode *Polynomial; 6 | struct PolyNode { 7 | ElementType coef; 8 | ElementType expon; 9 | Polynomial link; 10 | }; 11 | typedef Polynomial List; 12 | 13 | List Read(); 14 | void Print( List L ); 15 | Polynomial Add(Polynomial P1, Polynomial P2); 16 | Polynomial Multi(Polynomial P1, Polynomial P2); 17 | 18 | int main() 19 | { 20 | Polynomial L1, L2, L; 21 | L1 = Read(); 22 | L2 = Read(); 23 | L = Multi(L1, L2); 24 | Print(L); 25 | L = Add(L1, L2); 26 | Print(L); 27 | return 0; 28 | } 29 | 30 | void attach(int c, int e, Polynomial *pRear){ 31 | Polynomial p = (Polynomial)malloc(sizeof(struct PolyNode)); 32 | p->coef = c; 33 | p->expon = e; 34 | p->link = NULL; 35 | (*pRear)->link = p; // 连上p 36 | *pRear = p; //pRear往后移一位指向p 37 | } 38 | 39 | 40 | 41 | List Read(){ 42 | int N, c, e; 43 | scanf("%d", &N); 44 | Polynomial P, Rear, t; 45 | P = (Polynomial)malloc(sizeof(struct PolyNode)); // 插入一个空结点 46 | P->link = NULL; 47 | Rear = P; 48 | while(N--){ 49 | scanf("%d %d", &c, &e); 50 | attach(c, e, &Rear); 51 | } 52 | // 释放掉空结点 53 | t = P; 54 | P = P->link; 55 | free(t); 56 | return P; 57 | 58 | } 59 | 60 | 61 | void Print( List L ){ 62 | Polynomial temp; 63 | // 如果链表为空,打印0 0 64 | if (L == NULL){ 65 | printf("0 0\n"); 66 | return; 67 | } 68 | int tag = 0; //控制开头的空格 69 | 70 | // 打印每一项 71 | for (temp = L; temp != NULL; temp = temp->link){ 72 | if (tag == 0){ 73 | tag = 1; 74 | }else 75 | { 76 | printf(" "); 77 | } 78 | printf("%d %d", temp->coef, temp->expon); 79 | } 80 | printf("\n"); 81 | } 82 | 83 | Polynomial Add(Polynomial P1, Polynomial P2){ 84 | Polynomial P, Rear, t1, t2, t; 85 | P = (Polynomial)malloc(sizeof(struct PolyNode)); // 插入一个空结点 86 | P->link = NULL; 87 | Rear = P; 88 | t1 = P1; 89 | t2 = P2; 90 | while (t1 && t2){ 91 | if(t1->expon == t2->expon) // expon相同 92 | { 93 | int sum; 94 | sum = t1->coef + t2->coef; 95 | if (sum != 0) attach(sum, t1->expon, &Rear); 96 | t1 = t1->link; 97 | t2 = t2->link; 98 | } 99 | else if(t1->expon > t2->expon) // t1的expon大 100 | { 101 | attach(t1->coef, t1->expon, &Rear); 102 | t1 = t1->link; 103 | } 104 | else // t2的expon大 105 | { 106 | attach(t2->coef, t2->expon, &Rear); 107 | t2 = t2->link; 108 | } 109 | } 110 | while(t1){ 111 | attach(t1->coef, t1->expon, &Rear); 112 | t1 = t1->link; 113 | } 114 | while(t2){ 115 | attach(t2->coef, t2->expon, &Rear); 116 | t2 = t2->link; 117 | } 118 | // 释放空结点 119 | t = P; 120 | P = P->link; 121 | free(t); 122 | return P; 123 | } 124 | 125 | Polynomial Multi(Polynomial P1, Polynomial P2) 126 | { 127 | Polynomial P, Rear, t1, t2, t; 128 | int c, e; 129 | P = (Polynomial)malloc(sizeof(struct PolyNode)); 130 | P->link = NULL; 131 | Rear = P; 132 | t1 = P1; 133 | t2 = P2; 134 | // 若P1或P2为空,则返回null 135 | if(!t1||!t2) return NULL; 136 | 137 | // P1第一项乘以P2每一项, 放入P 138 | while(t2){ 139 | c = t1->coef * t2->coef; //系数相乘,指数相加 140 | e = t1->expon + t2->expon; 141 | attach(c, e, &Rear); 142 | t2 = t2->link; 143 | } 144 | t1 = t1->link;// 从t1第二项开始,遍历t1和t2,得到结果与P比较,插入 145 | while(t1){ 146 | t2 = P2; 147 | Rear = P; 148 | while(t2) 149 | { 150 | e = t1->expon + t2->expon; 151 | c = t1->coef * t2->coef; 152 | while (Rear->link && Rear->link->expon > e) 153 | {// Rear一直移到 Rear所指的Node 的link所指的Node 的expon不大于e 154 | Rear = Rear->link; 155 | } 156 | if(Rear->link && Rear->link->expon == e) 157 | { // 下一项的expon和e相等; 158 | if(Rear->link->coef + c != 0) 159 | { // 指数相加不为0 160 | Rear->link->coef += c; // 原指数加上新指数 161 | } 162 | else 163 | { // 指数相加等于0, 释放掉Rear->link所指的Node 164 | t = Rear->link; 165 | Rear->link = t->link; 166 | free(t); 167 | } 168 | }else 169 | { // 小于e时,插入到Rear的后面,下一个Node的前面 170 | t= (Polynomial)malloc(sizeof(struct PolyNode)); 171 | t->coef = c; 172 | t->expon = e; 173 | t->link = Rear->link; // t的link指向Rear指向的后一个结点 174 | Rear->link = t; // 连上t 175 | Rear = Rear->link; // Rear往后移 176 | } 177 | t2 = t2->link; 178 | } 179 | t1 = t1->link; 180 | } 181 | // 释放空结点 182 | t = P; 183 | P = P->link; 184 | free(t); 185 | return P; 186 | } 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /PTA_Exercise/02-线性结构3 Reversing Linked List.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MaxSize 100005 4 | 5 | int main(){ 6 | int Data[MaxSize]; 7 | int Next[MaxSize]; 8 | int list[MaxSize]; 9 | int FirstAdd,N,K; 10 | scanf("%d %d %d",&FirstAdd,&N,&K); 11 | for(int i=0;i 3 | #include 4 | #include 5 | #define MaxSize 1005 6 | #define ERROR -1 7 | typedef int ElementType; 8 | 9 | /**************** Stack ******************/ 10 | 11 | typedef struct SNode *Stack; //结构指针 12 | struct SNode{ 13 | ElementType *Data; //数组 14 | int Top; // 栈顶位置的数组下标 15 | int Capacity; 16 | }; 17 | 18 | 19 | // 创建堆栈 20 | Stack CreateStack(int M) 21 | { 22 | Stack S = (Stack)malloc(sizeof(struct SNode)); 23 | S->Data = (ElementType*)malloc(M * sizeof(ElementType)); // Data 从 0 到 M-1 24 | S->Top = -1; 25 | S->Capacity = M; 26 | 27 | return S; 28 | } 29 | 30 | bool IsStackFull(Stack PtrS){ 31 | if (PtrS->Top == PtrS->Capacity-1 ) 32 | return true; 33 | else return false; 34 | } 35 | 36 | // 入栈 37 | void Push( Stack PtrS, ElementType item ) // stack这个类型的指针 38 | { 39 | if ( IsStackFull(PtrS) ) // 判断满不满。从 0 到 M-1 40 | { 41 | printf("堆栈满\n"); 42 | return; 43 | } 44 | else 45 | { 46 | PtrS->Data[++(PtrS->Top)] = item; 47 | /* 相当于: 48 | (PtrS->Top)++; 49 | PtrS->Data[PtrS->Top] = item; 50 | */ 51 | return; 52 | } 53 | } 54 | 55 | // 空 56 | bool IsStackEmpty(Stack PtrS){ 57 | if ( PtrS->Top == -1 ) 58 | return true; 59 | else return false; 60 | } 61 | 62 | // 出栈 63 | ElementType Pop( Stack PtrS ) 64 | { 65 | if ( IsStackEmpty(PtrS) ) { 66 | printf("堆栈空\n"); 67 | return ERROR; 68 | } 69 | else 70 | return ( PtrS->Data[(PtrS->Top)--] ); // return 出下标为top的这个值,同时Top-1 71 | } 72 | 73 | /* ************************** */ 74 | 75 | void ReadList(int List[], int N){ 76 | for (int i=1; i<=N; i++) 77 | scanf("%d", &List[i]); 78 | } 79 | 80 | void CheckList(int List[], int Sequence[], int M, int N){ 81 | Stack S = CreateStack(M); 82 | int j; 83 | int cur = 1; 84 | for (j=1; j<=N; j++){ 85 | if (!IsStackFull(S)) 86 | Push(S, Sequence[j]); 87 | while (!IsStackEmpty(S) && S->Data[S->Top] == List[cur]){ 88 | Pop(S); 89 | cur++; 90 | } 91 | if (IsStackFull(S)) 92 | break; 93 | } 94 | if (M && IsStackEmpty(S)) 95 | printf("YES\n"); 96 | else 97 | printf("NO\n"); 98 | 99 | } 100 | 101 | 102 | int main(int argc, char const *argv[]) 103 | { 104 | int M, N, K,i; 105 | int List[MaxSize]; 106 | 107 | scanf("%d %d %d", &M, &N, &K); 108 | int Sequence[MaxSize]; 109 | for (i = 1; i<=N; i++){ 110 | Sequence[i] = i; 111 | } 112 | for (i=0; i 2 | #define ElementType char 3 | #define null -1 4 | #define Tree int 5 | #define MaxTree 10 6 | 7 | typedef struct TreeNode tree; 8 | struct TreeNode 9 | { 10 | ElementType element; 11 | Tree left; 12 | Tree right; 13 | }T1[MaxTree], T2[MaxTree]; 14 | 15 | int BuildTree(struct TreeNode T[]); 16 | int Isomorphic(Tree R1, Tree R2); 17 | 18 | 19 | 20 | 21 | int main(int argc, char const *argv[]) 22 | { 23 | Tree R1, R2; 24 | R1 = BuildTree(T1); 25 | R2 = BuildTree(T2); 26 | // printf("R1=%d\n", R1); 27 | // printf("R2=%d\n", R2); 28 | if(Isomorphic(R1,R2)) 29 | printf("Yes\n"); 30 | else 31 | printf("No\n"); 32 | return 0; 33 | } 34 | 35 | Tree BuildTree(struct TreeNode T[]) 36 | { 37 | int N, i; 38 | Tree Root = null; 39 | char cl, cr; 40 | scanf("%d", &N); 41 | if(N) 42 | { 43 | /* 设置一个列表,初始化为0 */ 44 | int check[N]; 45 | for (i=0; i 2 | #include 3 | #define ElementType struct TreeNode 4 | #define null -1 5 | #define Tree int 6 | #define MaxTree 10 7 | 8 | struct TreeNode 9 | { 10 | int index; 11 | Tree left; 12 | Tree right; 13 | }; 14 | 15 | int BuildTree(struct TreeNode T[]); 16 | 17 | struct QNode 18 | { 19 | ElementType *Data; 20 | int rear; 21 | int front; 22 | int Maxsize; 23 | }; 24 | typedef struct QNode *Queue; 25 | Queue CreateQueue(int Maxsize); 26 | void AddQ( Queue PtrQ, ElementType item); 27 | ElementType DeleteQ ( Queue PtrQ ); 28 | int IsEmptyQ(Queue Q); 29 | 30 | void Leaves( struct TreeNode T[], int Root, int Maxsize); 31 | 32 | 33 | int main(int argc, char const *argv[]) 34 | { 35 | struct TreeNode T[MaxTree]; 36 | Tree R1; 37 | R1 = BuildTree(T); 38 | // printf("Root=%d\n", T[R1].index); 39 | // printf("T[0].left=%d\n", T[0].left); 40 | Leaves(T, R1, MaxTree); 41 | 42 | return 0; 43 | } 44 | 45 | Tree BuildTree(struct TreeNode T[]) 46 | { 47 | int N, i; 48 | Tree Root = null; 49 | char cl, cr; 50 | scanf("%d", &N); 51 | if(N) 52 | { 53 | /* 设置一个列表,初始化为0 */ 54 | int check[N]; 55 | for (i=0; iData = (ElementType*)malloc(Maxsize * sizeof(ElementType)); 115 | Q->front = Q->rear = 0; 116 | Q->Maxsize = Maxsize; 117 | return Q; 118 | } 119 | 120 | void AddQ( Queue PtrQ, ElementType item) { 121 | // if (IsFull(Q)) 122 | if ( (PtrQ->rear+1) % PtrQ->Maxsize == PtrQ->front ) 123 | { 124 | printf("FULL"); 125 | return; 126 | } 127 | PtrQ->rear = (PtrQ->rear+1)% PtrQ->Maxsize; 128 | PtrQ->Data[PtrQ->rear] = item; 129 | } 130 | 131 | int IsEmptyQ(Queue Q) 132 | { 133 | return(Q->front == Q->rear); 134 | } 135 | 136 | 137 | ElementType DeleteQ ( Queue PtrQ ) // front和rear相同 138 | { 139 | // if (IsEmpty(Q)) 140 | if ( PtrQ->front == PtrQ->rear ) 141 | { 142 | printf("EMPTY"); 143 | return (ElementType){}; 144 | } 145 | else 146 | { 147 | PtrQ->front = (PtrQ->front+1)% PtrQ->Maxsize; // front往后移一位指向第一个元素 148 | return PtrQ->Data[PtrQ->front]; 149 | } 150 | } 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /PTA_Exercise/03-树3 Tree Traversals Again .c: -------------------------------------------------------------------------------- 1 | // 03-树3 Tree Traversals Again 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define ElementType int 7 | #define MaxSize 50 8 | #define ERROR 999 9 | 10 | /**************** Stack ******************/ 11 | 12 | typedef struct SNode *Stack; //结构指针 13 | struct SNode{ 14 | ElementType *Data; //数组 15 | int Top; // 栈顶位置的数组下标 16 | }; 17 | 18 | 19 | // 创建堆栈 20 | Stack CreateStack(void) 21 | { 22 | Stack S = (Stack)malloc(sizeof(struct SNode)); 23 | S->Data = (ElementType*)malloc(MaxSize* sizeof(ElementType)); 24 | S->Top = -1; 25 | 26 | return S; 27 | } 28 | 29 | // 入栈 30 | void Push( Stack PtrS, ElementType item ) // stack这个类型的指针 31 | { 32 | if ( PtrS->Top == MaxSize-1 ) // 判断满不满。从 0 到 MaxSize-1 33 | { 34 | printf("堆栈满\n"); 35 | return; 36 | }else 37 | { 38 | PtrS->Data[++(PtrS->Top)] = item; 39 | /* 相当于: 40 | (PtrS->Top)++; 41 | PtrS->Data[PtrS->Top] = item; 42 | */ 43 | return; 44 | } 45 | } 46 | 47 | // 空 48 | bool IsStackEmpty(Stack PtrS){ 49 | if ( PtrS->Top == -1 ) 50 | return true; 51 | else return false; 52 | } 53 | 54 | // 出栈 55 | ElementType Pop( Stack PtrS ) 56 | { 57 | if ( IsStackEmpty(PtrS) ) { 58 | printf("堆栈空\n"); 59 | return ERROR; 60 | } 61 | else 62 | return ( PtrS->Data[(PtrS->Top)--] ); // return 出下标为top的这个值,同时Top-1 63 | } 64 | /**************** Stack ******************/ 65 | 66 | int pre[MaxSize], in[MaxSize],post[MaxSize]; // 全局变量 67 | void SolvePost(int preL, int inL, int postL, int n){ // pre的左端, in的左端, post的左端,树的总长度 68 | int root, i, L, R; 69 | if(n==0) return; 70 | if(n==1) { 71 | post[postL] = pre[preL]; 72 | return; 73 | } 74 | root = pre[preL]; 75 | post[postL+n-1] = root; 76 | for(i =0; i 2 | #include 3 | 4 | typedef struct TreeNode *Tree; 5 | struct TreeNode{ 6 | int v; 7 | Tree Left; 8 | Tree Right; 9 | int flag; 10 | }; 11 | 12 | Tree MakeTree(int N); 13 | Tree NewNode(int V); 14 | Tree Insert(Tree T, int V); 15 | int check(Tree T, int V); 16 | int Judge(Tree T, int N); 17 | void ResetT(Tree T); 18 | void FreeTree(Tree T); 19 | 20 | int main(){ 21 | int N,L,i; 22 | Tree T; 23 | 24 | scanf("%d", &N); 25 | while(N){ 26 | scanf("%d", &L); 27 | T = MakeTree(N); 28 | for(i=0; iv = V; 60 | T->Left = T->Right = NULL; 61 | T->flag = 0; 62 | return T; 63 | } 64 | 65 | 66 | // 递归加入新的结点 67 | Tree Insert(Tree T, int V){ 68 | if (!T) 69 | T = NewNode(V); 70 | else{ 71 | if(V > T->v) 72 | T->Right = Insert(T->Right, V); 73 | else 74 | T->Left = Insert(T->Left, V); 75 | } 76 | return T; 77 | } 78 | 79 | 80 | /*在树T中按顺序搜索序列3 2 4 1中的每个数 81 | 如果每次搜索所经过的结点在前面均出现过,则一致 82 | 否则(某次搜索中遇到前面未出现的结点),则不一致*/ 83 | int check(Tree T, int V){ 84 | if(T->flag) 85 | {//flag不等于0的情况 86 | if(V < T->v) 87 | return check(T->Left, V); 88 | else if(V > T->v) 89 | return check(T->Right, V); 90 | else 91 | return 0; 92 | } 93 | else 94 | {// T->flag = 0 的情况 95 | if (V == T->v) 96 | { 97 | T->flag = 1; 98 | return 1; 99 | }else 100 | return 0; 101 | } 102 | } 103 | 104 | 105 | int Judge(Tree T, int N){ 106 | int V, Tflag = 1; 107 | 108 | scanf("%d", &V); 109 | // 先和根结点比 110 | if (T->v != V) 111 | Tflag = 0; // 这里不要直接return 0,不然之后的数就不读了 112 | else 113 | T->flag = 1; 114 | 115 | // 依次比较接下来N-1个数 116 | for(int i=1; iLeft) 128 | ResetT(T->Left); 129 | if(T->Right) 130 | ResetT(T->Right); 131 | T->flag = 0; 132 | } 133 | 134 | void FreeTree(Tree T){ 135 | if(T->Left) 136 | FreeTree(T->Left); 137 | if(T->Right) 138 | FreeTree(T->Right); 139 | free(T); 140 | } 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /PTA_Exercise/04-树5 Root of AVL Tree.c: -------------------------------------------------------------------------------- 1 | // Root of AVL Tree 2 | #include 3 | #include 4 | #define ElementType int 5 | 6 | typedef struct AVLNode *Position; 7 | typedef Position AVLTree; 8 | struct AVLNode 9 | { 10 | ElementType Data; 11 | AVLTree Left; 12 | AVLTree Right; 13 | int Height; 14 | }; 15 | 16 | int Max(int a, int b); 17 | AVLTree Insert(AVLTree T, ElementType X); 18 | AVLTree LL(AVLTree A); 19 | AVLTree LR(AVLTree A); 20 | AVLTree RR(AVLTree A); 21 | AVLTree RL(AVLTree A); 22 | int GetHeight(AVLTree T); 23 | 24 | 25 | int main(int argc, char const *argv[]) 26 | { 27 | int N, V; 28 | AVLTree T = NULL; 29 | scanf("%d", &N); 30 | if (N){ 31 | for(int i=0; iData); 36 | } 37 | else 38 | printf("0\n"); 39 | 40 | return 0; 41 | } 42 | 43 | 44 | int Max(int a, int b){ 45 | return a>b? a:b; 46 | } 47 | 48 | //将X插入AVL树中,并且返回调整后的平衡树 49 | AVLTree Insert(AVLTree T, ElementType X){ 50 | if(!T) 51 | { //若插入空树,就新建包含一个结点的树 52 | T=(AVLTree)malloc(sizeof(struct AVLNode)); 53 | T->Data = X; 54 | T->Left = T->Right = NULL; 55 | T->Height = 1; 56 | } 57 | 58 | else if(X < T->Data) 59 | { 60 | T->Left = Insert(T->Left, X); // 插入左子树 61 | if((GetHeight(T->Left) - GetHeight(T->Right)) == 2) //需要做LL旋转或LR 62 | { 63 | if(X < T->Left->Data) // 新结点插入在A(Root)的左孩子的左子树中 64 | T = LL(T); 65 | else // 新结点插在A的左子树的右子树中 66 | T = LR(T); 67 | } 68 | } 69 | 70 | else if(X > T->Data) 71 | { 72 | T->Right = Insert(T->Right, X); // 插入左子树 73 | if((GetHeight(T->Right) - GetHeight(T->Left)) == 2) //需要做RR旋转或者RL 74 | { 75 | if(X > T->Right->Data) 76 | T = RR(T); // 新结点插入在A(Root)的右孩子B的右子树中 77 | else // 新结点插入在A(Root)的右孩子B的左子树中 78 | T = RL(T); 79 | } 80 | } 81 | 82 | // else T->Data == X 无需插入 83 | 84 | T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1; // 更新树的高度,左右高度的最大值+1 85 | 86 | return T; 87 | } 88 | 89 | 90 | // 左单旋函数LL 91 | AVLTree LL(AVLTree A){ 92 | // 新结点插入在A(Root)的左孩子B的左子树中 93 | AVLTree B = A->Left; // 根变成A的左孩子B 94 | A->Left = B->Right; // A的左孩子变成B的右孩子 95 | B->Right = A; //B的右孩子变成A 96 | A->Height = Max( GetHeight(A->Left), GetHeight(A->Right)) + 1; 97 | B->Height = Max( GetHeight(B->Left), A->Height) + 1; 98 | 99 | return B; 100 | } 101 | 102 | 103 | // 左右双旋函数LR 104 | AVLTree LR(AVLTree A){ 105 | // 新结点插在A的左子树B的右子树C中 106 | A->Left = RR(A->Left); // 对A的左子树B做一次右单旋RR 107 | return LL(A); //再对A做一次左单旋LL,返回根节点C 108 | } 109 | 110 | 111 | // 右单旋函数RR 112 | AVLTree RR(AVLTree A){ 113 | // 新结点插入在A(Root)的右孩子B的右子树中 114 | AVLTree B = A->Right; 115 | A->Right = B->Left; 116 | B->Left = A; 117 | A->Height = Max( GetHeight(A->Left), GetHeight(A->Right)) + 1; 118 | B->Height = Max( GetHeight(B->Right), A->Height) + 1; 119 | 120 | return B; 121 | } 122 | 123 | 124 | // 右左双旋函数RL 125 | AVLTree RL(AVLTree A){ 126 | // 新结点插入在A(Root)的右孩子B的左子树中 127 | A->Right = LL(A->Right); // 对A的右孩子B做一次左单旋RR 128 | return RR(A); //再对A做一次右单旋LL,返回根节点C 129 | } 130 | 131 | 132 | // 高度函数 133 | int GetHeight(AVLTree T){ 134 | int HL, HR; 135 | if(T){ 136 | HL = GetHeight(T->Left); 137 | HR = GetHeight(T->Right); 138 | T->Height = Max(HL, HR) + 1; 139 | } 140 | else return 0; 141 | return T->Height; 142 | } 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /PTA_Exercise/04-树6 Complete BST.c: -------------------------------------------------------------------------------- 1 | // 04-树6 Complete Binary Search Tree 2 | #include 3 | #include 4 | #include 5 | #define ElementType int 6 | #define MaxSize 1001 7 | 8 | int A[MaxSize], T[MaxSize]; 9 | 10 | int compare(const void* a, const void* b); 11 | void Solve(int Aleft, int Aright, int TRoot); 12 | int GetLeftLength(int n); 13 | int min(int a, int b); 14 | 15 | int main(int argc, char const *argv[]) 16 | { 17 | int N, V; 18 | scanf("%d", &N); 19 | for (int i=0; i 3 | #include 4 | 5 | typedef int ElementType; 6 | typedef struct TNode *Position; 7 | typedef Position BinTree; 8 | struct TNode{ 9 | ElementType Data; 10 | BinTree Left; 11 | BinTree Right; 12 | }; 13 | 14 | void PreorderTraversal( BinTree BT ); /* 先序遍历,由裁判实现,细节不表 */ 15 | void InorderTraversal( BinTree BT ); /* 中序遍历,由裁判实现,细节不表 */ 16 | 17 | BinTree Insert( BinTree BST, ElementType X ); 18 | BinTree Delete( BinTree BST, ElementType X ); 19 | Position Find( BinTree BST, ElementType X ); 20 | Position FindMin( BinTree BST ); 21 | Position FindMax( BinTree BST ); 22 | 23 | int main() 24 | { 25 | BinTree BST, MinP, MaxP, Tmp; 26 | ElementType X; 27 | int N, i; 28 | 29 | BST = NULL; 30 | scanf("%d", &N); 31 | for ( i=0; iData); 45 | if (Tmp==MinP) printf("%d is the smallest key\n", Tmp->Data); 46 | if (Tmp==MaxP) printf("%d is the largest key\n", Tmp->Data); 47 | } 48 | } 49 | scanf("%d", &N); 50 | for( i=0; iData = X; 65 | BST->Left = BST->Right = NULL; 66 | } 67 | else{ 68 | //若不空 69 | if(X > BST->Data) 70 | BST->Right = Insert(BST->Right, X); 71 | else if(X < BST->Data) 72 | BST->Left = Insert(BST->Left, X); 73 | } 74 | 75 | return BST; 76 | } 77 | 78 | 79 | BinTree Delete( BinTree BST, ElementType X ){ 80 | BinTree Tmp; 81 | 82 | if(!BST) 83 | printf("Not Found\n"); 84 | else 85 | { 86 | if(X > BST->Data) 87 | BST->Right = Delete(BST->Right, X); 88 | else if(X < BST->Data) 89 | BST->Left = Delete(BST->Left, X); 90 | else // (X == BST->Data), 找到了,删除 91 | { 92 | if(BST->Left && BST->Right) // 被删除结点左右两边都有子树 93 | { 94 | /* 从右子树中找最小的元素填充删除结点 */ 95 | Tmp = FindMin( BST->Right); 96 | BST->Data = Tmp->Data; 97 | /* 从右子树中删除最小元素 */ 98 | BST->Right = Delete(BST->Right, Tmp->Data); 99 | } 100 | else // 删除结点只有一个孩子,或者是叶结点 101 | { 102 | Tmp = BST; 103 | if(BST->Left) // 左边不空,则BST这个结点变成BST左孩子 104 | BST = BST->Left; 105 | else // 左边空 (右边不空,或者都空) 106 | BST = BST->Right; 107 | free(Tmp); 108 | } 109 | } 110 | } 111 | return BST; 112 | } 113 | 114 | 115 | Position Find( BinTree BST, ElementType X ){ 116 | if(!BST) 117 | return NULL; 118 | else 119 | { 120 | if(BST->Data == X) // 找到了 121 | return BST; 122 | else if(X > BST->Data) 123 | return Find(BST->Right, X); 124 | else 125 | return Find(BST->Left,X); 126 | } 127 | } 128 | 129 | 130 | Position FindMin( BinTree BST){ 131 | if(BST) // 根节点不空 132 | { 133 | while(BST->Left) // 有左儿子 134 | BST = BST->Left; // 一直往左,直到左儿子为空 135 | } 136 | return BST; 137 | } 138 | 139 | 140 | Position FindMax( BinTree BST ){ 141 | if(BST) // 根节点不空 142 | { 143 | while(BST->Right) // 有右儿子 144 | BST = BST->Right; // 一直往右,直到右儿子为空 145 | } 146 | return BST; 147 | } 148 | 149 | 150 | void PreorderTraversal( BinTree BT){ 151 | if(BT){ 152 | printf(" %d", BT->Data); 153 | PreorderTraversal(BT->Left); 154 | PreorderTraversal(BT->Right); 155 | } 156 | } 157 | 158 | 159 | void InorderTraversal( BinTree BT){ 160 | if(BT){ 161 | InorderTraversal(BT->Left); 162 | printf(" %d", BT->Data); 163 | InorderTraversal(BT->Right); 164 | } 165 | } 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /PTA_Exercise/05-树7 堆中的路径.c: -------------------------------------------------------------------------------- 1 | // 05-树7 堆中的路径 2 | #include 3 | #include 4 | #define MAXN 1001 5 | #define MAXH -10001 6 | 7 | int H[MAXN], size; 8 | void Create(); 9 | void Insert (int x); 10 | 11 | int main(int argc, char const *argv[]) 12 | { 13 | int n, m, x, k; 14 | scanf("%d", &n); 15 | scanf("%d", &m); 16 | Create(); 17 | for (int i=0; i1){ 26 | k = k/2; 27 | printf(" %d", H[k]); 28 | } 29 | printf("\n"); 30 | } 31 | 32 | return 0; 33 | } 34 | 35 | void Create(){ 36 | size = 0; 37 | H[0] = MAXH; 38 | } 39 | 40 | void Insert (int x){ 41 | if(size > MAXN-1){ 42 | printf("FULL\n"); 43 | return; 44 | } 45 | 46 | size++; 47 | int i = size; 48 | for(; H[i/2] > x; i/=2) 49 | H[i] = H[i/2]; 50 | H[i] = x; 51 | } 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /PTA_Exercise/05-树8 File Transfer.c: -------------------------------------------------------------------------------- 1 | // 05-树8 File Transfer 2 | #include 3 | #include 4 | #define MAXN 10001 /* 集合最大元素个数 */ 5 | typedef int ElementType; /* 默认元素可以用非负整数表示 */ 6 | typedef int SetName; /* 默认用根结点的下标作为集合名称 */ 7 | typedef ElementType SetType[MAXN]; /* 假设集合元素下标从0开始 */ 8 | 9 | void Initial(SetType S, int n); 10 | void Input_connection(SetType S); 11 | void Check_connection(SetType S); 12 | void Check_network(SetType S,int n); 13 | SetName Find(SetType S, ElementType x); 14 | void Union(SetType S, SetName R1, SetName R2); 15 | 16 | int main(int argc, char const *argv[]) 17 | { 18 | SetType S; 19 | int n; 20 | char in; 21 | scanf("%d", &n); 22 | Initial(S, n); // 都初始化为-1 23 | do{ 24 | getchar(); // 接收每次多出来的回车 25 | scanf("%c",&in); 26 | switch(in){ 27 | case 'I': Input_connection(S); break; 28 | case 'C': Check_connection(S); break; 29 | case 'S': Check_network(S, n); break; 30 | } 31 | }while( in != 'S'); 32 | return 0; 33 | } 34 | 35 | 36 | void Initial(SetType S, int n){ 37 | for (int i=0; i S[R2]){ // 集合R2比较大,因为是负数 87 | S[R2] += S[R1]; 88 | S[R1] = R2; 89 | } 90 | else 91 | { 92 | S[R1] += S[R2]; 93 | S[R2] = R1; 94 | } 95 | } 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /PTA_Exercise/05-树9 Huffman Codes.c: -------------------------------------------------------------------------------- 1 | //05-树9 Huffman Codes 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define MaxSize 65 7 | #define ElementType HuffmanTree 8 | #define ERROR NULL 9 | #define INFINITY 1000 10 | 11 | 12 | /* ********* HuffmanTree ********************/ 13 | // 数据结构 14 | typedef struct HTNode *HuffmanTree; 15 | struct HTNode{ 16 | int Weight; // 结点的权值 17 | HuffmanTree Left; 18 | HuffmanTree Right; 19 | }; 20 | 21 | /* ********* MinHeap ************************/ 22 | 23 | // 数据结构 24 | typedef struct HNode *MinHeap; 25 | struct HNode { 26 | ElementType *Data; // 存储堆元素的数组 27 | int Size; // 堆的当前元素的个数 28 | int Capacity; // 堆的最大容量 29 | }; 30 | 31 | HuffmanTree mini; 32 | 33 | 34 | // Create a heap 35 | MinHeap CreateHeap(void) 36 | { 37 | MinHeap H = (MinHeap)malloc(sizeof(struct HNode)); 38 | H->Data = (ElementType*)malloc((MaxSize+1) * sizeof(ElementType)); // 因为这里是一个数组,需要分配空间 39 | H->Size = 0; // 当前是空的 40 | H->Capacity = MaxSize; // 堆的最大容量 41 | H->Data[0] = mini; /* 定义“哨兵”为小于堆中所有可能元素的值,便于以后操作 */ 42 | return H; 43 | } 44 | 45 | // Full 46 | bool IsHeapFull(MinHeap H){ 47 | return (H->Size == H->Capacity); 48 | } 49 | 50 | // Empty 51 | bool IsHeapEmpty(MinHeap H){ 52 | return (H->Size == 0); 53 | } 54 | 55 | // Insert a node to a minheap 56 | void InsertMinHeap(MinHeap H, ElementType item) 57 | { 58 | int i; 59 | if (IsHeapFull(H)){ 60 | printf("FULL\n"); 61 | return; 62 | } 63 | i = ++H->Size; // H->Size++; i = H->Size; 把新增元素放在末尾H->Size++的位置上 64 | 65 | for(; H->Data[i/2]->Weight > item->Weight; i/=2){ // 其父节点大于它 66 | H->Data[i] = H->Data[i/2]; // 把它的父节点,向下过滤, 插入的item向上过滤 67 | } 68 | // 当它的父结点[i/2]比它小的时候, 符合条件,跳出循环 69 | H->Data[i] = item; // 填上item 70 | } 71 | 72 | 73 | 74 | // Delete the root(the minimum) from a minheap 75 | ElementType DeleteMin(MinHeap H) 76 | { 77 | int parent, child; 78 | ElementType MinItem, temp; 79 | if(IsHeapEmpty(H)){ 80 | printf("Empty\n"); 81 | return ERROR; 82 | } 83 | 84 | MinItem = H->Data[1]; // 取出最小值 85 | /* 用最小堆中最后一个元素从根节点开始向上过滤下层节点 */ 86 | temp = H->Data[H->Size]; // 把堆中最后一个值,交给temp 87 | H->Size--; 88 | 89 | for(parent=1; parent*2 <= H->Size; parent=child) 90 | { 91 | child = parent*2; // 左儿子 92 | 93 | /* child=左右儿子中小的那个, 当右儿子存在,且右儿子的值比左儿子小时,让child=右儿子 */ 94 | if((child!= H->Size) && 95 | (H->Data[child]->Weight > H->Data[child+1]->Weight)) 96 | child++; 97 | 98 | /* 当temp比child的值小时跳出循环 */ 99 | if (temp->Weight <= H->Data[child]->Weight) 100 | break; 101 | else 102 | H->Data[parent] = H->Data[child]; //当parent < child,这个parent位置上变为child的值 103 | } 104 | H->Data[parent] = temp; 105 | return MinItem; 106 | } 107 | 108 | 109 | // 堆的排序(建立最小堆) 把一个完全二叉树调整为最小堆 110 | void PercDown( MinHeap H, int p) 111 | {// 下滤函数, 将Minheap中以H->Data[p]为根的子堆调整为最小堆 112 | int parent, child; 113 | ElementType X; 114 | 115 | X = H->Data[p]; // 取出根节点的值 116 | for(parent = p; parent*2 <= H->Size; parent = child) 117 | { 118 | child = parent * 2; 119 | if( (child != H->Size) && (H->Data[child]->Weight > H->Data[child+1]->Weight)) 120 | { 121 | child++; 122 | } 123 | if (X->Weight <= H->Data[child]->Weight) 124 | break; 125 | else // 将X下滤 126 | H->Data[parent] = H->Data[child]; 127 | } 128 | H->Data[parent] = X; 129 | } 130 | 131 | void BuildMinHeap(MinHeap H){ // 调整H->Data[]中的元素,使满足最小堆的有序新,这里假设H->Size个元素已经存在H->Data中了 132 | int i; 133 | for(i = H->Size/2; i>0; i--) 134 | {// 从最后一个结点的父节点(Size/2)开始,到根节点(1)为止 135 | PercDown(H, i); 136 | } 137 | } 138 | 139 | 140 | 141 | /* ********* HuffmanTree *************/ 142 | // 数据结构 143 | // typedef struct HTNode *HuffmanTree; 144 | // struct HTNode{ 145 | // int Weight; // 结点的权值 146 | // HuffmanTree Left; 147 | // HuffmanTree Right; 148 | // }; 149 | 150 | // 初始化 151 | HuffmanTree CreateHuffman(){ 152 | HuffmanTree HFT; 153 | HFT = (HuffmanTree) malloc(sizeof(struct HTNode)); 154 | HFT->Left = NULL; 155 | HFT->Right = NULL; 156 | return HFT; 157 | } 158 | 159 | // Create 160 | HuffmanTree Huffman(MinHeap H) 161 | { // 这里最小堆的元素类型ElementType为HuffmanTree 162 | // 假设 H->Size个权值已经存在在 H->Data[]->Weight里了 163 | int i, N; 164 | HuffmanTree T; 165 | BuildMinHeap(H); // 将H->Data[]按照权重调整为最小堆 166 | N = H->Size; 167 | for(i=1; i < N; i++) // 做size-1次合并 168 | { 169 | T = (HuffmanTree)malloc(sizeof(struct HTNode)); // 建立新结点 170 | 171 | T->Left = DeleteMin(H);/*从最小堆中删除一个结点,作为新T的左子结点*/ 172 | T->Right = DeleteMin(H); 173 | /*计算新权值*/ 174 | T->Weight = (T->Left->Weight) + (T->Right->Weight); 175 | InsertMinHeap( H, T ); /*将新T插入最小堆*/ 176 | } 177 | T = DeleteMin(H); // 最小堆中的最后一个元素就是指向Huffman树根节点的指针 178 | return T; 179 | } 180 | 181 | //计算最优编码长度Weighted Path Length 182 | int WPL(HuffmanTree H, int depth){ // Depth从0开始 183 | if(!H->Left && !H->Right) 184 | return (depth * H->Weight); 185 | else{ // 有左右孩子,WPL= 左WPL+右WPL 186 | return ( WPL(H->Left, depth+1)+ 187 | WPL(H->Right, depth+1) ); 188 | } 189 | 190 | } 191 | /* ************************************* */ 192 | int Min(int a, int b){ 193 | return aWeight = - INFINITY; 238 | MinHeap H = CreateHeap(); 239 | // 读数据 240 | scanf("%d", &N); 241 | H->Size = N; 242 | for(i=1; i<=N; i++){ 243 | getchar(); // 读掉空格和回车 244 | scanf("%c %d", &c[i], &f[i]); 245 | HFT = (HuffmanTree) malloc(sizeof(struct HTNode)); 246 | HFT->Left = NULL; 247 | HFT->Right = NULL; 248 | HFT->Weight = f[i]; 249 | H->Data[i] = HFT; 250 | } 251 | // 建立huffman树 252 | HFT = Huffman(H); 253 | // printf("Weight= %d\n", HFT->Weight); 254 | 255 | // 计算最优编码长度WPL 256 | wpl = WPL(HFT, 0); 257 | // printf("wpl= %d\n", wpl); 258 | 259 | // 读学生的数据 260 | scanf("%d", &M); 261 | for(j=0; j 3 | #include 4 | #include 5 | #define MaxVertexNum 10 6 | #define MaxSize 11 7 | #define INFINITY 65535 8 | #define ElementType int 9 | #define ERROR -1 10 | 11 | typedef int Vertex; // 用顶点下标表示顶点,为整形 12 | typedef int WeightType; // 边的权值设为int 13 | 14 | /**************** Queue ******************/ 15 | struct QNode { 16 | ElementType *Data; 17 | int rear; 18 | int front; 19 | }; 20 | typedef struct QNode *Queue; 21 | 22 | // 创建队 23 | Queue CreateQueue(void) 24 | { 25 | Queue Q = (Queue)malloc(sizeof(struct QNode)); 26 | Q->Data = (ElementType*)malloc(MaxSize * sizeof(ElementType)); 27 | Q->front = Q->rear = 0; 28 | return Q; 29 | } 30 | 31 | // 空 32 | bool IsEmpty(Queue Q) 33 | { 34 | return(Q->front == Q->rear); 35 | } 36 | 37 | // 满 38 | bool IsFull(Queue Q) 39 | { 40 | return ((Q->rear+1) % MaxSize == Q->front ); 41 | } 42 | 43 | // 入队 44 | void AddQ( Queue PtrQ, ElementType item) { 45 | // if (IsFull(Q)) 46 | if ( (PtrQ->rear+1) % MaxSize == PtrQ->front ) 47 | { 48 | printf("队列满"); 49 | return; 50 | } 51 | PtrQ->rear = (PtrQ->rear + 1)% MaxSize; 52 | PtrQ->Data[PtrQ->rear] = item; 53 | } 54 | 55 | // 出队 56 | ElementType DeleteQ ( Queue PtrQ ) // front和rear相同 57 | { 58 | // if (IsEmpty(Q)) 59 | if ( PtrQ->front == PtrQ->rear ) 60 | { 61 | printf("队列空"); 62 | return ERROR; 63 | } 64 | else 65 | { 66 | PtrQ->front = (PtrQ->front+1)% MaxSize; // front往后移一位指向第一个元素 67 | return PtrQ->Data[PtrQ->front]; 68 | } 69 | } 70 | 71 | /* *********************************** */ 72 | 73 | 74 | /* ********************* MGraph *******************/ 75 | // Graph struct 76 | typedef struct GNode * PtrGNode; 77 | struct GNode 78 | { 79 | int Nv; 80 | int Ne; 81 | WeightType G[MaxVertexNum][MaxVertexNum]; 82 | // DataType Data[MAX]; // 存顶点的数据 83 | }; 84 | typedef PtrGNode MGraph; 85 | 86 | // Edge struct 87 | typedef struct ENode *PtrENode; 88 | struct ENode 89 | { 90 | Vertex V1, V2; 91 | }; 92 | typedef PtrENode Edge; 93 | 94 | // 初始化有VertexNum个顶点但没有边的图 95 | MGraph CreateGraph(int VertexNum) 96 | { 97 | MGraph Graph; 98 | Vertex v,w; 99 | Graph = (MGraph)malloc(sizeof(struct GNode)); 100 | Graph->Nv = VertexNum; 101 | Graph->Ne = 0; 102 | 103 | for(v=0; vG[v][w] = 0; 106 | } 107 | } 108 | return Graph; 109 | } 110 | 111 | 112 | // 插入边 113 | void InsertEdge(MGraph Graph, Edge E){ 114 | // 插入 115 | Graph ->G[E->V1][E->V2] = 1; 116 | //若是无向图,还要插入 117 | Graph->G[E->V2][E->V1] = 1; 118 | } 119 | 120 | // 建图 121 | MGraph BuildGraph(){ 122 | MGraph Graph; 123 | Edge E; 124 | Vertex V; 125 | int Nv, i; 126 | 127 | scanf("%d", &Nv); 128 | Graph = CreateGraph(Nv); 129 | scanf("%d", &(Graph->Ne)); 130 | 131 | if (Graph->Ne != 0) 132 | { 133 | E = (Edge)malloc(sizeof(struct ENode)); // 创建边结点 134 | for (i=0; iNe; i++) 135 | { 136 | scanf("%d %d", &E->V1, &E->V2); 137 | InsertEdge(Graph, E); 138 | } 139 | } 140 | return Graph; 141 | } 142 | 143 | 144 | /* ********************* DFS *******************/ 145 | // 邻接矩阵深度优先DFS遍 146 | 147 | bool IsEdge(MGraph Graph, Vertex V, Vertex W){ 148 | return Graph->G[V][W]>0? true : false; 149 | } 150 | 151 | 152 | 153 | void DFS( MGraph Graph, Vertex V, bool Visited[], Queue Q) 154 | { 155 | Vertex W; 156 | AddQ(Q, V); 157 | Visited[V] = true; 158 | /* 对V的每个邻接点W */ 159 | for( W=0; W < Graph->Nv; W++ ) // 对图中的每个顶点遍历 160 | if ( !Visited[W] && IsEdge(Graph, V, W)) 161 | DFS( Graph, W, Visited, Q); 162 | } 163 | 164 | /* ********************* BFS *******************/ 165 | void BFS ( MGraph Graph, Vertex S, bool Visited[],Queue Q) 166 | { /* 以S为出发点对邻接矩阵存储的图Graph进行BFS搜索 */ 167 | Queue Que; 168 | Vertex V, W; 169 | AddQ(Q, S); 170 | Que = CreateQueue(); /* 创建空队列, MaxSize为外部定义的常数 */ 171 | 172 | Visited[S] = true; /* 标记S已访问 */ 173 | AddQ(Que, S); 174 | 175 | while ( !IsEmpty(Que) ) { 176 | V = DeleteQ(Que); 177 | for( W=0; WNv; W++ ) /* 对图中的每个顶点W */ 178 | /* 若W是V的邻接点并且未访问过 */ 179 | if ( !Visited[W] && IsEdge(Graph, V, W) ) { 180 | AddQ(Q, W); 181 | Visited[W] = true; /* 标记W已访问 */ 182 | AddQ(Que, W); /* W入队列 */ 183 | } 184 | } /* while结束*/ 185 | } 186 | 187 | 188 | int main(int argc, char const *argv[]) 189 | { 190 | int i; 191 | Vertex V; 192 | MGraph Graph; 193 | Graph = BuildGraph(); 194 | // printf("%d\n", Graph->G[0][4]); 195 | 196 | 197 | bool Visited[MaxVertexNum] = {false}; 198 | Queue Q = CreateQueue(); 199 | 200 | for( V=0; V < Graph->Nv; V++){ 201 | if (Visited[V] == false){ 202 | DFS(Graph, V, Visited, Q); 203 | printf("{ "); 204 | while (!IsEmpty(Q)) 205 | { 206 | printf("%d ", DeleteQ(Q)); 207 | } 208 | printf("}\n"); 209 | } 210 | } 211 | 212 | 213 | for (i=0; iNv; i++) 214 | Visited[i] = false; 215 | for( V=0; V < Graph->Nv; V++){ 216 | if (Visited[V] == false){ 217 | BFS(Graph, V, Visited, Q); 218 | printf("{ "); 219 | while (!IsEmpty(Q)) 220 | { 221 | printf("%d ", DeleteQ(Q)); 222 | } 223 | printf("}\n"); 224 | } 225 | } 226 | 227 | return 0; 228 | } -------------------------------------------------------------------------------- /PTA_Exercise/06-图2 Saving James Bond - Easy Version.c: -------------------------------------------------------------------------------- 1 | // 06-图2 Saving James Bond - Easy Version 2 | include 3 | #include 4 | #include 5 | #include 6 | #define MAX 101 7 | 8 | struct crocodile 9 | { 10 | int hori; 11 | int vert; 12 | bool shore; 13 | bool jump; 14 | bool visited; 15 | }; 16 | typedef struct crocodile croco[MAX]; 17 | croco c; // 全局变量数组c,每一项都是struct crocodile 18 | int safe = 0; // 全局变量 19 | 20 | int Distance(int x1, int y1, int x2, int y2){ 21 | int distance = (int)sqrt( pow((y2-y1), 2) + pow((x2-x1), 2)); 22 | return distance; 23 | } 24 | 25 | bool NearShore(int x, int y, int D){ 26 | if((50 -abs(x)) <= D || (50-abs(y)) <= D ) 27 | return true; 28 | else 29 | return false; 30 | } 31 | 32 | bool FirstJump(int x, int y, int D){ 33 | int dist = (int)sqrt(pow(x,2)+pow(y,2)); 34 | if( dist <= D + 15/2) 35 | return true; 36 | else 37 | return false; 38 | } 39 | 40 | // 初始化 41 | void Initial(int N, int D){ 42 | int x, y; 43 | for(int i=0; ivisited = true; 57 | if (v->shore) 58 | safe = 1; 59 | for(int i=0; ihori, v->vert, c[i].hori, c[i].vert); 61 | if( dist <= D && (c[i].visited == false)) 62 | DFS(&c[i], N, D); 63 | } 64 | return safe; 65 | 66 | } 67 | 68 | 69 | 70 | int main(int argc, char const *argv[]) 71 | { 72 | int N, D, i; 73 | scanf("%d %d", &N, &D); 74 | Initial(N, D); 75 | bool result = false; 76 | 77 | for(i=0; i 3 | #include 4 | #include 5 | #include 6 | #define MaxSize 101 7 | #define ElementType int 8 | #define ERROR 999 9 | 10 | /**************** Queue ******************/ 11 | struct QNode { 12 | ElementType *Data; 13 | int rear; 14 | int front; 15 | }; 16 | typedef struct QNode *Queue; 17 | 18 | // 创建队 19 | Queue CreateQueue(void) 20 | { 21 | Queue Q = (Queue)malloc(sizeof(struct QNode)); 22 | Q->Data = (ElementType*)malloc(MaxSize * sizeof(ElementType)); 23 | Q->front = Q->rear = 0; 24 | return Q; 25 | } 26 | 27 | // 空 28 | bool IsEmpty(Queue Q) 29 | { 30 | return(Q->front == Q->rear); 31 | } 32 | 33 | // 满 34 | bool IsFull(Queue Q) 35 | { 36 | return ((Q->rear+1) % MaxSize == Q->front ); 37 | } 38 | 39 | // 入队 40 | void AddQ( Queue PtrQ, ElementType item) { 41 | // if (IsFull(Q)) 42 | if ( (PtrQ->rear+1) % MaxSize == PtrQ->front ) 43 | { 44 | printf("队列满"); 45 | return; 46 | } 47 | PtrQ->rear = (PtrQ->rear + 1)% MaxSize; 48 | PtrQ->Data[PtrQ->rear] = item; 49 | } 50 | 51 | // 出队 52 | ElementType DeleteQ ( Queue PtrQ ) // front和rear相同 53 | { 54 | // if (IsEmpty(Q)) 55 | if ( PtrQ->front == PtrQ->rear ) 56 | { 57 | printf("队列空"); 58 | return ERROR; 59 | } 60 | else 61 | { 62 | PtrQ->front = (PtrQ->front+1)% MaxSize; // front往后移一位指向第一个元素 63 | return PtrQ->Data[PtrQ->front]; 64 | } 65 | } 66 | 67 | /**************** Stack ******************/ 68 | 69 | typedef struct SNode *Stack; //结构指针 70 | struct SNode{ 71 | ElementType *Data; //数组 72 | int Top; // 栈顶位置的数组下标 73 | }; 74 | 75 | 76 | // 创建堆栈 77 | Stack CreateStack(void) 78 | { 79 | Stack S = (Stack)malloc(sizeof(struct SNode)); 80 | S->Data = (ElementType*)malloc(MaxSize* sizeof(ElementType)); 81 | S->Top = -1; 82 | 83 | return S; 84 | } 85 | 86 | // 入栈 87 | void Push( Stack PtrS, ElementType item ) // stack这个类型的指针 88 | { 89 | if ( PtrS->Top == MaxSize-1 ) // 判断满不满。从 0 到 MaxSize-1 90 | { 91 | printf("堆栈满"); 92 | return; 93 | }else 94 | { 95 | PtrS->Data[++(PtrS->Top)] = item; 96 | /* 相当于: 97 | (PtrS->Top)++; 98 | PtrS->Data[PtrS->Top] = item; 99 | */ 100 | return; 101 | } 102 | } 103 | 104 | // 空 105 | bool IsStackEmpty(Stack PtrS){ 106 | if ( PtrS->Top == -1 ) 107 | return true; 108 | else return false; 109 | } 110 | 111 | // 出栈 112 | ElementType Pop( Stack PtrS ) 113 | { 114 | if ( IsStackEmpty(PtrS) ) { 115 | printf("堆栈空"); 116 | return ERROR; 117 | } 118 | else 119 | return ( PtrS->Data[(PtrS->Top)--] ); // return 出下标为top的这个值,同时Top-1 120 | } 121 | /**************** Stack ******************/ 122 | 123 | struct crocodile 124 | { 125 | int hori; 126 | int vert; 127 | bool shore; 128 | bool jump; 129 | } c[MaxSize]; // 全局变量,每一个数记录一个鳄鱼的结构 130 | 131 | struct Dist 132 | { 133 | int dist[MaxSize]; 134 | } Dist[MaxSize]; // 全局变量,记录要跳几下 135 | 136 | struct Path 137 | { 138 | int path[MaxSize]; 139 | }Path[MaxSize]; // 全局变量,记录路径 140 | 141 | 142 | int Distance(int x1, int y1, int x2, int y2){ 143 | int distance = (int)sqrt( pow((y2-y1), 2) + pow((x2-x1), 2)); 144 | return distance; 145 | } 146 | 147 | bool NearShore(int x, int y, int D){ 148 | if((50 -abs(x)) <= D || (50-abs(y)) <= D ) 149 | return true; 150 | else 151 | return false; 152 | } 153 | 154 | bool FirstJump(int x, int y, int D){ 155 | int distance = (int)sqrt(pow(x,2)+pow(y,2)); 156 | if( distance <= D + 15/2) 157 | return true; 158 | else 159 | return false; 160 | } 161 | 162 | // 初始化, 读入数据 163 | void Initial(int N, int D){ 164 | int x, y; 165 | for(int i=0; i= (50 - D/2)){ 229 | printf("1\n"); 230 | return 0; 231 | } 232 | 233 | for(i=0; i 0){ // 找到可跳上案,并且连通的路径 242 | if(Dist[i].dist[j] < min){ // 找到最小路径 243 | min = Dist[i].dist[j]; 244 | FistDistance = FirstJumpDistance; 245 | minj = j; 246 | mini = i; 247 | }else if((Dist[i].dist[j] = min) && (FirstJumpDistance < FistDistance)){ 248 | FistDistance = FirstJumpDistance; 249 | minj = j; 250 | mini = i; 251 | } 252 | 253 | } 254 | } 255 | } 256 | } // for循环结束 257 | if (min == MaxSize) // 无可连通且跳上岸的鳄鱼 258 | printf("0\n"); 259 | else 260 | { 261 | printf("%d\n", min+2); // 加2跳:从岛上到第一个鳄鱼的和从最后一个鳄鱼到岸上 262 | S = CreateStack(); 263 | while(minj >= 0){ 264 | Push(S, minj); // 入栈 265 | minj = Path[mini].path[minj]; 266 | } 267 | while(!IsStackEmpty(S)){ 268 | minj = Pop(S); // 出栈,直到栈空 269 | printf("%d %d\n", c[minj].hori, c[minj].vert); 270 | } 271 | } 272 | return 0; 273 | } 274 | 275 | -------------------------------------------------------------------------------- /PTA_Exercise/07-图4 哈利·波特的考试.c: -------------------------------------------------------------------------------- 1 | //07-图4 哈利·波特的考试 2 | #include 3 | #include 4 | #define MAX 101 5 | #define INFINITY 1000 6 | 7 | typedef int Graph[MAX][MAX]; 8 | 9 | // 全局变量 10 | Graph G, D; 11 | int Nv,Ne; 12 | 13 | void BuildGraph(void) 14 | { 15 | int i,j,v1,v2,w; 16 | scanf("%d", &Nv); 17 | // 初始化 18 | for(i=0; i maxdist)) 74 | maxdist = D[i][j]; 75 | } 76 | // 找最大值中的最小值 77 | if (maxdist < min) 78 | { 79 | min = maxdist; 80 | n = i + 1; // 下标从0开始,+1 81 | } 82 | } 83 | // 如果图不连通 84 | if (min == INFINITY) 85 | printf("0\n"); 86 | else 87 | printf("%d %d\n", n, min ); 88 | } 89 | 90 | 91 | int main(int argc, char const *argv[]) 92 | { 93 | BuildGraph(); 94 | Floyd(); 95 | // PrintGraph(D); 96 | FindAnimal(); 97 | return 0; 98 | } 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /PTA_Exercise/07-图6 旅游规划.c: -------------------------------------------------------------------------------- 1 | // 07-图6 旅游规划 2 | #include 3 | #include 4 | #include 5 | #define MaxVertexNum 501 6 | #define INFINITY 65535 7 | #define ERROR 999 8 | typedef int Vertex; // 用顶点下标表示顶点,为整形 9 | typedef int DataType; 10 | typedef int WeightType; 11 | 12 | /* ********************* MGraph *******************/ 13 | // Graph struct 14 | typedef struct GNode * PtrGNode; 15 | struct GNode 16 | { 17 | int Nv; 18 | int Ne; 19 | WeightType G[MaxVertexNum][MaxVertexNum]; // 放distance 20 | WeightType C[MaxVertexNum][MaxVertexNum]; // 放cost 21 | // DataType Data[MAX]; // 存顶点的数据 22 | }; 23 | typedef PtrGNode MGraph; 24 | 25 | // Edge struct 边 26 | typedef struct ENode *PtrENode; 27 | struct ENode 28 | { 29 | Vertex V1, V2; 30 | WeightType Weight; 31 | WeightType Cost; 32 | }; 33 | typedef PtrENode Edge; 34 | 35 | // 初始化有VertexNum个顶点但没有边的图 36 | MGraph CreateGraph(int VertexNum, int EdgeNum) 37 | { 38 | MGraph Graph; 39 | Vertex v,w; 40 | Graph = (MGraph)malloc(sizeof(struct GNode)); 41 | Graph->Nv = VertexNum; 42 | Graph->Ne = EdgeNum; 43 | 44 | for(v=0; vG[v][w] = INFINITY; 47 | Graph->C[v][w] = INFINITY; 48 | } 49 | } 50 | return Graph; 51 | } 52 | 53 | 54 | // 根据读入的数据建图 55 | void InsertEdge(MGraph Graph, Edge E){ 56 | Graph->G[E->V1][E->V2] = E->Weight; 57 | Graph->G[E->V2][E->V1] = E->Weight; 58 | Graph->C[E->V1][E->V2] = E->Cost; 59 | Graph->C[E->V2][E->V1] = E->Cost; 60 | } 61 | 62 | // 建图 63 | MGraph BuildGraph(int VertexNum, int EdgeNum){ 64 | MGraph Graph; 65 | Edge E; 66 | int i; 67 | 68 | Graph = CreateGraph(VertexNum, EdgeNum); 69 | 70 | if (Graph->Ne != 0) 71 | { 72 | E = (Edge)malloc(sizeof(struct ENode)); // 创建边结点 73 | for (i=0; iNe; i++) 74 | { 75 | scanf("%d %d %d %d", &E->V1, &E->V2, &E->Weight, &E->Cost); 76 | InsertEdge(Graph, E); 77 | } 78 | } 79 | return Graph; 80 | } 81 | 82 | 83 | /* ********************* Dijkstra *******************/ 84 | Vertex FindMinDist(MGraph Graph, int dist[], int collected[]){ 85 | Vertex MinV, V; 86 | int MinDist = INFINITY; 87 | 88 | for(V=0; V < Graph->Nv; V++){ 89 | if (collected[V] == false && dist[V]< MinDist){ /* 若V未被收录,且dist[V]更小 */ 90 | MinDist = dist[V]; 91 | MinV = V; /* 更新对应顶点 */ 92 | } 93 | } 94 | if (MinDist < INFINITY) /* 若找到最小dist */ 95 | return MinV; /* 返回对应的顶点下标 */ 96 | else 97 | return ERROR; /* 若这样的顶点不存在,返回错误标记 */ 98 | } 99 | 100 | 101 | bool Dijkstra(MGraph Graph, int dist[], int cost[], int path[], Vertex S) 102 | { 103 | int collected[MaxVertexNum]; 104 | Vertex V, W; 105 | 106 | // 初始化dist[], path[], cost[], collected[],邻接矩阵中不存在边的标记为INFINITY 107 | for(V=0; V < Graph->Nv; V++){ 108 | dist[V] = Graph->G[S][V]; 109 | cost[V] = Graph->C[S][V]; 110 | if (dist[V] < INFINITY) // S到V有直接路径 111 | path[V] = S; 112 | else 113 | path[V] = -1; 114 | collected[V] = false; 115 | } 116 | // 先将起点收入到集合中 117 | dist[S] = 0; 118 | cost[S] = 0; 119 | collected[S] = true; 120 | 121 | while(1) 122 | { 123 | V = FindMinDist(Graph, dist, collected); /* V = 未被收录顶点中dist最小者 */ 124 | if (V == ERROR) /* 若这样的V已经不存在 */ 125 | break; 126 | collected[V] = true; 127 | for(W=0; W < Graph->Nv; W++){ // 对图中的每个顶点W 128 | if(collected[W] == false && Graph->G[V][W] < INFINITY) // V的每个未被访问过的邻接点W 129 | { 130 | if ( Graph->G[V][W] < 0 ) /* 若有负边 */ 131 | return false; /* 不能正确解决,返回错误标记 */ 132 | 133 | /* 若收录V使得dist[W]变小 */ 134 | if ( dist[V]+ Graph->G[V][W] < dist[W] ) { 135 | dist[W] = dist[V]+ Graph->G[V][W]; // 更新dist[W] 136 | path[W] = V; // 更新S到W的路径 137 | cost[W] = cost[V] + Graph->C[V][W]; // 更新cost[w] 138 | }else if (dist[V]+ Graph->G[V][W] == dist[W] 139 | && cost[V] + Graph->C[V][W] < cost[W]) // 距离一样但是费用更低,则更新费用 140 | { 141 | cost[W] = cost[V] + Graph->C[V][W]; 142 | path[W] = V; 143 | } 144 | } 145 | } // for循环结束, 每个V的邻接点W遍历完 146 | }// while结束 147 | return true; 148 | } 149 | 150 | /* ********************************** */ 151 | 152 | 153 | int main(int argc, char const *argv[]) 154 | { 155 | int N,M,S,D; 156 | int dist[MaxVertexNum], cost[MaxVertexNum], path[MaxVertexNum]; 157 | scanf("%d %d %d %d", &N, &M,&S, &D); 158 | MGraph Graph = BuildGraph(N, M); 159 | if(Dijkstra(Graph, dist, cost, path, S)) 160 | printf("%d %d\n", dist[D], cost[D]); 161 | else 162 | printf("Error\n"); 163 | 164 | return 0; 165 | } 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /PTA_Exercise/08-图8 How Long Does It Take.c: -------------------------------------------------------------------------------- 1 | //08-图8 How Long Does It Take 2 | #include 3 | #include 4 | #include 5 | #define MaxVertexNum 101 6 | #define MaxSize 101 7 | #define ERROR -1 8 | #define INFINITY 65535 9 | 10 | typedef int Vertex; // 用顶点下标表示顶点,为整形 11 | typedef int WeightType; // 边的权值设为int 12 | 13 | 14 | /* ********************* LGraph *******************/ 15 | // 边的定义 16 | typedef struct ENode *PtrENode; 17 | struct ENode 18 | { 19 | Vertex V1, V2; 20 | WeightType Weight; 21 | }; 22 | typedef PtrENode Edge; 23 | 24 | // 邻接点的定义 边表 25 | typedef struct AdjVNode *PtrAdjVNode; 26 | struct AdjVNode 27 | { 28 | Vertex AdjV; // 邻接点下标 29 | WeightType Weight; // 边权重 30 | PtrAdjVNode Next; // 指向下一个邻接点的致指针 31 | }; 32 | 33 | // 顶点表头结点的定义 顶点表 34 | struct VNode{ 35 | PtrAdjVNode FirstEdge; // 边表头指针 36 | // DataType Data; // 存顶点数据,一般不用 37 | }; 38 | typedef struct VNode AdjList[MaxVertexNum]; 39 | 40 | // Graph struct 41 | /* 图结点的定义 */ 42 | typedef struct GNode * PtrGNode; 43 | struct GNode 44 | { 45 | int Nv; //顶点数 46 | int Ne; // 边数 47 | AdjList G; // 邻接表. 是一个size为MaxVertexNum的数组,每一个元素都是一个结点VNode 48 | }; 49 | typedef PtrGNode LGraph; 50 | 51 | // 初始化有VertexNum个顶点但没有边的图 52 | LGraph CreateGraph(int VertexNum) 53 | { 54 | LGraph Graph; 55 | Vertex V; 56 | 57 | Graph = (LGraph)malloc(sizeof(struct GNode)); 58 | Graph->Nv = VertexNum; 59 | Graph->Ne = 0; 60 | 61 | for(V=0; VNv; V++) 62 | Graph->G[V].FirstEdge = NULL; // 每一个顶点v的FirstEdge都是空的, 编号从0到 Graph->Nv-1 63 | return Graph; 64 | } 65 | 66 | // 插入一条边 67 | void InsertEdge (LGraph Graph, Edge E) /* 插入边 */ 68 | { 69 | PtrAdjVNode NewNode; 70 | 71 | /* 为V2建立新的邻接点 */ 72 | NewNode = (PtrAdjVNode)malloc(sizeof(struct AdjVNode)); 73 | NewNode->AdjV = E->V2; 74 | NewNode->Weight = E->Weight; 75 | /* 将V2插入V1的表头, 在头上插入 */ 76 | NewNode->Next = Graph->G[E->V1].FirstEdge; 77 | Graph->G[E->V1].FirstEdge = NewNode; 78 | } 79 | 80 | 81 | // 建图 82 | LGraph BuildGraph(){ 83 | LGraph Graph; 84 | Edge E; 85 | Vertex V, V1, V2; 86 | int Nv, i; 87 | 88 | scanf("%d", &Nv); 89 | Graph = CreateGraph(Nv); 90 | 91 | scanf("%d", &(Graph->Ne)); 92 | if (Graph->Ne != 0) 93 | { 94 | E = (Edge)malloc(sizeof(struct ENode)); // 创建边结点 95 | for (i=0; iNe; i++) 96 | { 97 | /* 读入边,格式为 起点 终点 权重 */ 98 | scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); 99 | InsertEdge(Graph, E); 100 | } 101 | } 102 | return Graph; 103 | } 104 | 105 | 106 | 107 | /**************** Queue ******************/ 108 | #define ElementType int 109 | 110 | struct QNode { 111 | ElementType *Data; 112 | int rear; 113 | int front; 114 | }; 115 | typedef struct QNode *Queue; 116 | 117 | // 创建队 118 | Queue CreateQueue(int N) 119 | { 120 | Queue Q = (Queue)malloc(sizeof(struct QNode)); 121 | Q->Data = (ElementType*)malloc(N * sizeof(ElementType)); 122 | Q->front = Q->rear = 0; 123 | return Q; 124 | } 125 | 126 | // 空 127 | bool IsEmpty(Queue Q) 128 | { 129 | return(Q->front == Q->rear); 130 | } 131 | 132 | // 满 133 | bool IsFull(Queue Q) 134 | { 135 | return ((Q->rear+1) % MaxSize == Q->front ); 136 | } 137 | 138 | // 入队 139 | void AddQ( Queue PtrQ, ElementType item) { 140 | // if (IsFull(Q)) 141 | if ( (PtrQ->rear+1) % MaxSize == PtrQ->front ) 142 | { 143 | printf("队列满"); 144 | return; 145 | } 146 | PtrQ->rear = (PtrQ->rear + 1)% MaxSize; 147 | PtrQ->Data[PtrQ->rear] = item; 148 | } 149 | 150 | // 出队 151 | ElementType DeleteQ ( Queue PtrQ ) // front和rear相同 152 | { 153 | // if (IsEmpty(Q)) 154 | if ( PtrQ->front == PtrQ->rear ) 155 | { 156 | printf("队列空"); 157 | return ERROR; 158 | } 159 | else 160 | { 161 | PtrQ->front = (PtrQ->front+1)% MaxSize; // front往后移一位指向第一个元素 162 | return PtrQ->Data[PtrQ->front]; 163 | } 164 | } 165 | 166 | /* *************** TopSort ***************** */ 167 | int MAX(int a, int b){ 168 | return a>b? a:b; 169 | } 170 | 171 | 172 | 173 | void TopSort(LGraph Graph, int Earliest[]){ 174 | int indegree[MaxVertexNum]={0}, cnt=0, MaxTime=0; 175 | Vertex V; 176 | PtrAdjVNode W; 177 | Queue Q = CreateQueue(Graph->Nv); 178 | 179 | // 计算入度 180 | for (V = 0; V < Graph->Nv; V++){ 181 | for(W=Graph->G[V].FirstEdge; W; W=W->Next) 182 | indegree[W->AdjV]++; 183 | } 184 | 185 | // 将所有入度为0的顶点入队 186 | for (V=0; VNv; V++){ 187 | if(indegree[V] == 0) 188 | AddQ(Q, V); 189 | Earliest[V] = 0; 190 | } 191 | 192 | // topsort 193 | while (!IsEmpty(Q)){ 194 | V =DeleteQ(Q); 195 | cnt++; 196 | for(W=Graph->G[V].FirstEdge; W; W=W->Next){ 197 | indegree[W->AdjV]--; // V的每一个邻接点的入度-1 198 | Earliest[W->AdjV] = MAX(Earliest[W->AdjV], Earliest[V] + W->Weight); // 如果有更长的时间,则更新时间 199 | if(indegree[W->AdjV] == 0) // 若删除V使得W->AdjV入度为0 200 | AddQ(Q, W->AdjV); 201 | } 202 | } // while循环结束 203 | 204 | if (cnt != Graph->Nv) 205 | printf("Impossible\n"); // 没把所有顶点都收进来,说明有回路 206 | else 207 | { 208 | for (V=0; VNv; V++) 209 | { 210 | if (MaxTime < Earliest[V]) 211 | MaxTime = Earliest[V]; 212 | } 213 | printf("%d\n", MaxTime); 214 | } 215 | } 216 | 217 | 218 | /* ******************************** */ 219 | 220 | 221 | int main(int argc, char const *argv[]) 222 | { 223 | LGraph Graph; 224 | int Earliest[MaxSize]; 225 | 226 | Graph = BuildGraph(); 227 | TopSort(Graph, Earliest); 228 | 229 | return 0; 230 | } 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /PTA_Exercise/09-排序2 Insert or Merge.c: -------------------------------------------------------------------------------- 1 | // 09-排序2 Insert or Merge 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define ElementType int 7 | 8 | 9 | /* *************** 插入排序 ****************** */ 10 | void Insertion_Sort(ElementType A[], int N, int Round){ // Round 执行了几次 11 | ElementType Tmp; 12 | int P, i; 13 | for(P=0; P < Round; P++){ 14 | Tmp = A[P]; // 摸下一张牌 15 | for (i = P; i>0; i--) 16 | { 17 | if(A[i-1] > Tmp) // 若前一张牌比新摸的牌大 18 | A[i] = A[i-1]; // 移出空位 19 | else break; // 若新摸的牌比前一张牌大,则跳出循环 20 | } 21 | A[i] = Tmp; // 新牌落位 22 | 23 | } 24 | } 25 | 26 | /* *************** 归并排序 ****************** */ 27 | void Merge(ElementType A[], ElementType TempA[], 28 | int L, int R, int RightEnd) 29 | { 30 | int LeftEnd = R - 1; 31 | int Tmp = L; // 存放结果的数组的初始位置 32 | int Num = RightEnd - L + 1; // 一共有几个数据 33 | while (L <= LeftEnd && R <= RightEnd){ // 左和右都不为空 34 | if (A[L] <= A[R]) 35 | TempA[Tmp++] = A[L++]; 36 | else 37 | TempA[Tmp++] = A[R++]; 38 | } 39 | // 跳出循环时左边还有剩下的 40 | while (L <= LeftEnd) 41 | TempA[Tmp++] = A[L++]; 42 | // 跳出循环时右边还有剩下的 43 | while (R <= RightEnd) 44 | TempA[Tmp++] = A[R++]; 45 | 46 | // 把TmpA倒回到A, 从RightEnd倒着复制回去 47 | for(int i=0; i B[i+1]) 117 | break; 118 | } 119 | for(j=i+1; jB[j]) 136 | // break; 137 | // } 138 | // if (j 3 | #include 4 | #include 5 | #include 6 | #define ElementType int 7 | 8 | 9 | bool Identical(int A[],int B[],int N){ 10 | for(int i=0;i0; i--) 23 | { 24 | if(A[i-1] > Tmp) // 若前一张牌比新摸的牌大 25 | A[i] = A[i-1]; // 移出空位 26 | else break; // 若新摸的牌比前一张牌大,则跳出循环 27 | } 28 | A[i] = Tmp; // 新牌落位 29 | 30 | } 31 | } 32 | 33 | /* *************** 堆排序 ****************** */ 34 | void Swap(ElementType *a, ElementType *b){ 35 | ElementType c; 36 | c = *a; 37 | *a = *b; 38 | *b = c; 39 | } 40 | 41 | 42 | void PercDown(ElementType A[] , int p, int N) 43 | {// 下滤函数, 将Minheap中以H->Data[p]为根的子堆调整为最小堆 44 | int parent, child; 45 | ElementType X; 46 | 47 | X = A[p]; // 取出根节点的值 48 | for(parent = p; parent*2+1 <= N-1 ; parent = child) 49 | { 50 | child = parent*2+1; 51 | if( (child != N-1 ) && (A[child] < A[child+1])) 52 | { 53 | child++; 54 | } 55 | if (X >= A[child]) 56 | break; 57 | else // 将X下滤 58 | A[parent] = A[child]; 59 | } 60 | A[parent] = X; 61 | } 62 | 63 | 64 | int Heap_Sort(ElementType A[], ElementType B[], int N){ 65 | int i; 66 | for (i=N/2; i>=0; i--) // Build MaxHeap 67 | PercDown(A, i, N); 68 | for (i=N-1; i>0; i--){ 69 | Swap(&A[0], &A[i]); // DeleteMax 70 | PercDown(A, 0, i); // 重新整理成最大堆 71 | if (Identical(A, B, N)){ // 如果相同, 则再swap一次 72 | 73 | Swap(&A[0], &A[--i]); // DeleteMax 74 | PercDown(A, 0, i); // 重新整理成最大堆 75 | 76 | return 1; 77 | } 78 | 79 | } 80 | return 0; 81 | } 82 | 83 | 84 | /* *************************************** */ 85 | int IsInsertion(ElementType A[], ElementType B[], int N){ 86 | int i, j; 87 | for (i=0; i B[i+1]) 89 | break; 90 | } 91 | for(j=i+1; j 3 | #include 4 | 5 | #define MAXSIZE 10 6 | #define NotFound 0 7 | typedef int ElementType; 8 | 9 | typedef int Position; 10 | typedef struct LNode *List; 11 | struct LNode { 12 | ElementType Data[MAXSIZE]; 13 | Position Last; /* 保存线性表中最后一个元素的位置 */ 14 | }; 15 | 16 | List ReadInput(); /* 裁判实现,细节不表。元素从下标1开始存储 */ 17 | Position BinarySearch( List L, ElementType X ); 18 | 19 | int main() 20 | { 21 | List L; 22 | ElementType X; 23 | Position P; 24 | 25 | L = ReadInput(); 26 | scanf("%d", &X); 27 | P = BinarySearch( L, X ); 28 | printf("%d\n", P); 29 | 30 | return 0; 31 | } 32 | 33 | List ReadInput(){ 34 | List L; 35 | int i; 36 | L = (List)malloc(sizeof(struct LNode)); 37 | L->Data[0] = 0; 38 | scanf("%d", &L->Last); 39 | for (i=1; i<=L->Last; i++) 40 | scanf("%d", &L->Data[i]); 41 | return L; 42 | } 43 | 44 | Position BinarySearch( List L, ElementType X ){ 45 | int Left, Right, Mid; 46 | Left = 0; 47 | Right = L->Last; 48 | while (Left <= Right){ 49 | Mid = (Left + Right) / 2; 50 | if (X > L->Data[Mid]) 51 | Left = Mid + 1; 52 | else if (X < L->Data[Mid]) 53 | Right = Mid - 1; 54 | else // 相等,找到了 55 | return Mid; 56 | } 57 | return NotFound; 58 | } 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /PTA_Exercise/10-排序5 PAT Judge.c: -------------------------------------------------------------------------------- 1 | // 10-排序5 PAT Judge 2 | #include 3 | #include 4 | #include 5 | #define ElementType int 6 | #define MaxUser 10005 7 | #define MaxProb 6 8 | 9 | struct NScore 10 | { 11 | int ID; 12 | int s[MaxProb]; 13 | int total_score; 14 | int perfect; 15 | int rank; 16 | bool enable; 17 | }; 18 | struct NScore Student[MaxUser]; 19 | 20 | int compare3keys(const void *a, const void *b){ 21 | int k; 22 | // 对total_score做降序排序 23 | if ( ((const struct NScore*)a)->total_score < ((const struct NScore*)b)->total_score) 24 | k = 1; 25 | else if(((const struct NScore*)a)->total_score > ((const struct NScore*)b)->total_score) 26 | k = -1; 27 | else 28 | { // total_score相等, 按perfect降序排序 29 | if (((const struct NScore*)a)->perfect < ((const struct NScore*)b)->perfect) 30 | k = 1; 31 | else if (((const struct NScore*)a)->perfect > ((const struct NScore*)b)->perfect) 32 | k = -1; 33 | else // total_score相等,perfect也相等, 则按ID做升序排序 34 | { 35 | if(((const struct NScore*)a)->ID < ((const struct NScore*)b)->ID) 36 | k = -1; 37 | else if (((const struct NScore*)a)->ID > ((const struct NScore*)b)->ID) 38 | k = 1; 39 | else 40 | k = 0; 41 | } 42 | } 43 | return k; 44 | } 45 | 46 | 47 | int main(int argc, char const *argv[]) 48 | { 49 | int N, K, M, i, j, cnt; 50 | int user_id, problem_id, partial_score; 51 | int p[MaxProb]; 52 | scanf("%d %d %d", &N, &K, &M); 53 | for (i=1; i<=K; i++) // 从p[1]到p[K] 54 | scanf("%d", &p[i]); 55 | 56 | // 初始化Student[] 57 | for (i=1; i<=N; i++){ // 从Student[1] 到 Student[N] 58 | Student[i].ID = i; 59 | Student[i].enable = false; // 初始化为都不可见 60 | for (j=1; j<=K; j++) // 从s[1] 到 s[k] 61 | Student[i].s[j] = -2; 62 | Student[i].total_score = Student[i].perfect = Student[i].rank = 0; 63 | } 64 | Student[0].total_score = -1; // Student[0]的数据不要,设置为负数 65 | 66 | // 读M次提交 67 | for (i=0; i -1) 70 | Student[user_id].enable = true; // 只要编译通过, 0分也可见 71 | if (partial_score > Student[user_id].s[problem_id]) 72 | Student[user_id].s[problem_id] = partial_score; 73 | } 74 | 75 | 76 | // 计算total_score和perfect的数目 77 | for (i=1; i<=N; i++){ // 从Student[1] 到 Student[N] 78 | for (j=1; j<=K; j++) // 从s[1] 到 s[k] 79 | { 80 | if (Student[i].s[j]>0){ 81 | Student[i].total_score += Student[i].s[j]; 82 | if(Student[i].s[j] == p[j]) 83 | Student[i].perfect++; 84 | } 85 | } 86 | } 87 | 88 | // 开始排序 89 | qsort(Student, N+1, sizeof(struct NScore), compare3keys); // N+1 因为要排到Student[N],包含[0], 总排数据为N+1个 90 | 91 | 92 | // 计算rank 93 | cnt = 0; 94 | for (i=0; i 3 | #include 4 | #define MaxN 100001 5 | 6 | int main(int argc, char const *argv[]) 7 | { 8 | int A[MaxN]; 9 | int N; 10 | int i, j, p,S=0, K=0; 11 | 12 | scanf("%d", &N); 13 | 14 | for(i=0; i 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define MAXNUMBER 100000 8 | #define KEYLENGTH 11 9 | #define MAXD 5 // the last 5 numbers as key 10 | 11 | typedef char ElementType[KEYLENGTH+1]; 12 | 13 | typedef struct LNode *PtrNode; 14 | struct LNode 15 | { 16 | ElementType Data; 17 | int Count; 18 | PtrNode Next; 19 | }; 20 | typedef struct LNode* List; 21 | typedef struct LNode* Position; 22 | 23 | typedef struct TblNode *HashTable; 24 | struct TblNode 25 | { 26 | int TableSize; 27 | List Heads; 28 | }; 29 | 30 | int GetPrime (int N){ 31 | int i,p = (N%2)? N+2:N+1; 32 | while(p2; i--){ 34 | if(!(p%i)) // 除尽, 不是素数 35 | break; 36 | } 37 | if (i==2) 38 | break; 39 | else 40 | p += 2; 41 | } 42 | return p; 43 | } 44 | 45 | HashTable CreateTable(int TableSize){ 46 | HashTable H; 47 | int i; 48 | H = (HashTable) malloc(sizeof(struct TblNode)); 49 | H->TableSize = GetPrime(TableSize); 50 | H->Heads = (List)malloc(H->TableSize * sizeof(struct LNode)); 51 | for (i = 0; i < H->TableSize; i++) 52 | { 53 | H->Heads[i].Data[0] = '\0'; 54 | H->Heads[i].Next = NULL; 55 | H->Heads[i].Count = 0; 56 | } 57 | return H; 58 | 59 | } 60 | 61 | int Hash(ElementType Key, int TableSize){ // 取手机号码的后5位作为keyword 62 | return atoi(Key + KEYLENGTH - MAXD) % TableSize; 63 | } 64 | 65 | Position Find(HashTable H, ElementType key){ 66 | int pos; 67 | Position p; 68 | 69 | pos = Hash(key, H->TableSize); 70 | p = H->Heads[pos].Next; 71 | while(p && strcmp(p->Data, key)){ 72 | p = p->Next; 73 | } 74 | return p; 75 | } 76 | 77 | 78 | void Insert(HashTable H, ElementType Key){ 79 | Position p, NewNode; 80 | int pos; 81 | 82 | p = Find(H, Key); 83 | if (!p){ 84 | pos = Hash(Key, H->TableSize); 85 | NewNode =(Position)malloc(sizeof(struct LNode)); 86 | strcpy(NewNode->Data, Key); 87 | NewNode->Count = 1; 88 | NewNode->Next = H->Heads[pos].Next; 89 | H->Heads[pos].Next = NewNode; 90 | } 91 | else{ 92 | p->Count++; 93 | } 94 | } 95 | 96 | void DestroyTable(HashTable H){ 97 | int i; 98 | Position p, tmp; 99 | 100 | for(i=0; i< H->TableSize; i++){ 101 | p = H->Heads[i].Next; 102 | while(p){ 103 | tmp = p->Next; 104 | free(p); 105 | p = tmp; 106 | } 107 | } 108 | free(H->Heads); 109 | free(H); 110 | } 111 | 112 | 113 | void ScanAndOutput(HashTable H){ 114 | int maxnum=0; 115 | int i, repeat; 116 | ElementType maxphone; 117 | Position p; 118 | 119 | for(i=0; iTableSize; i++){ 120 | p = H->Heads[i].Next; 121 | while(p) 122 | { 123 | if(p->Count > maxnum){ 124 | maxnum = p->Count; 125 | strcpy(maxphone, p->Data); 126 | repeat = 1; 127 | } 128 | else if(p->Count == maxnum){ 129 | if ( strcmp(p->Data, maxphone) < 0) 130 | strcpy(maxphone, p->Data); 131 | repeat++; 132 | } 133 | p = p->Next; 134 | } 135 | } 136 | printf("%s %d", maxphone, maxnum); 137 | if (repeat > 1) 138 | printf(" %d\n", repeat); 139 | else 140 | printf("\n"); 141 | 142 | } 143 | 144 | 145 | 146 | 147 | int main(int argc, char const *argv[]) 148 | { 149 | int n, i; 150 | ElementType phone; 151 | HashTable H; 152 | 153 | scanf("%d", &n); 154 | H = CreateTable(n*2); 155 | for(i=0; i<2*n; i++){ 156 | scanf("%s", phone); 157 | Insert(H, phone); 158 | } 159 | ScanAndOutput(H); 160 | DestroyTable(H); 161 | return 0; 162 | } 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /PTA_Exercise/11-散列2 Hashing.c: -------------------------------------------------------------------------------- 1 | //11-散列2 Hashing 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define MAXNUMBER 100000 7 | 8 | typedef enum{Legitimate, Empty} EntryType; 9 | typedef int ElementType; 10 | typedef int index; 11 | 12 | // 散列表单元类型 13 | struct Cell 14 | { 15 | ElementType Data; 16 | EntryType Info; 17 | 18 | }; 19 | 20 | // 散列表类型 21 | typedef struct TblNode *HashTable; 22 | struct TblNode 23 | { 24 | int TableSize; 25 | struct Cell* Cells; 26 | }; 27 | 28 | 29 | int GetPrime (int N){ 30 | int i,p = (N%2)? N:N+1; // 若N是偶数N=N+1,若N是奇数N=N 31 | if(N<=2) 32 | return 2; 33 | if (N==3) 34 | return N; 35 | while(p2; i--){ 37 | if(!(p%i)) // 除尽, 不是素数 38 | break; 39 | } 40 | if (i==2) 41 | break; 42 | else 43 | p += 2; 44 | } 45 | return p; 46 | } 47 | 48 | 49 | HashTable CreateTable(int TableSize){ 50 | HashTable H; 51 | H = (HashTable)malloc(sizeof(struct TblNode)); 52 | H->TableSize = GetPrime(TableSize); 53 | H->Cells = (struct Cell*)malloc(H->TableSize * sizeof(struct Cell)); 54 | // Initialize 55 | for (int i=0; iTableSize; i++){ 56 | H->Cells[i].Data = 0; 57 | H->Cells[i].Info = Empty; 58 | } 59 | return H; 60 | } 61 | 62 | int Hash(HashTable H, ElementType Key){ 63 | return Key % H->TableSize; 64 | } 65 | 66 | int Find(HashTable H, ElementType Key){ 67 | int CurrentPos, NewPos; 68 | int CNum=0; // conflict number 69 | 70 | CurrentPos = NewPos = Hash(H, Key); 71 | while(H->Cells[NewPos].Info != Empty && CNum < 2*H->TableSize && 72 | H->Cells[NewPos].Data != Key) 73 | { 74 | CNum++; 75 | NewPos = CurrentPos + CNum * CNum; 76 | if (NewPos > H->TableSize) 77 | NewPos %= H->TableSize; 78 | } 79 | if (CNum < 2*H->TableSize) 80 | return NewPos; 81 | else 82 | return -1; // 死循环,无位置可以插入 83 | } 84 | 85 | int Insert(HashTable H, ElementType Key){ 86 | int pos = Find(H, Key); 87 | 88 | if (pos != -1){ 89 | if (H->Cells[pos].Info != Legitimate){ 90 | H->Cells[pos].Info = Legitimate; 91 | H->Cells[pos].Data = Key; 92 | } 93 | } 94 | 95 | return pos; 96 | } 97 | 98 | 99 | 100 | int main(int argc, char const *argv[]) 101 | { 102 | int M, N, i, Key, pos, flag=0; 103 | HashTable H; 104 | scanf("%d %d", &M, &N); 105 | H = CreateTable(M); 106 | 107 | for (i = 0; i < N; i++) 108 | { 109 | scanf("%d", &Key); 110 | pos = Insert(H, Key); 111 | if (pos != -1){ 112 | if (flag == 0) 113 | flag = 1; 114 | else 115 | printf(" "); 116 | printf("%d", pos); 117 | } 118 | else{ 119 | if (flag == 0) 120 | flag = 1; 121 | else 122 | printf(" "); 123 | printf("-"); 124 | } 125 | } 126 | printf("\n"); 127 | 128 | return 0; 129 | } 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /PTA_Exercise/11-散列3 QQ帐户的申请与登陆 - 排序法.c: -------------------------------------------------------------------------------- 1 | //散列3 QQ帐户的申请与登陆 - 排序法(会超时) 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | typedef struct Node* List; 9 | struct Node 10 | { 11 | unsigned long QQ; 12 | char PW[20]; 13 | }; 14 | 15 | int compare(const void *a, const void *b) 16 | { 17 | if (((List)a)->QQ > ((const List)b)->QQ) 18 | return 1; 19 | else if(((List)a)->QQ < ((const List)b)->QQ) 20 | return -1; 21 | else 22 | return 0; 23 | } 24 | 25 | int BinarySearch(List list, unsigned long QQ, int N){ 26 | int Left, Right, Mid; 27 | Left = 0; 28 | Right = N-1; 29 | 30 | while (Left <= Right){ 31 | Mid = (Left + Right) / 2; 32 | if (QQ > list[Mid].QQ) 33 | Left = Mid + 1; 34 | else if (QQ < list[Mid].QQ) 35 | Right = Mid - 1; 36 | else // 相等,找到了 37 | return Mid; 38 | } 39 | return -1; 40 | } 41 | 42 | 43 | int main(int argc, char const *argv[]) 44 | { 45 | unsigned long QQ; 46 | char PW[20]; 47 | int i, j, N, cnt=0; 48 | char c; // 命令符 L OR N 49 | scanf("%d", &N); 50 | List list = (List)malloc(sizeof(struct Node) * N); 51 | for (i = 0; i < N; i++) 52 | { 53 | getchar(); // 读掉回车 54 | c = getchar(); 55 | scanf("%lu %s", &QQ, PW); 56 | 57 | list[cnt].QQ = 0; 58 | list[cnt].PW[0]='\0'; 59 | 60 | 61 | // 命令N 62 | if (c == 'N'){ 63 | j = BinarySearch(list, QQ, cnt); 64 | if (j != -1){ // 找到 65 | printf("ERROR: Exist\n"); 66 | } 67 | else // j=-1 没找到 68 | { 69 | printf("New: OK\n"); 70 | list[cnt].QQ = QQ; 71 | strcpy(list[cnt].PW, PW); 72 | cnt++; 73 | qsort(list, cnt, sizeof(struct Node), compare); // 按qq号从小到大排序 74 | } 75 | } 76 | 77 | // 命令L 78 | else 79 | { 80 | j = BinarySearch(list, QQ, cnt); 81 | if (j != -1) // 找到 82 | { 83 | if(!strcmp(list[j].PW, PW)) //strcmp = 0 相等 84 | printf("Login: OK\n"); 85 | else 86 | printf("ERROR: Wrong PW\n"); 87 | } 88 | else // j=-1 没找到 89 | printf("ERROR: Not Exist\n"); 90 | } 91 | } 92 | 93 | return 0; 94 | } 95 | 96 | 97 | -------------------------------------------------------------------------------- /PTA_Exercise/11-散列3 QQ帐户的申请与登陆 - 散列法.c: -------------------------------------------------------------------------------- 1 | //散列3 QQ帐户的申请与登陆 - 散列法 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define KEYLENGTH 16 // QQ号和密码的最大长度 8 | #define MAXTABLESIZE 1000000 9 | 10 | typedef char ElementType[KEYLENGTH+1]; 11 | typedef int Index; // 散列地址类型 12 | 13 | // 单链表定义 14 | typedef struct LNode *PtrNode; 15 | struct LNode 16 | { 17 | ElementType Data; 18 | ElementType Password; 19 | PtrNode Next; 20 | }; 21 | typedef PtrNode Position; 22 | typedef PtrNode List; 23 | 24 | typedef struct TblNode *HashTable; 25 | struct TblNode // 散列表结点 26 | { 27 | int TableSize; 28 | List Heads; // Heads是由 LNode 组成的一个列表 29 | }; 30 | 31 | // 生成一个不小于TableSize, 但不大于MAXTABLESIZE的最小素数 32 | int NextPrime(int N){ 33 | int i, p= (N%2)? N+2:N+1; // p=大于N的下一个奇数 34 | 35 | while (p<=MAXTABLESIZE){ 36 | for ( i = sqrt(p); i>2; i--){ 37 | if (! (p % i)) // p被i整除,余数为0的时候 38 | break; 39 | } 40 | if (i==2) break; // for循环正常跳出,没有被i整除过,说明p是素数 41 | else p+=2; // p不是素数,试探下一个奇数 42 | } 43 | return p; 44 | } 45 | 46 | // 构造并初始化HashTable 47 | HashTable CreateTable(int TableSize) 48 | { 49 | HashTable H; 50 | int i; 51 | 52 | 53 | H = (HashTable)malloc(sizeof(struct TblNode)); 54 | H->TableSize = NextPrime(TableSize); 55 | 56 | // 分配链表头结点的数组Heads的空间 57 | H->Heads = (List)malloc(H->TableSize * sizeof(struct LNode)); 58 | // 初始化表头结点 59 | for(i=0; iTableSize; i++){ 60 | H->Heads[i].Data[0] = '\0'; 61 | H->Heads[i].Password[0] = '\0'; 62 | H->Heads[i].Next = NULL; 63 | } 64 | 65 | return H; 66 | } 67 | 68 | 69 | // 构造一个Hash函数 70 | Index Hash(ElementType Key, int TableSize){ 71 | unsigned long h = 0; 72 | char *ptr = Key; 73 | while (*ptr != '\0'){ 74 | h = (h<<5) + *ptr; 75 | ptr++; 76 | } 77 | int p = (int)(h%TableSize); 78 | return p; 79 | } 80 | 81 | /* insert, 先找关键词,若已经存在就不需要再插入了, 82 | 若不存在先申请一个新结点,再插入到Heads[pos]的表头上 */ 83 | Position Find(HashTable H, ElementType Key){ 84 | Position p; 85 | Index pos; 86 | 87 | pos = Hash(Key, H->TableSize); 88 | p = H->Heads[pos].Next; 89 | while(p && strcmp(p->Data, Key)) // p 不指向空,且未找到时(strcmp != 0 代表不同) 90 | p = p->Next; 91 | 92 | return p; // 没找到是p为空,找到则指向那个LNode 93 | } 94 | 95 | 96 | void Insert(HashTable H, ElementType Key, ElementType PW){ 97 | Position p, NewCell; 98 | Index pos; 99 | 100 | p = Find(H, Key); 101 | if (!p) // 未找到关键词,可以插入 102 | { 103 | NewCell = (Position)malloc(sizeof(struct LNode)); 104 | strcpy(NewCell->Data, Key); // 把Key复制进去 105 | strcpy(NewCell->Password, PW); // 把密码复制进去 106 | 107 | pos = Hash(Key, H->TableSize); 108 | // 插入到表头 109 | NewCell->Next = H->Heads[pos].Next; 110 | H->Heads[pos].Next = NewCell; 111 | printf("New: OK\n"); 112 | } 113 | else // 关键字已经存在 114 | printf("ERROR: Exist\n"); 115 | 116 | } 117 | 118 | // 释放HashTable 119 | void DestroyTable(HashTable H){ 120 | int i; 121 | Position p, tmp; 122 | 123 | for(i=0; i< H->TableSize; i++){ 124 | p = H->Heads[i].Next; 125 | while(p){ 126 | tmp = p->Next; 127 | free(p); 128 | p = tmp; 129 | } 130 | } 131 | free(H->Heads); 132 | free(H); 133 | } 134 | 135 | 136 | 137 | 138 | int main(int argc, char const *argv[]) 139 | { 140 | char QQ[11]; 141 | char PW[20]; 142 | int i, j, N; 143 | char c; // 命令符 L OR N 144 | Position pos; 145 | 146 | scanf("%d", &N); 147 | int TableSize = N/10; 148 | HashTable H = CreateTable(TableSize); 149 | 150 | for (i = 0; i < N; i++) 151 | { 152 | getchar(); // 读掉回车 153 | c = getchar(); // 读命令符 154 | scanf("%s %s", QQ, PW); 155 | 156 | if (c == 'N') // 命令N 157 | Insert(H, QQ, PW); 158 | else // 命令L 159 | { 160 | pos = Find(H, QQ); 161 | if (pos){ // found 162 | if (!strcmp(pos->Password, PW)) // =0 相同 163 | printf("Login: OK\n"); 164 | else 165 | printf("ERROR: Wrong PW\n"); 166 | } 167 | else // not found 168 | printf("ERROR: Not Exist\n"); 169 | } 170 | } 171 | 172 | DestroyTable(H); 173 | 174 | return 0; 175 | } 176 | 177 | 178 | -------------------------------------------------------------------------------- /PTA_Exercise/11-散列4 Hashing - Hard Version 方法二.c: -------------------------------------------------------------------------------- 1 | //11-散列4 Hashing - Hard Version 2 | #include 3 | #include 4 | #include 5 | #define INFINITY 65535 6 | typedef int ElementType; //关键词类型 7 | typedef int Vertex; // 用顶点下标表示顶点,为整形 8 | #define MaxVertexNum 1000 9 | #define MaxSize 1000 10 | #define ERROR -1 11 | 12 | /* ********************* LGraph *******************/ 13 | // 边的定义 14 | typedef struct ENode *PtrENode; 15 | struct ENode 16 | { 17 | Vertex V1, V2; 18 | }; 19 | typedef PtrENode Edge; 20 | 21 | // 邻接点的定义 边表 22 | typedef struct AdjVNode *PtrAdjVNode; 23 | struct AdjVNode 24 | { 25 | Vertex AdjV; // 邻接点下标 26 | PtrAdjVNode Next; // 指向下一个邻接点的致指针 27 | }; 28 | 29 | // 顶点表头结点的定义 顶点表 30 | struct VNode{ 31 | PtrAdjVNode FirstEdge; // 边表头指针 32 | }; 33 | typedef struct VNode AdjList[MaxVertexNum]; 34 | 35 | // Graph struct 36 | /* 图结点的定义 */ 37 | typedef struct GNode * PtrGNode; 38 | struct GNode 39 | { 40 | int Nv; //顶点数 41 | int Ne; // 边数 42 | AdjList G; // 邻接表. 是一个size为MaxVertexNum的数组,每一个元素都是一个结点VNode 43 | }; 44 | typedef PtrGNode LGraph; 45 | 46 | // 初始化有VertexNum个顶点但没有边的图 47 | LGraph CreateGraph(int VertexNum) 48 | { 49 | LGraph Graph; 50 | Vertex v,w; 51 | 52 | Graph = (LGraph)malloc(sizeof(struct GNode)); 53 | Graph->Nv = VertexNum; 54 | Graph->Ne = 0; 55 | 56 | for(v=0; vNv; v++) 57 | Graph->G[v].FirstEdge = NULL; // 每一个顶点v的FirstEdge都是空的, 编号从0到 Graph->Nv-1 58 | return Graph; 59 | } 60 | 61 | // 插入一条边 62 | void InsertEdge (LGraph Graph, Edge E) /* 插入边 */ 63 | { 64 | PtrAdjVNode NewNode; 65 | 66 | /* 为V2建立新的邻接点 */ 67 | NewNode = (PtrAdjVNode)malloc(sizeof(struct AdjVNode)); 68 | NewNode->AdjV = E->V2; 69 | /* 将V2插入V1的表头, 在头上插入 */ 70 | NewNode->Next = Graph->G[E->V1].FirstEdge; 71 | Graph->G[E->V1].FirstEdge = NewNode; 72 | } 73 | 74 | /* ********************* TopSort *******************/ 75 | /* 邻接表存储 - 拓扑排序算法 */ 76 | 77 | bool TopSort( LGraph Graph, Vertex TopOrder[], int Cells[] ) // TopOrder[]顺序存储排序后的顶点下标 */ 78 | { 79 | int Indegree[MaxVertexNum], cnt; 80 | Vertex V; 81 | int mini, i; 82 | int *zeroin, num_in=0; // num_in 记录indegree为0的顶点有几个 83 | PtrAdjVNode W; 84 | 85 | 86 | zeroin = malloc(Graph->Nv * sizeof(int)); 87 | 88 | 89 | /* 初始化Indegree[], zeroin[] */ 90 | for (V=0; VNv; V++){ 91 | Indegree[V] = 0; 92 | zeroin[V] = INFINITY; 93 | } 94 | 95 | /* 遍历图,得到Indegree[] */ 96 | for (V=0; VNv; V++) 97 | for (W=Graph->G[V].FirstEdge; W; W=W->Next) 98 | Indegree[W->AdjV]++; /* 对有向边AdjV>累计终点的入度 */ 99 | 100 | /* 将所有入度为0的顶点加入zeroin[] */ 101 | for (V=0; VNv; V++) 102 | if ( Indegree[V]==0 ){ 103 | zeroin[V] = Cells[V]; 104 | num_in++; 105 | } 106 | 107 | /* 下面进入拓扑排序 */ 108 | cnt = 0; 109 | while( num_in != 0){ 110 | // 找出zeroin[]里的最小值,把它变成INFINITY 111 | mini = INFINITY; 112 | for (i=0; iNv; i++){ 113 | if (zeroin[i] < mini){ 114 | mini = zeroin[i]; 115 | V = i; 116 | } 117 | } 118 | zeroin[V] = INFINITY; 119 | num_in--; 120 | TopOrder[cnt++] = mini; /* 将之存为结果序列的下一个元素 */ 121 | 122 | /* 对V的每个邻接点W->AdjV */ 123 | for ( W=Graph->G[V].FirstEdge; W; W=W->Next ) 124 | if ( --Indegree[W->AdjV] == 0 ){/* 若删除V使得W->AdjV入度为0 */ 125 | zeroin[W->AdjV]=Cells[W->AdjV]; /* 则该顶点加入zeroin[] */ 126 | num_in++; 127 | } 128 | } /* while结束*/ 129 | 130 | if ( cnt != Graph->Nv ) 131 | return false; /* 说明图中有回路, 返回不成功标志 */ 132 | else 133 | return true; 134 | } 135 | 136 | 137 | 138 | /* ************************************************/ 139 | 140 | int main(int argc, char const *argv[]) 141 | { 142 | 143 | int N; 144 | scanf("%d", &N); // 记录散列表TablieSize 145 | int *c; // 数组c 记录冲突次数 146 | c = malloc(N * sizeof(int)); 147 | int *Cells; // 记录散列数组 148 | Cells = malloc(N * sizeof(int)); 149 | 150 | int i, j; 151 | 152 | // 计算冲突次数 153 | for (i = 0; i < N; i++) 154 | { 155 | scanf("%d", &Cells[i]); 156 | if (Cells[i] < 0){ 157 | c[i] = INFINITY; 158 | } 159 | else{ 160 | c[i] = i - (Cells[i] % N); 161 | if (c[i] < 0 ) 162 | c[i] += N; 163 | } 164 | 165 | } 166 | 167 | 168 | // 建立邻接表 169 | LGraph Graph = CreateGraph(N); 170 | Edge E; 171 | 172 | for (i = 0; i < N; i++){ 173 | if (c[i] > 0 && c[i]V1 = (i-j)>0? i-j:i-j+N; 178 | E->V2 = i; 179 | InsertEdge(Graph, E); 180 | } 181 | } 182 | } 183 | 184 | // 拓扑排序 185 | Vertex TopOrder[MaxSize]; 186 | TopSort(Graph, TopOrder, Cells); 187 | 188 | //输出 189 | int flag = 0; 190 | for (i = 0; i < N; i++){ 191 | if (TopOrder[i] >= 0){ //非负,为有效数据 192 | if (flag == 0) 193 | flag = 1; 194 | else 195 | printf(" "); 196 | printf("%d", TopOrder[i]); 197 | } 198 | } 199 | 200 | printf("\n"); 201 | return 0; 202 | } 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /PTA_Exercise/11-散列4 Hashing - Hard Version.c: -------------------------------------------------------------------------------- 1 | //11-散列4 Hashing - Hard Version 2 | #include 3 | #include 4 | #include 5 | #define INFINITY 65535 6 | typedef int ElementType; //关键词类型 7 | typedef int Vertex; // 用顶点下标表示顶点,为整形 8 | #define MaxVertexNum 1000 9 | #define MaxSize 1000 10 | #define ERROR -1 11 | 12 | /* ********************* LGraph *******************/ 13 | // 边的定义 14 | typedef struct ENode *PtrENode; 15 | struct ENode 16 | { 17 | Vertex V1, V2; 18 | }; 19 | typedef PtrENode Edge; 20 | 21 | // 邻接点的定义 边表 22 | typedef struct AdjVNode *PtrAdjVNode; 23 | struct AdjVNode 24 | { 25 | Vertex AdjV; // 邻接点下标 26 | PtrAdjVNode Next; // 指向下一个邻接点的致指针 27 | }; 28 | 29 | // 顶点表头结点的定义 顶点表 30 | struct VNode{ 31 | PtrAdjVNode FirstEdge; // 边表头指针 32 | }; 33 | typedef struct VNode AdjList[MaxVertexNum]; 34 | 35 | // Graph struct 36 | /* 图结点的定义 */ 37 | typedef struct GNode * PtrGNode; 38 | struct GNode 39 | { 40 | int Nv; //顶点数 41 | int Ne; // 边数 42 | AdjList G; // 邻接表. 是一个size为MaxVertexNum的数组,每一个元素都是一个结点VNode 43 | }; 44 | typedef PtrGNode LGraph; 45 | 46 | // 初始化有VertexNum个顶点但没有边的图 47 | LGraph CreateGraph(int VertexNum) 48 | { 49 | LGraph Graph; 50 | Vertex v,w; 51 | 52 | Graph = (LGraph)malloc(sizeof(struct GNode)); 53 | Graph->Nv = VertexNum; 54 | Graph->Ne = 0; 55 | 56 | for(v=0; vNv; v++) 57 | Graph->G[v].FirstEdge = NULL; // 每一个顶点v的FirstEdge都是空的, 编号从0到 Graph->Nv-1 58 | return Graph; 59 | } 60 | 61 | // 插入一条边 62 | void InsertEdge (LGraph Graph, Edge E) /* 插入边 */ 63 | { 64 | PtrAdjVNode NewNode; 65 | 66 | /* 为V2建立新的邻接点 */ 67 | NewNode = (PtrAdjVNode)malloc(sizeof(struct AdjVNode)); 68 | NewNode->AdjV = E->V2; 69 | /* 将V2插入V1的表头, 在头上插入 */ 70 | NewNode->Next = Graph->G[E->V1].FirstEdge; 71 | Graph->G[E->V1].FirstEdge = NewNode; 72 | } 73 | 74 | /* ************************ MinHeap **********************/ 75 | 76 | // 数据结构 77 | typedef struct HNode *MinHeap; 78 | struct HNode { 79 | ElementType *Data; // 存储堆元素的数组 80 | int Size; // 堆的当前元素的个数 81 | int Capacity; // 堆的最大容量 82 | }; 83 | 84 | 85 | // Create a heap 86 | MinHeap CreateHeap(void) 87 | { 88 | MinHeap H = (MinHeap)malloc(sizeof(struct HNode)); 89 | H->Data = (ElementType*)malloc((MaxSize+1) * sizeof(ElementType)); // 因为这里是一个数组,需要分配空间 90 | H->Size = 0; // 当前是空的 91 | H->Capacity = MaxSize; // 堆的最大容量 92 | H->Data[0] = - INFINITY; /* 定义“哨兵”为小于堆中所有可能元素的值,便于以后操作 */ 93 | return H; 94 | } 95 | 96 | // Full 97 | bool IsHeapFull(MinHeap H){ 98 | return (H->Size == H->Capacity); 99 | } 100 | 101 | // Empty 102 | bool IsHeapEmpty(MinHeap H){ 103 | return (H->Size == 0); 104 | } 105 | 106 | // Insert a node to a minheap 107 | void InsertMinHeap(MinHeap H, ElementType item) 108 | { 109 | int i; 110 | if (IsHeapFull(H)){ 111 | printf("FULL\n"); 112 | return; 113 | } 114 | i = ++H->Size; // H->Size++; i = H->Size; 把新增元素放在末尾H->Size++的位置上 115 | if (i > 1){ 116 | for(; H->Data[i/2] > item; i/=2){ // 其父节点大于它 117 | H->Data[i] = H->Data[i/2]; // 把它的父节点,向下过滤, 插入的item向上过滤 118 | } 119 | } 120 | // 当它的父结点[i/2]比它小的时候, 符合条件,跳出循环 121 | H->Data[i] = item; // 填上item 122 | } 123 | 124 | 125 | 126 | // Delete the root(the minimum) from a minheap 127 | ElementType DeleteMin(MinHeap H) 128 | { 129 | int parent, child; 130 | ElementType MinItem, temp; 131 | if(IsHeapEmpty(H)){ 132 | printf("Empty\n"); 133 | return ERROR; 134 | } 135 | 136 | MinItem = H->Data[1]; // 取出最小值 137 | /* 用最小堆中最后一个元素从根节点开始向上过滤下层节点 */ 138 | temp = H->Data[H->Size]; // 把堆中最后一个值,交给temp 139 | H->Size--; 140 | 141 | for(parent=1; parent*2 <= H->Size; parent=child) 142 | { 143 | child = parent*2; // 左儿子 144 | 145 | /* child=左右儿子中小的那个, 当右儿子存在,且右儿子的值比左儿子小时,让child=右儿子 */ 146 | if((child!= H->Size) && 147 | (H->Data[child] > H->Data[child+1])) 148 | child++; 149 | 150 | /* 当temp比child的值小时跳出循环 */ 151 | if (temp <= H->Data[child]) 152 | break; 153 | else 154 | H->Data[parent] = H->Data[child]; //当parent < child,这个parent位置上变为child的值 155 | } 156 | H->Data[parent] = temp; 157 | return MinItem; 158 | } 159 | 160 | 161 | /* ********************* TopSort *******************/ 162 | /* 邻接表存储 - 拓扑排序算法 */ 163 | 164 | bool TopSort( LGraph Graph, Vertex TopOrder[], int Cells[] ) // TopOrder[]顺序存储排序后的顶点下标 */ 165 | { 166 | int Indegree[MaxVertexNum], cnt; 167 | Vertex V; 168 | int mini; 169 | PtrAdjVNode W; 170 | MinHeap H = CreateHeap(); 171 | 172 | /* 初始化Indegree[] */ 173 | for (V=0; VNv; V++) 174 | Indegree[V] = 0; 175 | 176 | /* 遍历图,得到Indegree[] */ 177 | for (V=0; VNv; V++) 178 | for (W=Graph->G[V].FirstEdge; W; W=W->Next) 179 | Indegree[W->AdjV]++; /* 对有向边AdjV>累计终点的入度 */ 180 | 181 | /* 将所有入度为0的顶点插入最小堆 */ 182 | for (V=0; VNv; V++) 183 | if ( Indegree[V]==0 ) 184 | InsertMinHeap(H, Cells[V]); 185 | 186 | /* 下面进入拓扑排序 */ 187 | cnt = 0; 188 | while( !IsHeapEmpty(H) ){ 189 | mini = DeleteMin(H); // 弹出最小值 190 | TopOrder[cnt++] = mini; /* 将之存为结果序列的下一个元素 */ 191 | for (V=0; VNv; V++){ 192 | if (Cells[V] == mini) 193 | break; 194 | } 195 | /* 对V的每个邻接点W->AdjV */ 196 | for ( W=Graph->G[V].FirstEdge; W; W=W->Next ) 197 | if ( --Indegree[W->AdjV] == 0 )/* 若删除V使得W->AdjV入度为0 */ 198 | InsertMinHeap(H, Cells[W->AdjV]); /* 则该顶点插入最小堆 */ 199 | } /* while结束*/ 200 | 201 | if ( cnt != Graph->Nv ) 202 | return false; /* 说明图中有回路, 返回不成功标志 */ 203 | else 204 | return true; 205 | } 206 | 207 | 208 | 209 | /* ************************************************/ 210 | 211 | int main(int argc, char const *argv[]) 212 | { 213 | 214 | int N; 215 | scanf("%d", &N); // 记录散列表TablieSize 216 | int *c; // 数组c 记录冲突次数 217 | c = malloc(N * sizeof(int)); 218 | int *Cells; // 记录散列数组 219 | Cells = malloc(N * sizeof(int)); 220 | 221 | int i, j; 222 | 223 | // 计算冲突次数 224 | for (i = 0; i < N; i++) 225 | { 226 | scanf("%d", &Cells[i]); 227 | if (Cells[i] < 0){ 228 | c[i] = INFINITY; 229 | } 230 | else{ 231 | c[i] = i - (Cells[i] % N); 232 | if (c[i] < 0 ) 233 | c[i] += N; 234 | } 235 | 236 | } 237 | 238 | 239 | // 建立邻接表 240 | LGraph Graph = CreateGraph(N); 241 | Edge E; 242 | 243 | for (i = 0; i < N; i++){ 244 | if (c[i] > 0 && c[i]V1 = (i-j)>0? i-j:i-j+N; 249 | E->V2 = i; 250 | InsertEdge(Graph, E); 251 | } 252 | } 253 | } 254 | 255 | // 拓扑排序 256 | Vertex TopOrder[MaxSize]; 257 | TopSort(Graph, TopOrder, Cells); 258 | 259 | //输出 260 | int flag = 0; 261 | for (i = 0; i < N; i++){ 262 | if (TopOrder[i] >= 0){ //非负,为有效数据 263 | if (flag == 0) 264 | flag = 1; 265 | else 266 | printf(" "); 267 | printf("%d", TopOrder[i]); 268 | } 269 | } 270 | 271 | printf("\n"); 272 | return 0; 273 | } 274 | 275 | 276 | 277 | 278 | -------------------------------------------------------------------------------- /PTA_Exercise/KMP 串的模式匹配.c: -------------------------------------------------------------------------------- 1 | // KMP 串的模式匹配 2 | #include 3 | #include 4 | #include 5 | #define MAXSTRING 1000001 6 | #define MAXPATTERN 100001 7 | #define NotFound -1 8 | 9 | void BuildMatch(char *pattern, int *match){ 10 | int i, j; 11 | int m = strlen(pattern); 12 | match[0] = -1; 13 | for (j=1; j=0 && (pattern[i+1] != pattern[j])) // 找到能对上的的pattern为止 16 | i = match[i]; 17 | if (pattern[i+1] == pattern[j]) 18 | match[j] = i+1; 19 | else 20 | match[j] = NotFound; 21 | } 22 | } 23 | 24 | int KMP(char *string, char *pattern){ 25 | int n = strlen(string); 26 | int m = strlen(pattern); 27 | int s, p; 28 | if (n < m) return NotFound; 29 | // match列表来放pattern的最大匹配值 30 | int *match; 31 | match = (int*)malloc(m * sizeof(int)); 32 | BuildMatch(pattern, match); 33 | 34 | s=p=0; 35 | while(s < n && p < m){ 36 | if (string[s] == pattern[p]){ 37 | s++; 38 | p++; 39 | } 40 | else if(p > 0) // p回撤到上一个match模块后一位, s不动,继续比较s和回撤后的p 41 | p = match[p-1] + 1; 42 | else s++; // p=0 pattern第一个就没有对上,移动s, p不动 43 | } 44 | return (p == m)? (s-m):NotFound; 45 | } 46 | 47 | int main(int argc, char const *argv[]) 48 | { 49 | char string[MAXSTRING]; 50 | scanf("%s", string); 51 | char pattern[MAXPATTERN]; 52 | int n; 53 | int p; 54 | scanf("%d", &n); 55 | for(int i=0; i