├── Chapter02 ├── C_2.3.1.c ├── E_2.1-4.c ├── E_2.2-2.2.c ├── E_2.2-2.c ├── E_2.3-2.c ├── E_2.3-5.2.c ├── E_2.3-5.c ├── E_2.3-6.c ├── E_2.3-7.c ├── P_2-1.2.c ├── P_2-1.c ├── P_2-2.c └── P_2-4.c ├── Chapter04 ├── C_4.1.c ├── E_4.1-3.c ├── E_4.1-4.c ├── E_4.1-5.c ├── E_4.2-2.2.cpp ├── E_4.2-2.c └── P_4-6.c ├── Chapter05 ├── E_5.1-2.c └── E_5.1-3.c ├── Chapter06 ├── C_6.2.c ├── C_6.c ├── E_6.2-5.c ├── E_6.5-3.c ├── E_6.5-6.c ├── E_6.5-9.cpp ├── P_6-2.c └── P_6-3.c ├── Chapter07 ├── C_7.3.c ├── E_7.4-5.c ├── E_7.4-5.cpp ├── P_7-1.2.c ├── P_7-1.3.c ├── P_7-1.c ├── P_7-2.c ├── P_7-4.c └── P_7-6.c ├── Chapter08 ├── P_8-2.c ├── P_8-3.c ├── P_8-5.c └── P_8-7.c ├── Chapter09 └── E_9.2-3.c ├── Chapter10 ├── E_10.1-5.c ├── E_10.1-5~7.c ├── E_10.2-2.2.c ├── E_10.2-2.c ├── E_10.2-3.c ├── E_10.2-5.c ├── E_10.2-7.c ├── E_10.3-2.c ├── E_10.3-5.c ├── E_10.4-2.c ├── E_10.4-3.c └── P_10-2.c ├── Chapter12 ├── P_12-1.c └── P_12-2.c ├── Chapter13 ├── P_13-1.cpp ├── P_13-4.cpp └── README.md ├── Chapter14 ├── C_14.3.cpp ├── E_14.3-1~5.cpp ├── E_14.3-6.cpp └── README.md ├── Chapter15 └── E_15.1-5.cpp ├── Chapter16 ├── E_16.1-2.cpp └── E_16.1-4.cpp ├── Chapter17 └── C_17.1.c ├── Images ├── RB-INSERT-FIXUP-01.png ├── 区间树-02.png └── 红黑树 RB-DELETE-FIXUP 路线图 .png ├── LICENSE.md ├── Others ├── Brute-Force-Additive-Cipher.c ├── Ext-Euclid.c ├── Modular-Exp.c └── Multiplicative-Inverse.c └── README.md /Chapter02/C_2.3.1.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Chapter 2.3.1 6 | * 文件: MERGE 7 | * 作者: cppgp 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | int merge(int *arr, size_t p, size_t q, size_t r) 18 | { 19 | int i,j,k; 20 | int n1=q-p+1; 21 | int n2=r-q; 22 | int *arr_l, *arr_r; 23 | 24 | assert(NULL!=arr); 25 | assert(p<=q && q 17 | 18 | int main() 19 | { 20 | const int N=8; 21 | int A[N]={1,0,1,1,0,1,1,1}; 22 | int B[N]={0,1,1,0,0,1,0,1}; 23 | int C[N+1]; 24 | int flag=0; // 存放右侧位的溢出 25 | 26 | /* 从最右位开始相加 */ 27 | for (int i=N; i>0; --i) 28 | { 29 | C[i]=A[i-1]+B[i-1]+flag; 30 | if (C[i]>1) { // 如果结果为 2 或 3,最多为 3;说明溢出了 31 | C[i]=C[i]%2; 32 | flag=1; 33 | } else { 34 | flag=0; 35 | } 36 | } 37 | C[0]=flag; 38 | 39 | /* 输出 */ 40 | for (int i=0; i<=N; ++i) { 41 | printf("%d",C[i]); 42 | } 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /Chapter02/E_2.2-2.2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 2.2-2 6 | * 文件名: SELECTION-SORT 7 | * 作者: cppgp 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | void selction_sort(int *arr, size_t size) 18 | { 19 | int i, j, min; 20 | 21 | assert(NULL!=arr); 22 | 23 | for (i=0; i 18 | #include 19 | #include 20 | void selction_sort(int in[], int count) 21 | { 22 | int i=0; 23 | int j=0; 24 | int min_count=0; 25 | 26 | for (i=0; i 17 | 18 | void merge(int A[], int p, int q, int r) { 19 | int i,j,k; 20 | 21 | int n1=q-p+1; 22 | int n2=r-q; 23 | 24 | int L[n1]; 25 | int R[n2]; 26 | 27 | /* 将子数组 A[p..q] 复制到 L[1..n1] */ 28 | for (i=0; i 17 | 18 | /* 迭代 */ 19 | int BSEARCH(int a[], int low, int high, int key) 20 | { 21 | int mid=0; 22 | while (low<=high) {// 注意循环条件 low<=high 23 | mid=low+(high-low)/2; 24 | if (a[mid]==key) 25 | return mid; 26 | else if (a[mid]>key) 27 | high=mid-1; 28 | else 29 | low=mid+1; 30 | } 31 | 32 | return -(low+1); 33 | } 34 | 35 | /* 递归 */ 36 | int RBSEARCH(int a[], int low, int high, int key) 37 | { 38 | if (low>high) 39 | return -(low+1); 40 | int mid=low+(high-low)/2; 41 | if (a[mid]==key) 42 | return mid; 43 | else if (a[mid]>key) 44 | return RBSEARCH(a, low, mid-1, key); 45 | else 46 | return RBSEARCH(a, mid+1, high, key); 47 | } 48 | -------------------------------------------------------------------------------- /Chapter02/E_2.3-5.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 2.3-5 6 | * 文件: BINARY-SEARCH 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | int binary_search(int A[], int length, int v) 18 | { 19 | /* 初始化 */ 20 | int low=0; 21 | int high=length; 22 | 23 | int mid; 24 | while (low 17 | void insertSort(int a[], int len) 18 | { 19 | int i,j,k,key; 20 | int pos,rpos; 21 | 22 | for(i=1; j=0) 27 | rpos=pos; 28 | else 29 | rpos=-pos-1; 30 | for (k=j-1; k>rpos; k--) { 31 | a[k+1]=a[k]; 32 | a[rpos]=key; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter02/E_2.3-7.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 2.3-7 6 | * 文件: FIND 7 | * 作者: qiemengdao.iteye.com 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | /* 18 | * 参数:按升序排列的数组,数组的起始位置,末尾位置,查找和为 key 的两个元素 19 | * 返回结果:若不存在和为 key 的两个元素,返回 0. 否则,返回存在的组数 20 | */ 21 | int find(int a[], int start, int end, int key) 22 | { 23 | int i=start, j=end, num=0; // num 是符合条件的组数 24 | while(1) 25 | { 26 | if (i>j) // 输入错误,break 27 | break; 28 | if (a[i]+a[j]key) // 头尾元素相加>key,则尾元素左移 31 | j--; 32 | else { // 排除其他可能后,头尾元素相加=key,输出 33 | printf("%d+%d=%d\n", a[i],a[j],key); 34 | i++,j--; 35 | num++; 36 | } 37 | } 38 | 39 | return num; 40 | } 41 | -------------------------------------------------------------------------------- /Chapter02/P_2-1.2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 2-1 6 | * 文件名: INSERT-MERGE-SORT & SELECT-MERGE-SORT 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150702 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | 19 | #define INSERTION_SORT_TRESHOLD 20 20 | #define SELECTION_SORT_TRESHOLD 15 21 | 22 | /* 归并排序 */ 23 | void merge(int A[], int p, int q, int r) 24 | { 25 | int i,j,k; 26 | 27 | int n1=q-p+1; 28 | int n2=r-q; 29 | 30 | #ifdef MERGE_HEAP_ALLOCTION 31 | /* 在内存的动态存储区中分配 n 块长度为 size 字节的连续区域,每一位都初始化为零,返回首地址 */ 32 | int *L=calloc(n1, sizeof(int)); 33 | int *R=calloc(n2, sizeof(int)); 34 | #else 35 | int L[n1]; 36 | int R[n2]; 37 | #endif 38 | /* 原型 void *memcpy(void *dest, const void *src, size_t n); */ 39 | /* 由 src 指向地址为起始地址的连续 n 个字节的数据复制到以 destin 指向地址为起始地址空间内 */ 40 | /* 返回值为一个指向 dest 的指针 */ 41 | memcpy(L, A+p, n1*sizeof(int)); 42 | memcpy(R, A+q+1, n2*sizeof(int)); 43 | 44 | /* 从左到右分别比较大小,取较小者赋值给 A[k],合并,并在等待数组中删除 */ 45 | for (i=0,j=0,k=p; k<=r; k++) 46 | { 47 | if (i==n1) { 48 | A[k]=R[j++]; 49 | } else if (j==n2) { 50 | A[k]=L[i++]; 51 | } else if (L[i]<=R[j]) { 52 | A[k]=L[i++]; 53 | } else { 54 | A[k]=R[j++]; 55 | } 56 | } 57 | 58 | #ifdef MERGE_HEAP_ALLOCATION 59 | /* void free( *FirstByte):将之前分配的空间还给程序或操作系统,也就是释放该内存 */ 60 | free(L); 61 | free(R); 62 | #endif 63 | } 64 | 65 | void merge_sort(int A[], int p, int r) { 66 | if (p=p && A[i]>key) 85 | { 86 | A[i+1]=A[i]; 87 | i=i-1; 88 | } 89 | A[i+1]=key; 90 | } 91 | } 92 | 93 | /* 选择排序 */ 94 | void selection_sort(int A[], int p, int r) 95 | { 96 | int min, temp; 97 | for (int i=p; i=r) return; 112 | 113 | if (r-p=r) return; 127 | 128 | if (r-p 17 | 18 | void mergeSort(int A[], int p, int r) 19 | { 20 | if (r-p<=6) { // 这里的 r-p+1<=7, 即 r-p<=6,k 值为 7 21 | return insertSort(A,p,r); 22 | } else { 23 | int q=(p+r)/2; 24 | mergeSort(A,p,q); 25 | mergeSort(A,q+1,r); 26 | mergeSort(A,p,q,r); // ???多一个参数 27 | } 28 | } 29 | 30 | /* 插入排序 */ 31 | void insertSort(int A[], int p, int r) 32 | { 33 | int i,j,key; 34 | 35 | for (j=p+1; j<=r; j++) { 36 | key=A[j]; 37 | i=j-1; 38 | while (i>=p && A[i]>key) { 39 | A[i+1]=A[i]; 40 | i--; 41 | } 42 | A[i+1]=key; 43 | } 44 | } 45 | 46 | 47 | /* 插入排序变形 */ 48 | void insertSort2(int A[], int p, int r) 49 | { 50 | int i,j; 51 | for (i=p; ip&&A[j-1]>A[j]; j--) 53 | swap(A,j,j-1); // 交换数组 A 中的 j 和 j-1 位置处的值 54 | } 55 | -------------------------------------------------------------------------------- /Chapter02/P_2-2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 2-2 6 | * 文件名: BUBBLE-SORT 7 | * 作者: baike 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150707 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | 18 | #define SIZE 8 19 | 20 | void BUBBLE_SORT(int A[], int n); 21 | 22 | void BUBBLE_SORT(int A[], int n) // n 为数组 A 的元素个数 23 | { 24 | int i,j,temp; 25 | for (j=0; jA[i+1]) // 数组元素大小按升序排列 28 | { 29 | temp=A[i]; 30 | A[i]=A[i+1]; 31 | A[i+1]=temp; 32 | } 33 | } 34 | } 35 | 36 | int main() 37 | { 38 | int number[SIZE]={95,45,15,78,84,51,24,12}; 39 | int i; 40 | BUBBLE_SORT(number, SIZE); 41 | /* 输出已排序数组 number */ 42 | for (i=0; i 17 | 18 | int MERGE(int A[], int p, int q, int r) 19 | { 20 | int i,j,k,inversions=0; 21 | 22 | int n1=q-p+1; 23 | int n2=r-q; 24 | 25 | int L[n1]; 26 | int R[n2]; 27 | 28 | for (i=0; i 17 | 18 | void MaxSum(int array[], unsigned int len) 19 | { 20 | if (array==NULL || len<=0) 21 | return; 22 | 23 | int curSum=0, maxSum=0; 24 | int i=0; 25 | for (i=0; imaxSum) // 当前和大于最大和,则重置最大和 32 | maxSum=curSum; 33 | } 34 | 35 | if (maxSum==0) // 最大和依然为 0,说明数组中所有元素都为负值 36 | { 37 | maxSum=array[0]; 38 | for (i=1; imaxSum) { 40 | maxSum=array[i]; 41 | } 42 | } 43 | } 44 | 45 | printf("maxSum: %d\n", maxSum); 46 | } 47 | -------------------------------------------------------------------------------- /Chapter04/E_4.1-3.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 4.1-3 6 | * 名称: BRUTE-FORCE & DIVIDE-CONQUER 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | 18 | #define CROSSOVER_POINT 37 // In skanev's computer 19 | 20 | /* A struct to represent the tuple */ 21 | typedef struct { 22 | unsigned left; 23 | unsigned right; 24 | int sum; 25 | }; max_subarray; 26 | 27 | /* The BRUTE-FORCE approach */ 28 | max_subarray find_maximum_subarray_brute(int A[], unsigned low, unsigned high) 29 | { 30 | max_subarray result={0,0,INT_MIN}; 31 | 32 | for (int i=low; i=(int)low; i--) 59 | { 60 | sum+=A[i]; 61 | if (sum>left_sum) 62 | { 63 | left_sum=sum; 64 | result.left=i; 65 | } 66 | } 67 | 68 | sum=0; 69 | 70 | for (int j=mid; jright_sum) 74 | { 75 | right_sum=sum; 76 | result.right=j+1; 77 | } 78 | } 79 | 80 | result.sum=left_sum+right_sum; 81 | return result; 82 | } 83 | 84 | max_subarray find_maximum_subarray(int A[], unsigned low, unsigned high) 85 | { 86 | if (high==low+1) 87 | { 88 | max_subarray result={low, high, A[low]}; 89 | return result; 90 | } else { 91 | unsigned mid=(low+high)/2; 92 | max_subarray left=find_maximum_subarray(A,low,mid); 93 | max_subarray right=find_maximum_subarray(A,mid,high); 94 | max_subarray cross=find_max_crossing_subarray(A,low,mid,high); 95 | 96 | if (left.sum>=right.sum && left.sum>=cross.sum) { 97 | return left; 98 | } else if (right.sum>=left.sum && right.sum>=cross.sum) { 99 | return right; 100 | } else { 101 | return cross; 102 | } 103 | } 104 | } 105 | 106 | /* The mixed algorithm */ 107 | max_subarray find_maximum_subarray_mixed(int A[], unsigned low, unsigned high) 108 | { 109 | if (high-low=right.sum && left.sum>=cross.sum) { 118 | return left; 119 | } else if (right.sum>=left.sum && right.sum>=cross.sum) { 120 | return right; 121 | } else { 122 | return cross; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Chapter04/E_4.1-4.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 4.1-4 6 | * 名称: BRUTE-FORCE & DIVIDE-CONQUER(empty array) 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | 18 | #define CROSSOVER_POINT 37 // In skanev's computer 19 | 20 | /* A struct to represent the tuple */ 21 | typedef struct { 22 | unsigned left; 23 | unsigned right; 24 | int sum; 25 | }; max_subarray; 26 | 27 | /* The BRUTE-FORCE approach */ 28 | max_subarray find_maximum_subarray_brute(int A[], unsigned low, unsigned high) 29 | { 30 | max_subarray result={0,0,INT_MIN}; 31 | 32 | for (int i=low; i=(int)low; i--) 59 | { 60 | sum+=A[i]; 61 | if (sum>left_sum) 62 | { 63 | left_sum=sum; 64 | result.left=i; 65 | } 66 | } 67 | 68 | sum=0; 69 | 70 | for (int j=mid; jright_sum) 74 | { 75 | right_sum=sum; 76 | result.right=j+1; 77 | } 78 | } 79 | 80 | /* E4.1-4 mod */ 81 | if (left_sum+right_sum<0) 82 | { 83 | /* 返回空子数组 */ 84 | max_subarray empty={mid,mid,0}; 85 | return empty; 86 | } else { 87 | result.sum=left_sum+right_sum; 88 | return result; 89 | } 90 | } 91 | 92 | max_subarray find_maximum_subarray(int A[], unsigned low, unsigned high) 93 | { 94 | if (high==low+1) 95 | { 96 | if (A[low]<0) // 判断是否为空子数组 97 | { 98 | max_subarray empty={low,low,0}; 99 | return empty; 100 | } else { 101 | max_subarray result={low, high, A[low]}; 102 | return result; 103 | } 104 | } else { 105 | unsigned mid=(low+high)/2; 106 | max_subarray left=find_maximum_subarray(A,low,mid); 107 | max_subarray right=find_maximum_subarray(A,mid,high); 108 | max_subarray cross=find_max_crossing_subarray(A,low,mid,high); 109 | 110 | if (left.sum>=right.sum && left.sum>=cross.sum) { 111 | return left; 112 | } else if (right.sum>=left.sum && right.sum>=cross.sum) { 113 | return right; 114 | } else { 115 | return cross; 116 | } 117 | } 118 | } 119 | 120 | /* The mixed algorithm */ 121 | max_subarray find_maximum_subarray_mixed(int A[], unsigned low, unsigned high) 122 | { 123 | if (high-low=right.sum && left.sum>=cross.sum) { 132 | return left; 133 | } else if (right.sum>=left.sum && right.sum>=cross.sum) { 134 | return right; 135 | } else { 136 | return cross; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /Chapter04/E_4.1-5.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 4.1-5 6 | * 名称: MAXIMUM-SUBARRAY(linear time) 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | 18 | typedef struct { 19 | unsigned left; 20 | unsigned right; 21 | int sum; 22 | }; max_subarray; 23 | 24 | max_subarray find_maximum_subarray(int A[], unsigned low, unsigned high) 25 | { 26 | max_subarray suffixes[high-low]; 27 | 28 | suffixes[0].left=low; 29 | suffixes[0].right=low+1; 30 | suffixes[0].sum=A[low]; 31 | 32 | for (int i=low+1; ileft; 41 | suffixes[i].right=i+1; 42 | suffixes[i].sum=previous->sum+A[i]; 43 | } 44 | } 45 | 46 | max_subarray *max=&suffixes[0]; 47 | 48 | for (int i=low+1; isum 17 | 18 | const int N=4; // 常量 N 用来定义矩阵的大小 19 | 20 | void main() 21 | { 22 | void STRASSEN(int n, float A[][N], float B[][N], float C[][N]); 23 | void input(int n, float p[][N]); 24 | void output(int n, float C[][N]); // 函数声明部分 25 | 26 | float A[N][N], B[N][N], C[N][N]; // 定义三个矩阵A,B,C 27 | 28 | cout<<"现在录入矩阵 A[N][N]:"<>p[i][j]; 47 | } 48 | } 49 | 50 | void output(int n, float C[][N]) // 矩阵输出函数 51 | { 52 | int i,j; 53 | cout<<"输出矩阵:"<C 68 | for (j=0; j<2; j++) 69 | { 70 | C[i][j]=0; // 计算完一个 C[i][j] 应重新赋值为零 71 | for (t=0; t<2; t++) 72 | C[i][j]=C[i][j]+A[i][t]*B[t][j]; 73 | } 74 | } 75 | 76 | /* 矩阵加法函数 X+Y-->Z */ 77 | void MATRIX_ADD(int n, float X[][N], float Y[][N], float Z[][N]) 78 | { 79 | int i,j; 80 | for (i=0; iZ */ 86 | void MATRIX_ADD(int n, float X[][N], float Y[][N], float Z[][N]) 87 | { 88 | int i,j; 89 | for (i=0; i 17 | #include 18 | 19 | /* The matrix representation. 20 | * One structure to fit a matrix and a submatrix. 21 | */ 22 | struct matrix { 23 | int x; 24 | int y; 25 | int size; 26 | int original_size; 27 | int *data; 28 | }; 29 | 30 | /* Functions to index matrices */ 31 | int get(matrix m, int x, int y) { 32 | return m.data[m.original_size*(m.x+x)+m.y+y]; 33 | }; 34 | 35 | void put(matrix m, int x, int y, int value) { 36 | m.data[m.original_size*(m.x+x)+m.y+y]=value; 37 | }; 38 | 39 | /* matrix building */ 40 | matrix create_matrix(int size, int *data) 41 | { 42 | matrix result; 43 | result.x=0; 44 | result.y=0; 45 | result.size=size; 46 | result.original_size=size; 47 | result.data=data; 48 | 49 | return result; 50 | } 51 | 52 | matrix submatrix(matrix A, int x, int y, int size) 53 | { 54 | matrix result; 55 | result.x=A.x+x; 56 | result.y=A.y+y; 57 | result.size=size; 58 | result.original_size=A.original_size; 59 | result.data=A.data; 60 | return result; 61 | } 62 | 63 | #define INIT_ON_STACK(m_, size_) \ 64 | m_.x=0; \ 65 | m_.y=0; \ 66 | m_.size=size_; \ 67 | m_.original_size=size_; \ 68 | m_.data=alloca(size_*size_*sizeof(int)); 69 | 70 | /* Adding and subtracting matrices */ 71 | void plus(matrix C, matrix A, matrix B) 72 | { 73 | for (int i=0; i 17 | #include 18 | #include 19 | 20 | #define random(x) (rand()%x) 21 | 22 | int t5_1_2(int low, int high) 23 | { 24 | int i=0; 25 | int count=0; 26 | double j=log(high-low+1)/log(2); 27 | 28 | if (j-(int)j>0) { 29 | j++; 30 | } 31 | 32 | while(1) { 33 | count=0; 34 | for (i=0; i 17 | #include 18 | #include 19 | 20 | int biaseRandom() 21 | { 22 | int i=random(3); 23 | if (i>=1) return 1; 24 | else return 0; 25 | } 26 | 27 | int t5_1_3() 28 | { 29 | int j1=0, j2=0; 30 | while (1) 31 | { 32 | j1=biaseRandom(); 33 | j2=biaseRandom(); 34 | if (j1+j2!=1) { 35 | continue; 36 | } 37 | if (j1==1) return 1; 38 | else return 0; 39 | } 40 | } 41 | 42 | /* 测试代码 */ 43 | int main() 44 | { 45 | int j=0, 46 | i0=0, 47 | i1=0; 48 | for (;j<500;j++) { 49 | if (t5_1_3()==0) i0++; 50 | else i1++; 51 | } 52 | 53 | printf("i0=%d,i1=%d", i0,i1); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /Chapter06/C_6.2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Chapter 6 6 | * 名称: HEAP-SORT 7 | * 作者: Anker 8 | * 语言: c 9 | * 内容摘要: 堆排序 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | 19 | //array's index begins 1, not 0 20 | 21 | #define PARENT(i) (i/2) 22 | #define LEFT(i) (i*2) 23 | #define RIGHT(i) (i*2+1) 24 | #define NOTNUSEDATA -65536 25 | 26 | void adjust_max_heap(int *datas, int length, int i); 27 | void adjust_max_heap_recursive(int *datas, int length, int i); 28 | void build_max_heap(int *datas, int length); 29 | void heap_sort(int *datas, int length); 30 | 31 | int main() 32 | { 33 | int i; 34 | //array's index begin 1 35 | int datas[11]={NOTNUSEDATA,5,3,17,10,84,19,6,22,9,35}; 36 | heap_sort(datas,10); 37 | for (i=1; i<11; ++i) 38 | printf("%d",datas[i]); 39 | printf("\n"); 40 | exit(0); 41 | } 42 | 43 | void adjust_max_heap_recursive(int *datas, int length, int i) 44 | { 45 | int left,right,largest; 46 | int temp; 47 | left=LEFT(i); //left child 48 | right=RIGHT(i); //right child 49 | //find the largest value among left and right and i. 50 | if (left<=length && datas[left]>datas[i]) 51 | largest=left; 52 | else 53 | largest=right; 54 | if (right<=length && datas[right]>datas[largest]) 55 | largest=right; 56 | //exchange i and largest 57 | if (largest!=i) 58 | { 59 | temp=datas[i]; 60 | datas[i]=datas[largest]; 61 | datas[largest]=temp; 62 | //recursive call the function, adjust form largest 63 | adjust_max_heap(datas,length,largest); 64 | } 65 | } 66 | 67 | void adjust_max_heap(int *datas, int length, int i) 68 | { 69 | int left,right,largest; 70 | int temp; 71 | while (1) 72 | { 73 | left=LEFT(i); //left child 74 | right=RIGHT(i); //right child 75 | //find the largest value among left and right and i. 76 | if (left<=length && datas[left]>datas[i]) 77 | largest=i; 78 | else 79 | largest=i; 80 | if (right<=length && datas[right]>datas[largest]) 81 | largest=right; 82 | //exchange i and largest 83 | if (largest!=i) 84 | { 85 | temp=datas[i]; 86 | datas[i]=datas[largest]; 87 | datas[largest]=temp; 88 | i=largest; 89 | continue; 90 | } 91 | else 92 | break; 93 | } 94 | } 95 | 96 | void build_max_heap(int *datas, int length) 97 | { 98 | int i; 99 | //build max heap from the last parent node 100 | for (i=length/2; i>0; i--) 101 | adjust_max_heap(datas,length,i); 102 | } 103 | 104 | void heap_sort(int *datas, int length) 105 | { 106 | int i,temp; 107 | //build max heap 108 | build_max_heap(datas, length); 109 | i=length; 110 | //exchange the first value to the last unitl i=1 111 | while (i>1) 112 | { 113 | temp=datas[i]; 114 | datas[i]=datas[1]; 115 | datas[1]=temp; 116 | i--; 117 | //adjust max heap, make sure the first value is the largest 118 | adjust_max_heap(datas,i,1); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Chapter06/C_6.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Chapter 6 6 | * 名称: HEAP-SORT 7 | * 作者: Anker 8 | * 语言: c 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | /* 递归形式递归 */ 17 | void adjust_max_heap_recursive(int *datas, int length, int i) 18 | { 19 | int left,right,largest; 20 | int temp; 21 | left=LEFT(i); //left child 22 | right=RIGHT(i); //right child 23 | //find the largest value among left and right and i. 24 | if (left<=length && datas[left]>datas[i]) 25 | largest=left; 26 | else 27 | largest=i; 28 | if (right<=length && datas[right]>datas[largest]) 29 | largest=right; 30 | //exchange i and largest 31 | if (largest!=i) 32 | { 33 | temp=datas[i]; 34 | datas[i]=datas[largest]; 35 | datas[largest]=temp; 36 | //recursive call the function, adjust from largest 37 | adjust_max_heap(datas,length,largest); 38 | } 39 | } 40 | 41 | /* 非递归形式调整 */ 42 | void adjust_max_heap(int *datas, int length, int i) 43 | { 44 | int left,right,largest; 45 | int temp; 46 | while(1) 47 | { 48 | left=LEFT(i); //left child 49 | right=RIGHT(i); //right child 50 | //find the largest value among left and right and i. 51 | if (left<=length && datas[left]>datas[i]) 52 | largest=left; 53 | else 54 | largest=i; 55 | if (right<=length && datas[right]>datas[largest]) 56 | largest=right; 57 | //exchange i and largest 58 | if (largest!=i) 59 | { 60 | temp=datas[i]; 61 | datas[i]=datas[largest]; 62 | datas[largest]=temp; 63 | i=largest; 64 | continue; 65 | } 66 | else 67 | break; 68 | } 69 | } 70 | 71 | /* 创建堆 */ 72 | void build_max_heap(int *datas, int length) 73 | { 74 | int i; 75 | //build max heap from the last parent node 76 | for (i=length/2; i>0; i--) 77 | adjust_max_heap(datas, length, i); 78 | } 79 | 80 | /* 堆排序 */ 81 | void heap_sort(int *datas, int length) 82 | { 83 | int i,temp; 84 | //build max heap 85 | build_max_heap(datas, length); 86 | i=length; 87 | //exchange the first value to the last unit1 i=1 88 | while (i>1) 89 | { 90 | temp=datas[i]; 91 | datas[i]=datas[1]; 92 | datas[1]=temp; 93 | i--; 94 | //adjust max heap, make sure the first value is the largest 95 | adjust_max_heap(datas, i, 1); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Chapter06/E_6.2-5.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 6.2-5 6 | * 名称: MAX-HEAPIFY 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 维护堆的性质 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #define PARENT(i) ((i-1)/2) 17 | #define LEFT(i) (2*i+1) 18 | #define RIGHT(i) (2*i+2) 19 | 20 | typedef struct { 21 | int *nodes; 22 | int length; 23 | int heap_size; 24 | } heap; 25 | 26 | void max_heapify(heap A, int i) 27 | { 28 | int left, right, largest, temp; 29 | 30 | while(1) { 31 | left=LEFT(i); 32 | right=RIGHT(i); 33 | 34 | if (leftA.nodes[i]) 35 | largest=left; 36 | else 37 | largest=i; 38 | 39 | if (rightA.nodes[largest]) 40 | largest=right; 41 | 42 | if (largest==i) 43 | return; 44 | 45 | temp=A.nodes[i]; 46 | A.nodes[i]=A.nodes[largest]; 47 | A.nodes[largest]=temp; 48 | 49 | i=largest; // 取消recursive,在循环末尾重新定义节点i 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Chapter06/E_6.5-3.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 6.5-3 6 | * 名称: MIN-HEAPIFY 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 最小堆实现最小优先队列 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | #include 19 | 20 | #define PARENT(i) ((i-1)/2) 21 | #define LEFT(i) (2*i+1) 22 | #define RIGHT(i) (2*i+2) 23 | 24 | typedef struct { 25 | int *elements; 26 | int length; 27 | int heap_size; 28 | } heap_t; 29 | 30 | int heap_minimum(heap_t *heap) { 31 | return heap->elements[0]; 32 | } 33 | 34 | void min_heapify(heap_t *heap, int i) 35 | { 36 | int left=LEFT(i), 37 | right=RIGHT(i), 38 | smallest; 39 | 40 | if (leftheap_size && heap->elements[right]elements[smallest]) { 41 | smallest=right; 42 | } 43 | 44 | if (smallest!=i) 45 | { 46 | int tmp=heap->elements[i]; 47 | heap->elements[i]=heap->elements[smallest]; 48 | heap->elements[smallest]=tmp; 49 | 50 | min_heapify(heap,smallest); 51 | } 52 | } 53 | 54 | int heap_extract_min(heap_t *heap) 55 | { 56 | if (heap->heap_size==0) { 57 | fprintf(stderr,"heap underflow"); 58 | exit(0); 59 | } 60 | 61 | int min=heap->elements[0]; 62 | heap->elements[0]=heap->elements[heap->heap_size-1]; 63 | heap->heap_size--; 64 | min_heapify(heap,0); 65 | 66 | return min; 67 | } 68 | 69 | void heap_decrease_key(heap_t *heap, int i, int key) 70 | { 71 | if (key>heap->elements[i]) { 72 | fprintf(stderr,"new key is larger than current key"); 73 | eixt(0); 74 | } 75 | 76 | heap->elements[i]=key; 77 | while (i>0 && heap->elements[PARENT(i)]>heap->elements[i]) { 78 | int tmp=heap->elements[PARENT(i)]; 79 | heap->elements[PARENT(i)]=heap->elements[i]; 80 | heap->elements[i]=tmp; 81 | i=PARENT(i); 82 | } 83 | } 84 | 85 | void min_heap_insert(heap_t *heap, int key) 86 | { 87 | if (heap->length==heap->heap_size) { 88 | fprintf(stderr,"heap overflow"); 89 | exit(0); 90 | } 91 | 92 | heap->elements[heap->heap_size]=INT_MAX; 93 | heap->heap_size++; 94 | heap_decrease_key(heap,heap->heap_size-1,key); 95 | } 96 | -------------------------------------------------------------------------------- /Chapter06/E_6.5-6.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 6.5-6 6 | * 名称: HEAP-INCREASE-KEY 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 只用一次赋值完成交换操作 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | #include 19 | 20 | #define PARENT(i) ((i-1)/2 21 | #define LEFT(i) (2*2+1) 22 | #define RIGHT (2*i+2) 23 | 24 | typedef struct { 25 | int *elements; 26 | int length; 27 | int heap_size; 28 | } heap_t; 29 | 30 | void heap_increase_key(heap_t *heap, int i, int key) 31 | { 32 | if (keyelements[i]) { 33 | fprintf(stderr,"new key is larger than current key"); 34 | exit(0); 35 | } 36 | 37 | while (i>0 && heap->elements[PARENT(i)]elements[i]=heap->elements[PARENT(i)]; 39 | i=PARENT(i); 40 | } 41 | heap->elements[i]=key; 42 | } 43 | -------------------------------------------------------------------------------- /Chapter06/E_6.5-9.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 6.5-9 6 | * 名称: K-WAY-MERGING 7 | * 作者: windmissing 8 | * 语言: c++ 9 | * 内容摘要: 使用最小堆完成K路归并排序 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | 17 | /* 产品代码 */ 18 | #include 19 | #include 20 | using namespace std; 21 | 22 | #include 23 | 24 | #include "Exercise6_5_8.h" 25 | #include "Heap.h" 26 | 27 | #define K 10 28 | #define DATA_COUNT 100 29 | 30 | ostream& operator<<(ostream & s, const node & n) 31 | { 32 | s << n.value; 33 | return s; 34 | } 35 | 36 | //5个链表,每个链表的头结点放入Head中 37 | int mergeResult[DATA_COUNT+1] = {0}; 38 | CMaxHeap H(K, node::getMaxNode()); 39 | 40 | vector buildTestData(); 41 | void showTestData(vector inputParam); 42 | void insertListHeadToHeap(vector &inputParam, int listIndex); 43 | void showResult(); 44 | void recordMergeResult(int data); 45 | ARRAY solve_6_5_8(vector inputParam); 46 | 47 | int K_Merge_6_5_8() 48 | { 49 | vector inputParam = buildTestData(); 50 | showTestData(inputParam); 51 | 52 | ARRAY result = solve_6_5_8(inputParam); 53 | 54 | showResult(); 55 | return 0; 56 | } 57 | 58 | ARRAY solve_6_5_8(vector inputParam) 59 | { 60 | ARRAY ret; 61 | while(H.isEmpty() == false) 62 | H.extract(); 63 | 64 | for(int i = 0; i < inputParam.size(); i++) 65 | insertListHeadToHeap(inputParam, i); 66 | while(H.isEmpty() == false) 67 | { 68 | node top = H.extract(); 69 | ret.push_back(top); 70 | insertListHeadToHeap(inputParam, top.list); 71 | } 72 | return ret; 73 | } 74 | 75 | vector buildTestData() 76 | { 77 | int value, list; 78 | //构造需要合并的数据 79 | vector ret(K); 80 | for(value = DATA_COUNT; value >0; value--) 81 | { 82 | list = rand() % K; 83 | node newNode;// = {list, value}; 84 | newNode.list = list; 85 | newNode.value = value; 86 | ret[list].push_back(newNode); 87 | } 88 | return ret; 89 | } 90 | 91 | void showTestData(vector inputParam) 92 | { 93 | cout<<"显示待排序数据"< &inputParam, int listIndex) 104 | { 105 | ARRAY &array = inputParam[listIndex]; 106 | if(array.size() != 0) 107 | { 108 | H.insert(array[0]); 109 | array.erase(array.begin()); 110 | } 111 | } 112 | 113 | void showResult() 114 | { 115 | //输出合并结果 116 | cout<<"输出合并结果"< 129 | using namespace std; 130 | 131 | #include "Exercise6_5_8.h" 132 | 133 | #include "gtest/gtest.h" 134 | #include "gmock/gmock.h" 135 | // Tests factorial of negative numbers. 136 | // 137 | using ::testing::_; 138 | using ::testing::SetArgPointee; 139 | using ::testing::DoAll; 140 | using ::testing::Return; 141 | using ::testing::Pointee; 142 | 143 | ARRAY setArray(int *initArray, int len, int list) 144 | { 145 | ARRAY ret; 146 | for(int i = 0; i < len; i++) 147 | { 148 | node newNode; 149 | newNode.value = initArray[i]; 150 | newNode.list = list; 151 | ret.push_back(newNode); 152 | } 153 | return ret; 154 | } 155 | 156 | bool compare(ARRAY A, ARRAY B) 157 | { 158 | if(A.size() != B.size()) 159 | return false; 160 | for(int i = 0; i < A.size(); i++) 161 | if(A[i].value != B[i].value) 162 | return false; 163 | return true; 164 | } 165 | 166 | TEST(only_one_array, only_one_data_in_array) 167 | { 168 | int initArray[1] = {5}; 169 | ARRAY array = setArray(initArray, 1, 0); 170 | vector inputParam; 171 | inputParam.push_back(array); 172 | 173 | ARRAY result = solve_6_5_8(inputParam); 174 | EXPECT_TRUE(compare(array, result)); 175 | } 176 | 177 | void printArray(ARRAY array) 178 | { 179 | for(int i = 0; i < array.size(); i++) 180 | cout< inputParam; 191 | inputParam.push_back(array1); 192 | inputParam.push_back(array2); 193 | 194 | ARRAY result = solve_6_5_8(inputParam); 195 | 196 | int expectArray[2] = {5, 4}; 197 | ARRAY expect = setArray(expectArray, 2, 0); 198 | EXPECT_TRUE(compare(expect, result)); 199 | } 200 | 201 | TEST(two_array, negitave_data_in_array) 202 | { 203 | int initArray1[5] = {13, 10, 7, -1, -4}; 204 | ARRAY array1 = setArray(initArray1, 5, 0); 205 | int initArray2[10] = {15, 14, 12, 11, 9, 8, 6, 0, -2, -3}; 206 | ARRAY array2 = setArray(initArray2, 10, 1); 207 | vector inputParam; 208 | inputParam.push_back(array1); 209 | inputParam.push_back(array2); 210 | 211 | ARRAY result = solve_6_5_8(inputParam); 212 | 213 | int expectArray[15] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 0, -1, -2, -3, -4}; 214 | ARRAY expect = setArray(expectArray, 15, 0); 215 | EXPECT_TRUE(compare(expect, result)); 216 | } 217 | 218 | TEST(three_array, different_data_count_in_array) 219 | { 220 | int initArray1[6] = {10, 9, 8, 4, 3, 2}; 221 | ARRAY array1 = setArray(initArray1, 6, 0); 222 | int initArray2[2] = {7, 1}; 223 | ARRAY array2 = setArray(initArray2, 2, 1); 224 | int initArray3[4] = {6, 5, 0, -1}; 225 | ARRAY array3 = setArray(initArray3, 4, 2); 226 | vector inputParam; 227 | inputParam.push_back(array1); 228 | inputParam.push_back(array2); 229 | inputParam.push_back(array3); 230 | 231 | ARRAY result = solve_6_5_8(inputParam); 232 | 233 | int expectArray[15] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1}; 234 | ARRAY expect = setArray(expectArray, 12, 0); 235 | EXPECT_TRUE(compare(expect, result)); 236 | } 237 | -------------------------------------------------------------------------------- /Chapter06/P_6-2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 6-2 6 | * 名称: D-ARY-HEAP 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 对d叉堆的分析 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | #include 19 | 20 | #define PARENT(i,d) ((i-1)/d) 21 | #define CHILD(i,c,d) (3*i+c+1) 22 | 23 | typedef struct { 24 | int *elements; 25 | int d; 26 | int heap_size; 27 | int length; 28 | } heap_t; 29 | 30 | void max_heapify(heap_t *heap, int i) 31 | { 32 | int largest=i; 33 | 34 | for (int k=0; kd; k++) { 35 | int child=CHILD(i,k,heap->d); 36 | if (childheap_size && heap->elements[child]>heap->elements[largest]) 37 | largest=child; 38 | } 39 | 40 | if (largest!=i) 41 | { 42 | int tmp=heap->elements[i]; 43 | heap->elements[i]=heap->elements[largest]; 44 | heap->elements[largest]=tmp; 45 | 46 | max_heapify(heap,largest); 47 | } 48 | } 49 | 50 | int extract_max(heap_t *heap) 51 | { 52 | int max=heap->elements[0]; 53 | heap->elements[0]=heap->elements[heap->heap_size-1]; 54 | heap->heap_size--; 55 | max_heapify(heap,0); 56 | return max; 57 | }; 58 | 59 | void increase_key(heap_t *heap, int i, int key) 60 | { 61 | if (keyelements[i]) { 62 | fprintf(stderr,"new key is smaller than current key\n"); 63 | exit(0); 64 | } 65 | 66 | while (i>0 && heap->elements[PARENT(i,heap->d)]elements[i]=heap->elements[PARENT(i,heap->d)]; 68 | i=PARENT(i,heap->d); 69 | } 70 | 71 | heap->elements[i]=key; 72 | } 73 | 74 | void insert(heap_t *heap, int key) 75 | { 76 | heap->heap_size++; 77 | heap->elements[heap->heap_size-1]=INT_MIN; 78 | increase_key(heap,heap->heap_size-1,key); 79 | } 80 | -------------------------------------------------------------------------------- /Chapter06/P_6-3.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 6-3 6 | * 名称: YOUNG-TABLEAUS 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: Young氏矩阵 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | typedef struct { 22 | int i; 23 | int j; 24 | } cell; 25 | 26 | typedef struct { 27 | int *elements; 28 | int m; 29 | int n; 30 | } tableau_t; 31 | 32 | cell up(cell c) { 33 | cell result={c.i-1, c.j}; 34 | return result; 35 | } 36 | 37 | cell down(cell c) { 38 | cell result={c.i+1, c.j}; 39 | return result; 40 | } 41 | 42 | cell left(cell c) { 43 | cell result={c.i, c.j-1}; 44 | return result; 45 | } 46 | 47 | cell right(cell c) { 48 | cell result={c.i, c.j+1}; 49 | return result; 50 | } 51 | 52 | cell make_cell(int i, int j) { 53 | cell result={i,j}; 54 | return result; 55 | } 56 | 57 | bool within(tableau_t *tableau, cell c) { 58 | int index=c.i*tableau->n+c.j; 59 | return tableau->elements[index]; 60 | } 61 | 62 | void set(tableau_t *tableau, cell c, int value) { 63 | int index=c.i*tableau->n+c.j; 64 | tableau->elements[index]=value; 65 | } 66 | 67 | void init_empty_tableau(tableau_t *tableau) { 68 | for (int i=0; im*tableau->n; i++) { 69 | tableau->elements[i]=INT_MAX; 70 | } 71 | } 72 | 73 | int extract_min(tableau_t *tableau) 74 | { 75 | int min, new; 76 | cell current={0,0}, next; 77 | 78 | new=INT_MAX; 79 | min=get(tableau,current); 80 | 81 | set(tableau,current,INT_MAX); 82 | 83 | while (true) { 84 | int smallest; 85 | cell d=down(current); 86 | cell r=right(current); 87 | 88 | if (within(tableau,d) && get(tableau,d)m-1, tableau->n-1) 115 | next; 116 | 117 | if (get(tableau,current)!=INT_MAX) { 118 | fprintf(stderr,"tableau is full\n"); 119 | exit(0); 120 | } 121 | 122 | while (true) { 123 | int largest; 124 | cell u=up(current); 125 | cell l=left(current); 126 | 127 | if (within(tableau,u) && get(tableau,u)>key) { 128 | next=u; 129 | largest=get(tableau,next); 130 | } else { 131 | largest=key; 132 | } 133 | 134 | if (within(tableau,l) && get(tableau,l)>largest) { 135 | next=l; 136 | largest=get(tableau,next); 137 | } 138 | 139 | if (key==largest) { 140 | set(tableau,current,key); 141 | break; 142 | } 143 | 144 | set(tableau,current,largest); 145 | current=next; 146 | } 147 | } 148 | 149 | void sort(int *array, int size_sqrt) 150 | { 151 | int elements[size_sqrt*size_sqrt]; 152 | tableau_t tableau={elements,size_sqrt,size_sqrt}; 153 | 154 | init_empty_tableau(&tableau); 155 | 156 | for (int i=0; im-1,0}; 169 | 170 | while (within(tableau,c)) { 171 | int value=get(tableau,c); 172 | 173 | if (value==key) { 174 | return true; 175 | } else if (value>key) { 176 | c=up(c); 177 | } else { 178 | c=right(c); 179 | } 180 | } 181 | 182 | return false; 183 | } 184 | -------------------------------------------------------------------------------- /Chapter07/C_7.3.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Chapter 7.3 6 | * 名称: RANDOMIZED-QUICKSORT 7 | * 作者: alan-forever 8 | * 语言: 9 | * 内容摘要: 快速排序随机化版本 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | int RANDOMIZED_PARTITION(int A[], int p, int r) 17 | { 18 | int i=p+rand()%(r-p+1); 19 | int temp=A[r]; 20 | A[r]=A[i]; 21 | A[i]=temp; 22 | return PARTITION(A,p,r); 23 | } 24 | 25 | int PARTITION(int A[], int p, int r) 26 | { 27 | int x=A[r]; 28 | int i=p-1; 29 | int j; 30 | for (j=p; j<=r-1; j++) 31 | { 32 | if (A[j]<=x) 33 | { 34 | i++; 35 | int temp=A[i]; 36 | A[i]=A[j]; 37 | A[j]=temp; 38 | } 39 | } 40 | int temp=A[i+1]; 41 | A[i+1]=A[r]; 42 | A[r]=temp; 43 | return i+1; 44 | } 45 | 46 | void RANDOMIZED_QUICKSORT(int A[], int p, int r) 47 | { 48 | if (ptreshold) 49 | { 50 | int q=partition(A,p,r); 51 | limited_quicksort(A,p,q,treshold); 52 | limited_quicksort(A,q+1,r,treshold); 53 | } 54 | } 55 | 56 | int partition(int A[], int p, int r) 57 | { 58 | int x,i,j,tmp; 59 | 60 | x=A[r-1]; 61 | i=p; 62 | 63 | for (j=p; j=p && A[i]>key; i--) { 87 | A[i+1]=A[i]; 88 | } 89 | A[i+1]=key; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Chapter07/E_7.4-5.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 7.4-5 6 | * 名称: MODIFIED-QUICKSORT 7 | * 作者: windmissing 8 | * 语言: C++ 9 | * 内容摘要: 利用插入排序改善快排 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | // 利用插入排序改善快排 17 | int k=4; 18 | 19 | // 划分 20 | int Partition(int *A, int p, int r) 21 | { 22 | // 选择A[r]作为主元 23 | int x=A[r]; 24 | int i=p-1, j; 25 | bool flag=0; 26 | 27 | for (j=p; j=k) 50 | { 51 | // 以某个主元为标准,把数组分为两部分,左边都比主元小,右边都比主元大 52 | int q=Partition(A,p,r); 53 | // 分别对左边和右边排序 54 | QuickSort(A,p,q-1); 55 | QuickSort(A,q+1,r); 56 | } 57 | } 58 | 59 | // 插入排序 60 | void InsertSort(int *A, int p, int r) 61 | { 62 | int i, j; 63 | for (i=p+1; i<=r; i++) 64 | { 65 | int temp=A[i]; 66 | j=i; 67 | while (A[j-1]>temp) { 68 | A[j]=A[j-1]; 69 | j--; 70 | } 71 | A[j]=temp; 72 | } 73 | } 74 | 75 | void Sort(int *A, int p, int r) 76 | { 77 | // 先进行粗粒度的快排 78 | QuickSort(A,p,r); 79 | // 逐个进行插入排序 80 | InsertSort(A,p,r); 81 | } 82 | -------------------------------------------------------------------------------- /Chapter07/P_7-1.2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 7-1 6 | * 名称: HOARE-PARTITION 7 | * 作者: windmissing 8 | * 语言: c 9 | * 内容摘要: Hoare划分 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | 18 | int Hoare_Partition(int *A, int p, int r) { 19 | int x=A[p], 20 | i=p-1, 21 | j=r+1; 22 | 23 | while(true) 24 | { 25 | do { j--; } while (A[j]>x); 26 | do { i++; } while (A[i] 17 | 18 | int hoare_partition(int A[], int p, int r) { 19 | int x=A[p], 20 | i=p-1, 21 | j=r, 22 | tmp; 23 | 24 | while(true) { 25 | do { j--; } while (!(A[j]<=x)); 26 | do { i++; } while (!(A[i]>=x)); 27 | 28 | if (ix) 23 | j--; 24 | A[i]=A[j]; 25 | while(i 17 | 18 | #define EXCHANGE(a,b) tmp=a; a=b; b=tmp; 19 | 20 | typedef struct { 21 | int q; 22 | int t; 23 | } pivot_t; 24 | 25 | pivot_t partition(int[], int, int); 26 | pivot_t randomized_partition(int[], int, int); 27 | 28 | void quicksort(int A[], int p, int r) { 29 | if (p=t; i--) { 61 | if (A[i]==x) { 62 | EXCHANGE(A[t], A[i]); 63 | t++; 64 | } 65 | } 66 | 67 | pivot_t result={q, t}; 68 | return result; 69 | } 70 | -------------------------------------------------------------------------------- /Chapter07/P_7-4.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 7-4 6 | * 名称: TAIL-RECURSIVE-QUICKSORT 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: stack depth for quicksort 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | 18 | int partition(int[], int, int); 19 | 20 | static int stack_depth=0; 21 | static int max_stack_depth=0; 22 | 23 | void reset_stack_depth_counter(); 24 | void increment_stack_depth(); 25 | void decrement_stack_depth(); 26 | 27 | void tail_recursive_quicksort(int A[], int p, int r) { 28 | increment_stack_depth(); 29 | 30 | while (p 17 | #include 18 | 19 | typedef struct { 20 | int left; 21 | int right; 22 | } interval; 23 | 24 | bool intersects(interval a, interval b) { return a.left<=b.right && b.left<=a.right; } 25 | bool before(interval a, interval b) { return a.rightb.right; } 27 | 28 | #define EXCHANGE(a,c) tmp=a; a=b; b=tmp; 29 | 30 | interval partition(interval A[], int p, int r) { 31 | int pick, s, t, i; 32 | interval intersection, tmp; 33 | 34 | // Pick a random interval as a pivot 35 | pick=p+rand()%(r-p); 36 | EXCHANGE(A[pick], A[r-1]); 37 | intersection=A[r-1]; 38 | 39 | // Find an intersection of the pivot and other intervals 40 | for (i=p; i intersection.left) 43 | intersection.left=A[i].left; 44 | if (A[i].right < intersection.right) 45 | intersection.right=A[i].right; 46 | } 47 | } 48 | 49 | // Classic partition around the intersection 50 | for (i=s=p; i 17 | 18 | typedef struct { 19 | int key; 20 | int value; 21 | } item; 22 | 23 | static item tmp; 24 | 25 | #define EXCHANGE(a,b) tmp=a; a=b; b=tmp; 26 | 27 | void stable_linear_sort(item *A, int size) 28 | { 29 | int zero=0; 30 | one =0; 31 | item copy[size]; 32 | 33 | for (int i=0; iright) { 63 | return; 64 | } 65 | 66 | EXCHANGE(A[left], A[right]); 67 | } 68 | } 69 | 70 | void stable_in_place_sort(item *A, int size) { 71 | for (int i=size; i>0; i--) { 72 | for (int j=0; jA[j+1].key) { 74 | EXCHANGE(A[j], A[j+1]); 75 | } 76 | } 77 | } 78 | } 79 | 80 | void in_place_counting_sort(item *A, int size, int range) 81 | { 82 | int counts[range+1]; 83 | int positions[range+1]; 84 | 85 | for (int i=0; i<=range; i++) { 86 | counts[i]=0; 87 | } 88 | 89 | for (int i=0; i 17 | #include 18 | 19 | #define MAX_LENGTH 10 20 | 21 | //---------------- Structs and typedefs ----------------------- 22 | 23 | /* In order to simplify everything, both numbers and strings are 24 | * meshed in a single union called key_t. The key does not know 25 | * whether it is a number or a string - the handling code already 26 | * knows it instead. */ 27 | 28 | union key_t { 29 | int number; 30 | char string[MAX_LENGTH+1]; 31 | }; 32 | 33 | typedef struct { 34 | union key_t key; 35 | int value; 36 | } item; 37 | 38 | typedef int (*key_f)(item, int); 39 | typedef int (*dimension_f)(item); 40 | typedef int (*compare_f)(item, item); 41 | 42 | //---------------- Prototypes --------------------------------- 43 | 44 | /* Varoius sorting functions */ 45 | 46 | void partition(item *A, int size, int digits, int *groups, dimension_f dimension); 47 | void radix_sort(item *A, int left, int right, int digits, key_f key); 48 | void counting_sort(item *A, int left, int right, int dimension, key_f key, int key_index); 49 | 50 | /* Functions to work on numbers */ 51 | 52 | int item_nth_digit(item i, int d); 53 | int item_digits(item i); 54 | 55 | /* Functions to work on strings */ 56 | int item_string_length(item i); 57 | int item_nth_char(item i, int d); 58 | 59 | //---------------- The solutions ------------------------------ 60 | 61 | void sort_numbers(item *A, int size, int max_digits) 62 | { 63 | int groups[max_digits+1]; 64 | 65 | partition(A, size, max_digits, groups, item_digits); 66 | 67 | for (int i=1; i0; len--) { 79 | counting_sort(A, groups[len-1], size, 26, item_nth_char, len-1); 80 | } 81 | } 82 | 83 | //---------------- Auxiliary sorting functions ----------------- 84 | 85 | /* Performs counting sort on a dimension (number of digits or 86 | * string length) and populates a table (groups) with the position 87 | * of each dimension. */ 88 | 89 | void partition(item *A, int size, int max_dimension, int *groups, dimension_f dimension) 90 | { 91 | int counts[max_length+1]; 92 | itme temp[size]; 93 | 94 | for (int i=0; i=0; i--) 101 | { 102 | int d=dimension(temp[i]); 103 | int count=counts[d]; 104 | 105 | A[count-1]=temp[i]; 106 | counts[d]--; 107 | } 108 | } 109 | 110 | /* A simple radix sort */ 111 | 112 | void radix_sort(item *A, int left, int right, int digits, key_f key) 113 | { 114 | for (int i=0; i=0; i--) 133 | { 134 | int n=key(temp[i], key_index); 135 | int count=counts[n]; 136 | 137 | A[left+count-1]=temp[i]; 138 | counts[n]--; 139 | } 140 | } 141 | 142 | //---------------- Key handling --------------------------------- 143 | 144 | int count_digits(int a) 145 | { 146 | if (n==0) { 147 | return 1; 148 | } else { 149 | return (int) log10(n)+1; 150 | } 151 | } 152 | 153 | int nth_digit(int n, int d) 154 | { 155 | int magnitude=(int)pow(10, d); 156 | 157 | return (n/magnitude)%10; 158 | } 159 | 160 | int item_nth_digit(item i, int d) { 161 | return nth_digit(i.key.number, d); 162 | } 163 | 164 | int item_digits(item i) { 165 | return count_digits(i.key.number); 166 | } 167 | 168 | int item_string_length(item a) { 169 | return strlen(a.key.string); 170 | } 171 | 172 | int item_nth_char(item a, int n) { 173 | return a.key.string[n]-'a'; 174 | } 175 | -------------------------------------------------------------------------------- /Chapter08/P_8-5.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 8-5 6 | * 名称: Average sorting 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 平均排序 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | typedef struct { 22 | int values; 23 | int s; 24 | } item; 25 | 26 | typedef struct { 27 | item *elements; 28 | int length; 29 | int heap_size; 30 | } heap_t; 31 | 32 | typedef struct { 33 | int size; 34 | int k; 35 | int exhausted; 36 | int *next_indices; 37 | } sort_state_t; 38 | 39 | void merge_sort(int A[], int p, int r, int k, int s); 40 | void min_heap_insert(heap_t *heap, item key); 41 | int state_took_column(sort_state_t *state, int index); 42 | item min_heap_push_pop(heap_t *heap, item new); 43 | item heap_minimum(heap_t *heap); 44 | item heap_extract_min(heap_t *heap); 45 | 46 | /* Average sorting is performed by just merge-sorting each column. 47 | * That was easy. Modifying merge sort was hard. */ 48 | 49 | void k_sort(int *numbers, int size, int k) 50 | { 51 | for (int i=0; isize, 96 | k=state->k, 97 | s=index, 98 | *next_indices=state->next_indices; 99 | 100 | if (next_indices[s]>=size) { 101 | while (state->exhaustedexhausted]>=state->size) { 102 | state->exhausted++; 103 | } 104 | 105 | if (state->exhausted==k) { 106 | return -1; 107 | } 108 | 109 | int next=next_indices[state->exhausted]; 110 | next_indices[state->exhausted]+=k; 111 | return next; 112 | } else { 113 | int next=next_indices[s]; 114 | next_indices[s]+=k; 115 | return s; 116 | } 117 | } 118 | 119 | /* This is the merge sort from Chapter 2, modified to look only at 120 | * indices congruent to k modulo s. There are two very ugly and 121 | * long macros that perform this unpleasant job. There's probably 122 | * a nicer way to do the calculation, but modular arithmetic has 123 | * always been my Achilles' heel. */ 124 | 125 | #define FIRST(index,k,s) ((index)+(s)-(index)%(k)+((index)%(k)<=(s)?0:(k))) 126 | #define COUNT(a,b,k,s) ((b)-(a))/(k)+((((s)-(a)%(k))+(k))%(k)<((b)-(a))%(k)?1:0)) // 多了一个)? 127 | 128 | void merge(int A[], int p, int q, int r, int k, int s) 129 | { 130 | int i, j, l; 131 | 132 | int n1=COUNT(p, q, k, s); 133 | int n2=COUNT(q, r, k, s); 134 | 135 | int L[n1]; 136 | int R[n2]; 137 | 138 | for (i=FIRST(p,k,s),j=0; i1) { 158 | int q=(p+r)/2; 159 | merge_sort(A,p,q,k,s); 160 | merge_sort(A,q,r,k,s); 161 | merge(A,p,q,r,k,s); 162 | } 163 | } 164 | 165 | /* Finally, the min heap from exercise 6.5-3, modified to store items 166 | * instead of ints. When I first wrote it, I made an error int the 167 | * implementation and that sent me in an hour-long debugging session. 168 | * C is fun. 169 | * 170 | * Also, there is a new heap operation (min_heap_push_pop) that is a 171 | * faster than heap_extract_min and then min_heap_insert. */ 172 | 173 | #define PARENT(i) ((i-1)/2) 174 | #define LEFT(i) (2*i+1) 175 | #define RIGHT(i) (2*i+2) 176 | 177 | item heap_minimum(heap_t *heap) { 178 | return heap->elements[0]; 179 | } 180 | 181 | void min_heapify(heap_t *heap, int i) 182 | { 183 | int left=LEFT(i), 184 | right=RIGHT(i), 185 | smallest; 186 | 187 | if (left < heap->heap_size && heap->elements[left].value < heap->elements[i].value) { 188 | smallest=left; 189 | } else { 190 | smallest=i; 191 | } 192 | 193 | if (right < heap->heap_size && heap->elements[right].value < heap->elements[smallest].value) { 194 | smallest=right; 195 | } 196 | 197 | if (smallest != i) { 198 | item tmp=heap->elements[i]; 199 | heap->elements[i]=heap->elements[smallest]; 200 | heap->elements[smallest]=tmp; 201 | 202 | min_heapify(heap, smallest); 203 | } 204 | } 205 | 206 | item heap_extract_min(heap_t *heap) 207 | { 208 | if (heap->heap_size==0) { 209 | fprintf(stderr, "heap underflow"); 210 | exit(0); 211 | } 212 | 213 | item min=heap->elements[0]; 214 | heap->elments[0] = heap->elements[heap->heap_size-1]; 215 | heap->heap_size--; 216 | min_heapify(heap, 0); 217 | 218 | return min; 219 | } 220 | 221 | void heap_decrease_key(heap_t *heap, int i, item key) 222 | { 223 | if (key.value > heap->elements[i].value) { 224 | fprintf(stderr, "new key is larger than current key"); 225 | exit(0); 226 | } 227 | 228 | heap->elements[i].value=key.value; 229 | while (i>0 && heap->elements[PARENT(i)].value > heap->elements[i].value) { 230 | item tmp = heap->elements[PARENT(i)]; 231 | heap->elements[PARENT(i)] = heap->elements[i]; 232 | heap->elements[i] = tmp; 233 | i=PARENT(i); 234 | } 235 | } 236 | 237 | void min_heap_insert(heap_t *heap, item key) 238 | { 239 | if (heap->length == heap->heap_size) { 240 | fprintf(stderr, "heap overflow"); 241 | exit(0); 242 | } 243 | 244 | heap->elements[heap->heap_size].value = INT_MAX; 245 | heap->elements[heap->heap_size].s = key.s; 246 | heap->heap_szie++; 247 | heap_decrease_key(heap, heap->heap_size-1, key); 248 | } 249 | 250 | item min_heap_push_pop(heap_t *heap, item new) 251 | { 252 | item result = heap->elements[0]; 253 | heap->elements[0] = new; 254 | min_heapify(heap, 0); 255 | return result; 256 | } 257 | -------------------------------------------------------------------------------- /Chapter08/P_8-7.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 8-7 6 | * 名称: The 0-1 sorting lemma and solumnsort 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 0-1排序引理和列排序 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define STDLIB_SORT qsort 22 | 23 | typedef unsigned int number; 24 | 25 | typedef struct { 26 | size_t start; 27 | size_t size; 28 | } column_t; 29 | 30 | typedef void column_sorter(number *, column_t *, int); 31 | 32 | void check_dimensions(size_t r, size_t s); 33 | 34 | /** 35 | * The basic column sort implementation. It does a copy of the array for steps 36 | * 3 and 5. It also does not sort the half-columns in the beginning and the 37 | * end, since that is not necessary for the correctness of the algorithm. 38 | */ 39 | 40 | void columnsort(number *A, size_t r, size_t s, column_sorter sort_columns) { 41 | size_t size = r * s; 42 | number *copy; 43 | column_t columns[s]; 44 | 45 | check_dimensions(r, s); 46 | 47 | copy = calloc(size, sizeof(number)); 48 | 49 | for (size_t i = 0; i < s; i++) { 50 | columns[i] = (column_t) {i * r, r}; 51 | } 52 | 53 | sort_columns(A, columns, s); 54 | 55 | for (size_t i = 0; i < size; i++) { 56 | copy[(i % s) * r + i / s] = A[i]; 57 | } 58 | 59 | sort_columns(copy, columns, s); 60 | 61 | for (size_t i = 0; i < size; i++) { 62 | A[i] = copy[(i % s) * r + i / s]; 63 | } 64 | 65 | sort_columns(A, columns, s); 66 | 67 | for (size_t i = 0; i < s - 1; i++) { 68 | columns[i] = (column_t) {i * r + r / 2, r}; 69 | } 70 | 71 | sort_columns(A, columns, s - 1); 72 | 73 | free(copy); 74 | } 75 | 76 | /* 77 | * A function that compares numbers, to be passed to the stdlib sort. 78 | */ 79 | 80 | int compare(const void *a, const void *b) { 81 | number *first = (number *) a; 82 | number *second = (number *) b; 83 | 84 | if (*first == *second) { 85 | return 0; 86 | } else if (*first > *second) { 87 | return 1; 88 | } else { 89 | return -1; 90 | } 91 | } 92 | 93 | /* 94 | * Verified the dimensions of the passed array. 95 | */ 96 | 97 | void check_dimensions(size_t r, size_t s) { 98 | if (r % 2) { 99 | fprintf(stderr, "r must be even\n"); 100 | exit(0); 101 | } 102 | 103 | if (r % s) { 104 | fprintf(stderr, "s must divide r\n"); 105 | exit(0); 106 | } 107 | 108 | if (r < 2 * s * s) { 109 | fprintf(stderr, "r must be grater than 2s²\n"); 110 | exit(0); 111 | } 112 | } 113 | 114 | /* 115 | * A utility function to call with the array and a column. 116 | */ 117 | 118 | void sort(number *A, column_t column) { 119 | STDLIB_SORT(A + column.start, column.size, sizeof(number), compare); 120 | } 121 | 122 | /* 123 | * Sequential sorting of columns 124 | */ 125 | 126 | void sequential_sort_columns(number *numbers, column_t *columns, int size) { 127 | for (int i = 0; i < size; i++) { 128 | sort(numbers, columns[i]); 129 | } 130 | } 131 | 132 | /* 133 | * Parallel sorting of columns. This implementation is a bit naïve - it can 134 | * reuse existing threads instead of spawning new ones every time. Furthermore, 135 | * I never explored using locking mechanisms instead of joining the threads. 136 | */ 137 | 138 | typedef struct { 139 | number *numbers; 140 | column_t column; 141 | } job_t; 142 | 143 | void *sort_job(void *pjob) { 144 | job_t *job = (job_t *) pjob; 145 | sort(job->numbers, job->column); 146 | return NULL; 147 | } 148 | 149 | void threaded_sort_columns(number *numbers, column_t *columns, int size) { 150 | void *status; 151 | pthread_t threads[size]; 152 | job_t jobs[size]; 153 | pthread_attr_t attr; 154 | 155 | pthread_attr_init(&attr); 156 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 157 | 158 | for (int i = 0; i < size; i++) { 159 | jobs[i] = (job_t) {numbers, columns[i]}; 160 | pthread_create(&threads[i], &attr, sort_job, &jobs[i]); 161 | } 162 | 163 | for (int i = 0; i < size; i++) { 164 | pthread_join(threads[i], &status); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /Chapter09/E_9.2-3.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 9.2-3 6 | * 名称: RANDOMIZED-SELECT 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: RANDOMIZED-SELECT循环结构 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | 18 | static int tmp; 19 | #define EXCHANGE(a,b) { tmp=a; a=b; b=tmp; } 20 | 21 | int randomized_partition(int *A, int p, int r); 22 | 23 | int randomized_select(int *A, int p, int r, int i) 24 | { 25 | while (p 17 | #include 18 | 19 | #define MAX_SIZE 10 20 | 21 | typedef struct { 22 | int items[MAX_SIZE]; 23 | int head; 24 | int tail; 25 | } deque_t; 26 | 27 | void init_deque(deque_t *deque) 28 | { 29 | deque->head=-1; 30 | deque->tail=0; 31 | } 32 | 33 | int is_empty(deque_t *deque) 34 | { 35 | return (deque->head==-1); 36 | } 37 | 38 | void push(deque_t *deque, int n) 39 | { 40 | if (deque->head == deque->tail) { 41 | fprintf(stderr, "Deque overflow\n"); 42 | exit(1); 43 | } 44 | 45 | deque->items[deque->tail]=n; 46 | 47 | if (deque->head == -1) { 48 | deque->head = deque->tail; 49 | } 50 | 51 | deque->tail = (deque->tail+1)%MAX_SIZE; 52 | } 53 | 54 | void unshift(deque_t *deque, int n) 55 | { 56 | if (deque->head == deque->tail) { 57 | fprintf(stderr, "Deque overflow\n"); 58 | exit(1); 59 | } 60 | 61 | if (deque->head == -1) { 62 | deque->head = deque->tail; 63 | } 64 | 65 | deque->head = (deque->head-1+MAX_SIZE)%MAX_SIZE; 66 | deque->items[deque->head]=n; 67 | } 68 | 69 | int pop(deque_t *deque) 70 | { 71 | if (deque->head == -1) { 72 | fprintf(stderr, "Deque underflow\n"); 73 | exit(1); 74 | } 75 | 76 | deque->tail = (deque->tail+MAX_SIZE-1)%MAX_SIZE; 77 | 78 | if (deque->tail == deque->head) { 79 | deque->head = -1; 80 | } 81 | 82 | return deque->items[deque->tail]; 83 | } 84 | 85 | int shift(deque_t *deque) 86 | { 87 | if (deque->head == -1) { 88 | fprintf(stderr, "Deque underflow\n"); 89 | exit(1); 90 | } 91 | 92 | int result = deque->items[deque->head]; 93 | 94 | deque->head = (deque->head+1)%MAX_SIZE; 95 | 96 | if (deque->head == deque->tail) { 97 | deque->head = -1; 98 | } 99 | 100 | return result; 101 | } 102 | -------------------------------------------------------------------------------- /Chapter10/E_10.1-5~7.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.1-5, 10.1-6, 10.1-7 6 | * 名称: Double-ended queue 7 | * 作者: Nastukashii 8 | * 语言: c 9 | * 内容摘要: 双端队列实现代码 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | 19 | #define Max 100 20 | 21 | //双端队列实现c 22 | typedef struct{ 23 | int head; 24 | int tail; 25 | int a[Max]; 26 | }Deque; 27 | 28 | void Init_Deque(Deque *d){ 29 | d->head = -1; 30 | d->tail = 0; 31 | } 32 | 33 | bool Empty(Deque *d){ 34 | return d->head == -1; 35 | } 36 | 37 | void Push_Back(Deque *d,int key){ 38 | if (d->head == d->tail){ 39 | fprintf(stderr, "Deque overflow"); 40 | exit(1); 41 | } 42 | if (d->head == -1) 43 | d->head = d->tail; 44 | d->a[d->tail] = key; 45 | d->tail = (d->tail + 1) % Max; 46 | } 47 | 48 | int Pop_Back(Deque *d){ 49 | if (d->head == -1){ 50 | fprintf(stderr, "Deque underflow"); 51 | exit(1); 52 | } 53 | d->tail = (d->tail - 1+Max) % Max; 54 | if (d->head == d->tail) 55 | d->head = -1; 56 | return d->a[d->tail]; 57 | } 58 | 59 | void Push_Front(Deque *d,int key){ 60 | if (d->head == d->tail){ 61 | fprintf(stderr, "Deque overflow"); 62 | exit(1); 63 | } 64 | if (d->head == -1) 65 | d->head = d->tail; 66 | d->head = (d->head - 1 + Max) % Max; 67 | d->head = key; 68 | } 69 | 70 | int Pop_Front(Deque *d){ 71 | if (d->head == -1){ 72 | fprintf(stderr, "Deque underflow"); 73 | exit(1); 74 | } 75 | int temp = d->a[d->head]; 76 | d->head = (d->head + 1) % Max; 77 | if (d->head == d->tail) 78 | d->head = -1; 79 | return temp; 80 | } 81 | 82 | 83 | //两个栈实现一个队列 84 | typedef struct{ 85 | Deque inqueue; 86 | Deque dequeue; 87 | }Like_Queue; 88 | 89 | void Push(Like_Queue *lq,int key){ 90 | Push_Back(&lq->inqueue, key); 91 | } 92 | 93 | int Pop(Like_Queue *lq){ 94 | if (Empty(&lq->dequeue)){ 95 | while (!Empty(&lq->inqueue)){ 96 | int temp = Pop_Back(&lq->inqueue); 97 | Push_Back(&lq->dequeue, temp); 98 | } 99 | } 100 | return Pop_Back(&lq->dequeue); 101 | } 102 | -------------------------------------------------------------------------------- /Chapter10/E_10.2-2.2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.2-2 6 | * 名称: Singly linked list-stack 7 | * 作者: windmissing 8 | * 语言: c 9 | * 内容摘要: 单链表实现栈 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | //结点 17 | struct node 18 | { 19 | node *pre;//为了方便实现出栈操作 20 | node *next; 21 | int key; 22 | node(int x):pre(NULL),next(NULL),key(x){} 23 | }; 24 | //链式栈 25 | struct list 26 | { 27 | node *Head;//栈的起始结点 28 | node *Top;//栈顶指针 29 | list(){Head = new node(0);Top = Head;} 30 | }; 31 | //打印栈中的元素 32 | void Print(list *L) 33 | { 34 | node *p = L->Head->next; 35 | while(p) 36 | { 37 | cout<key<<' '; 38 | p = p->next; 39 | } 40 | cout<Top->next = A; 49 | A->pre = L->Top; 50 | L->Top = A; 51 | } 52 | //出栈 53 | int Pop(list *L) 54 | { 55 | if(L->Head == L->Top) 56 | { 57 | cout<<"error:underflow"<Top->key; 62 | //修改指针 63 | node *A = L->Top; 64 | L->Top = A->pre; 65 | L->Top->next = NULL; 66 | delete A; 67 | return ret; 68 | } 69 | -------------------------------------------------------------------------------- /Chapter10/E_10.2-2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.2-2 6 | * 名称: Singly linked list-stack 7 | * 作者: alan-forever 8 | * 语言: c 9 | * 内容摘要: 单链表实现栈 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | 19 | typedef struct ListNode{ 20 | int value; 21 | struct ListNode * next; 22 | }ListNode; 23 | 24 | typedef struct { 25 | ListNode * top; 26 | }Stack; 27 | 28 | void list_insert(ListNode *l , int x); 29 | 30 | void print_list(ListNode *l); 31 | 32 | int stack_empty(Stack *S); 33 | 34 | void push(Stack *S, int x); 35 | 36 | int pop(Stack *S); 37 | 38 | int main(){ 39 | int i, num; 40 | Stack * S; 41 | S = (Stack *)malloc(sizeof(Stack)); 42 | S->top = (ListNode *)malloc(sizeof(ListNode)); 43 | 44 | for(i = 1; i <= 5; i++){ 45 | scanf("%d", &num); 46 | push(S, num); 47 | } 48 | 49 | //printf("%d\n", stack_empty(S)); 50 | //print_list(S->top); 51 | 52 | for(i = 1; i<= 5; i++) 53 | printf("%d ", pop(S)); 54 | printf("\n"); 55 | 56 | return 0; 57 | } 58 | 59 | void list_insert(ListNode *l, int x){ 60 | ListNode * p; 61 | p = (ListNode *)malloc(sizeof(ListNode)); 62 | p->value = x; 63 | if(l->next == NULL){ 64 | l->next = p; 65 | p->next = NULL; 66 | } 67 | else{ 68 | p->next = l->next; 69 | } 70 | l->next = p; 71 | } 72 | 73 | void print_list(ListNode *l){ 74 | ListNode * p = l->next; 75 | while(p != NULL){ 76 | printf("%d ", p->value); 77 | p = p->next; 78 | } 79 | printf("\n"); 80 | } 81 | 82 | 83 | int stack_empty(Stack *S){ 84 | if(S->top->next == NULL) 85 | return 1; 86 | else 87 | return 0; 88 | } 89 | 90 | void push(Stack *S, int x){ 91 | list_insert(S->top, x); 92 | } 93 | 94 | int pop(Stack *S){ 95 | if(stack_empty(S)){ 96 | printf("underflow\n"); 97 | return ; 98 | } 99 | else{ 100 | ListNode *p = S->top->next; 101 | int x = p->value; 102 | S->top->next = p->next; 103 | free(p); 104 | return x; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Chapter10/E_10.2-3.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.2-3 6 | * 名称: Singly linked list-queue 7 | * 作者: windmissing 8 | * 语言: c 9 | * 内容摘要: 单链表实现队列 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | //结点 17 | struct node 18 | { 19 | node *next; 20 | int key; 21 | node(int x):next(NULL),key(x){} 22 | }; 23 | //链式队列 24 | struct list 25 | { 26 | node *Head;//头指针 27 | node *Tail;//尾指针 28 | list(){Head = new node(0);Tail = Head;} 29 | }; 30 | //打印 31 | void Print(list *L) 32 | { 33 | node *p = L->Head->next; 34 | while(p) 35 | { 36 | cout<key<<' '; 37 | p = p->next; 38 | } 39 | cout<Tail->next = A; 48 | L->Tail = A; 49 | } 50 | //出队列 51 | int Dequeue(list *L) 52 | { 53 | if(L->Head == L->Tail) 54 | { 55 | cout<<"error:underflow"<Head->next; 60 | int ret = A->key; 61 | L->Head->next = A->next; 62 | if(A == L->Tail) 63 | L->Tail = L->Head; 64 | delete A; 65 | return ret; 66 | } 67 | -------------------------------------------------------------------------------- /Chapter10/E_10.2-5.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.2-5 6 | * 名称: Singly linked circular list-dictionary operations 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 单向循环链表实现字典操作 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | /* 在单向循环链表中使用哨兵,用来终结 search */ 17 | 18 | #include 19 | 20 | // 构建节点 21 | typedef struct node_t { 22 | int key; 23 | struct node_t *next; 24 | } node_t; 25 | 26 | // 构建链表 27 | typedef struct { 28 | struct node_t nil; 29 | } list_t; 30 | 31 | // 初始化链表 32 | void init_list(list_t *list) { 33 | list->nil.key = 0; 34 | list->nil.next = &(list->nil); 35 | } 36 | 37 | // 摧毁链表 38 | void destroy_list(list_t *list) { 39 | node_t *node = list->nil.next; 40 | node_t *next; 41 | 42 | while (node != &(list->nil)) { 43 | next = node->next; 44 | free(node); 45 | node = next; 46 | } 47 | } 48 | 49 | // insert 50 | void insert(list_t *list, int key) { 51 | node_t *new = (node_t *) malloc(sizeof(node_t)); 52 | new->key = key; 53 | new->next = list->nil.next; 54 | list->nil.next = new; 55 | } 56 | 57 | // 节点search操作 58 | node_t *search(list_t *list, int key) { 59 | node_t *node = list->nil.next; 60 | 61 | // The trick from exercise 10.2.4 62 | list->nil.key = key; 63 | while (node->key != key) { 64 | node = node->next; 65 | } 66 | 67 | if (node == &(list->nil)) { 68 | return NULL; 69 | } else { 70 | return node; 71 | } 72 | } 73 | 74 | // delete 75 | void delete(list_t *list, int key) { 76 | node_t *node = &(list->nil); 77 | 78 | while (node->next != &(list->nil)) { 79 | if (node->next->key == key) { 80 | node_t *to_be_deleted = node->next; 81 | node->next = node->next->next; 82 | free(to_be_deleted); 83 | } else { 84 | node = node->next; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Chapter10/E_10.2-7.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.2-7 6 | * 名称: Reverse List 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 非递归逆转单链表 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | 18 | typedef struct node_t { 19 | int key; 20 | struct node_t *next; 21 | } node_t; 22 | 23 | typedef struct { 24 | struct node_t nil; 25 | } list_t; 26 | 27 | void init_list(list_t *list) { 28 | list->nil.key = 0; 29 | list->nil.next = &(list->nil); 30 | } 31 | 32 | void destroy_list(list_t *list) { 33 | node_t *node = list->nil.next; 34 | node_t *next; 35 | 36 | while (node != &(list->nil)) { 37 | next = node->next; 38 | free(node); 39 | node = next; 40 | } 41 | } 42 | 43 | void insert(list_t *list, int key) { 44 | node_t *new = (node_t *) malloc(sizeof(node_t)); 45 | new->key = key; 46 | new->next = list->nil.next; 47 | list->nil.next = new; 48 | } 49 | 50 | void reverse(list_t *list) { 51 | node_t *prev = &(list->nil); 52 | node_t *node = list->nil.next; 53 | node_t *next; 54 | 55 | while (node != &(list->nil)) { 56 | next = node->next; 57 | node->next = prev; 58 | prev = node; 59 | node = next; 60 | } 61 | 62 | list->nil.next = prev; 63 | } 64 | -------------------------------------------------------------------------------- /Chapter10/E_10.3-2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.3-2 6 | * 名称: Single Array 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 单数组实现ALLOCATE-OBJECT和FREE-OBJECT 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | 19 | #define MAX_SIZE 3 20 | 21 | typedef int list_t; 22 | typedef int obj_t; 23 | 24 | int empty_list = -1; 25 | int cells[MAX_SIZE * 3]; 26 | int free_list; 27 | 28 | #define NEXT(i) cells[(i) + 1] 29 | #define PREV(i) cells[(i) + 2] 30 | #define KEY(i) cells[i] 31 | 32 | // 初始化存储 33 | void init_storage() { 34 | int i; 35 | for (i = 0; i < (MAX_SIZE - 1) * 3; i += 3) 36 | NEXT(i) = i + 3; 37 | 38 | NEXT(i) = -1; 39 | free_list = 0; 40 | } 41 | 42 | // ALLOCATE-OBEJCT 43 | list_t allocate_object() { 44 | if (free_list == -1) { // 如果自由表为空,表明单数组已满 45 | fprintf(stderr, "Storage depleted\n"); 46 | exit(1); 47 | } 48 | 49 | // 插入对象 50 | list_t new = free_list; 51 | free_list = NEXT(free_list); 52 | return new; 53 | } 54 | 55 | // 释放对象 56 | void free_object(list_t list) { 57 | NEXT(list) = free_list; 58 | free_list = list; 59 | } 60 | 61 | list_t cons(obj_t key, list_t list) { 62 | list_t new = allocate_object(); 63 | 64 | NEXT(new) = list; 65 | PREV(new) = empty_list; 66 | KEY(new) = key; 67 | 68 | if (list != empty_list) { 69 | PREV(list) = new; 70 | } 71 | 72 | return new; 73 | } 74 | 75 | // 删除链表 76 | void delete(list_t list) { 77 | if (PREV(list) != empty_list) { 78 | NEXT(PREV(list)) = NEXT(list); 79 | } 80 | 81 | if (NEXT(list) != empty_list) { 82 | PREV(NEXT(list)) = PREV(list); 83 | } 84 | 85 | free_object(list); 86 | } 87 | 88 | // 返回key 89 | obj_t get(list) { 90 | if (list == empty_list) return -1; 91 | return KEY(list); 92 | } 93 | 94 | // 返回list.next 95 | list_t next(list) { 96 | if (list == empty_list) return -1; 97 | return NEXT(list); 98 | } 99 | -------------------------------------------------------------------------------- /Chapter10/E_10.3-5.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.3-5 6 | * 名称: COMPACTIFY-LIST 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 使双向链表保持紧凑 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | 19 | #define MAX_SIZE 100 20 | 21 | typedef int list_t; 22 | typedef int obj_t; 23 | 24 | int empty_list = -1; 25 | 26 | int prev[MAX_SIZE]; 27 | int next[MAX_SIZE]; 28 | obj_t keys[MAX_SIZE]; 29 | 30 | int free_list; 31 | 32 | // 初始化存储 33 | void init_storage() { 34 | int i; 35 | for (i = 0; i < MAX_SIZE - 1; i++) 36 | next[i] = i + 1; 37 | 38 | next[i] = -1; 39 | free_list = 0; 40 | } 41 | 42 | // ALLOCATE-OBJECT 43 | list_t allocate_object() { 44 | if (free_list == -1) { 45 | fprintf(stderr, "Storage depleted\n"); 46 | exit(1); 47 | } 48 | 49 | list_t new = free_list; 50 | free_list = next[free_list]; 51 | return new; 52 | } 53 | 54 | // FREE-OBJECT 55 | void free_object(list_t list) { 56 | next[list] = free_list; 57 | free_list = list; 58 | } 59 | 60 | // 构建list 61 | list_t cons(obj_t key, list_t list) { 62 | list_t new = allocate_object(); 63 | 64 | next[new] = list; 65 | prev[new] = empty_list; 66 | keys[new] = key; 67 | 68 | if (list != empty_list) { 69 | prev[list] = new; 70 | } 71 | 72 | return new; 73 | } 74 | 75 | // 删除list 76 | void delete(list_t list) { 77 | if (prev[list] != empty_list) { 78 | next[prev[list]] = next[list]; 79 | } 80 | 81 | if (next[list] != empty_list) { 82 | prev[next[list]] = prev[list]; 83 | } 84 | 85 | free_object(list); 86 | } 87 | 88 | obj_t get(list) { 89 | if (list == empty_list) return -1; 90 | return keys[list]; 91 | } 92 | 93 | list_t next_obj(list) { 94 | if (list == empty_list) return -1; 95 | return next[list]; 96 | } 97 | 98 | // COMPACTIFY-LIST 99 | list_t compatify_list(list_t list) { 100 | list_t left, right, i; 101 | 102 | if (free_list == empty_list) { 103 | return list; 104 | } 105 | 106 | i = free_list; 107 | while (i != empty_list) { 108 | prev[i] = -2; 109 | i = next[i]; 110 | } 111 | 112 | left = 0; 113 | right = MAX_SIZE - 1; 114 | while (1) { 115 | while (prev[left] != -2) 116 | left++; 117 | 118 | while (prev[right] == -2) 119 | right--; 120 | 121 | if (left >= right) break; 122 | 123 | prev[left] = prev[right]; 124 | next[left] = next[right]; 125 | keys[left] = keys[right]; 126 | 127 | next[right] = left; 128 | 129 | right--; 130 | left++; 131 | } 132 | 133 | right++; 134 | 135 | for (int i = 0; i < right; i++) { 136 | if (prev[i] >= right) { 137 | prev[i] = next[prev[i]]; 138 | } 139 | 140 | if (next[i] >= right) { 141 | next[i] = next[next[i]]; 142 | } 143 | } 144 | 145 | if (list >= right) { 146 | list = next[list]; 147 | } 148 | 149 | for (i = right; i < MAX_SIZE - 1; i++) { 150 | next[i] = i+1; 151 | } 152 | next[i] = -1; 153 | 154 | free_list = right; 155 | 156 | return list; 157 | } 158 | -------------------------------------------------------------------------------- /Chapter10/E_10.4-2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.4-2 6 | * 名称: RECURSIVE-PRINT-TREE 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 递归输出二叉树结点关键字 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | struct tree_t { 17 | struct tree_t *left; 18 | struct tree_t *right; 19 | struct tree_t *parent; 20 | int key; 21 | }; 22 | typedef struct tree_t tree_t; 23 | void store(int); 24 | 25 | void print_tree(tree_t *tree) { 26 | store(tree->key); 27 | 28 | if (tree->left) 29 | print_tree(tree->left); 30 | 31 | if (tree->right) 32 | print_tree(tree->right); 33 | } 34 | 35 | #define MAX_SIZE 10 36 | int keys[MAX_SIZE]; 37 | int count = 0; 38 | 39 | void reset_storage() { 40 | count = 0; 41 | } 42 | 43 | void store(int key) { 44 | keys[count++] = key; 45 | } 46 | -------------------------------------------------------------------------------- /Chapter10/E_10.4-3.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 10.4-3 6 | * 名称: NONRECURSIVE-PRINT-TREE 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 非递归输出二叉树结点关键字 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #define MAX_SIZE 10 17 | 18 | struct tree_t { 19 | struct tree_t *left; 20 | struct tree_t *right; 21 | struct tree_t *parent; 22 | int key; 23 | }; 24 | typedef struct tree_t tree_t; 25 | void store(int); 26 | 27 | void print_tree(tree_t *tree) { 28 | tree_t *stack[MAX_SIZE]; 29 | int count = 0; 30 | 31 | stack[count++] = tree; 32 | 33 | while (count) { 34 | tree = stack[--count]; 35 | 36 | store(tree->key); 37 | 38 | if (tree->right) 39 | stack[count++] = tree->right; 40 | 41 | if (tree->left) 42 | stack[count++] = tree->left; 43 | } 44 | } 45 | 46 | int keys[MAX_SIZE]; 47 | int count = 0; 48 | 49 | void reset_storage() { 50 | count = 0; 51 | } 52 | 53 | void store(int key) { 54 | keys[count++] = key; 55 | } 56 | -------------------------------------------------------------------------------- /Chapter10/P_10-2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 10-2 6 | * 名称: Linked List & Mergeable Heap 7 | * 作者: skanev 8 | * 语言: c 9 | * 内容摘要: 利用链表实现可合并堆 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150708 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | 19 | ///////////////////////////////////////////////////////////////////////////// 20 | // List operations 21 | ///////////////////////////////////////////////////////////////////////////// 22 | 23 | // 链表结构 24 | struct list_t { 25 | int key; 26 | struct list_t *next; 27 | }; 28 | 29 | // 链表结构声明 30 | typedef struct list_t list_t; 31 | 32 | // 插入排序 33 | list_t *insert_sorted(list_t *list, int key) { 34 | list_t *new = malloc(sizeof(list_t)); 35 | new->key = key; 36 | 37 | if (!list || key < list->key) { 38 | new->next = list; 39 | return new; 40 | } 41 | 42 | list_t *l = list; 43 | while (l->next && l->next->key < key) { 44 | l = l->next; 45 | } 46 | 47 | new->next = l->next; 48 | l->next = new; 49 | 50 | return list; 51 | } 52 | 53 | // 删除关键字 54 | list_t *delete_key(list_t *list, int key) { 55 | list_t *match; 56 | while (list && list->key == key) { 57 | match = list; 58 | list = list->next; 59 | free(match); 60 | } 61 | 62 | if (!list) { 63 | return NULL; 64 | } 65 | 66 | list_t *node = list; 67 | while (node->next) { 68 | if (node->next->key == key) { 69 | match = node->next; 70 | node->next = match->next; 71 | free(match); 72 | } else { 73 | node = node->next; 74 | } 75 | } 76 | 77 | return list; 78 | } 79 | 80 | list_t *prepend(list_t *list, int key) { 81 | list_t *new = malloc(sizeof(list_t)); 82 | 83 | new->key = key; 84 | new->next = list; 85 | 86 | return new; 87 | } 88 | 89 | // 找到最小值 90 | int find_min(list_t *list) { 91 | int min = list->key; 92 | list = list->next; 93 | 94 | while (list) { 95 | if (list->key < min) { 96 | min = list->key; 97 | } 98 | list = list->next; 99 | } 100 | 101 | return min; 102 | } 103 | 104 | // 链表合并 105 | list_t *link_together(list_t *a, list_t *b) { 106 | list_t *result; 107 | 108 | if (!a) { 109 | result = b; 110 | } else { 111 | result = a; 112 | while (a->next) { 113 | a = a->next; 114 | } 115 | a->next = b; 116 | } 117 | 118 | return result; 119 | } 120 | 121 | // 归并排序 122 | list_t *merge_sorted(list_t *a, list_t *b) { 123 | list_t dummy; 124 | list_t *new = &dummy; 125 | 126 | while (a && b) { 127 | if (a->key < b->key) { 128 | new->next = a; 129 | a = a->next; 130 | new = new->next; 131 | } else { 132 | new->next = b; 133 | b = b->next; 134 | new = new->next; 135 | } 136 | } 137 | 138 | if (a) { 139 | new->next = a; 140 | } else { 141 | new->next = b; 142 | } 143 | 144 | return dummy.next; 145 | } 146 | 147 | ///////////////////////////////////////////////////////////////////////////// 148 | // 1. Mergreable heaps with sorted list 149 | ///////////////////////////////////////////////////////////////////////////// 150 | 151 | typedef struct { 152 | list_t *head; 153 | } heap1; 154 | 155 | heap1 *make_heap1() { 156 | heap1 *result = malloc(sizeof(heap1)); 157 | result->head = NULL; 158 | return result; 159 | } 160 | 161 | void insert1(heap1 *heap, int key) { 162 | heap->head = insert_sorted(heap->head, key); 163 | } 164 | 165 | int minimum1(heap1 *heap) { 166 | return heap->head->key; 167 | } 168 | 169 | int extract_min1(heap1 *heap) { 170 | list_t *head = heap->head; 171 | int result = head->key; 172 | heap->head = head->next; 173 | free(head); 174 | return result; 175 | } 176 | 177 | heap1 *union1(heap1 *ha, heap1 *hb) { 178 | heap1 *result = malloc(sizeof(heap1)); 179 | result->head = merge_sorted(ha->head, hb->head); 180 | 181 | free(ha); 182 | free(hb); 183 | 184 | return result; 185 | } 186 | 187 | ///////////////////////////////////////////////////////////////////////////// 188 | // 2. Mergreable heaps with unsorted lists 189 | ///////////////////////////////////////////////////////////////////////////// 190 | 191 | typedef struct { 192 | list_t *head; 193 | } heap2; 194 | 195 | heap2 *make_heap2() { 196 | heap2 *result = malloc(sizeof(heap2)); 197 | result->head = NULL; 198 | return result; 199 | } 200 | 201 | void insert2(heap2 *heap, int key) { 202 | heap->head = prepend(heap->head, key); 203 | } 204 | 205 | int minimum2(heap2 *heap) { 206 | return find_min(heap->head); 207 | } 208 | 209 | int extract_min2(heap2 *heap) { 210 | int min = minimum2(heap); 211 | heap->head = delete_key(heap->head, min); 212 | return min; 213 | } 214 | 215 | heap2 *union2(heap2 *ha, heap2 *hb) { 216 | heap2 *result = make_heap2(); 217 | result->head = link_together(ha->head, hb->head); 218 | 219 | free(ha); 220 | free(hb); 221 | 222 | return result; 223 | } 224 | -------------------------------------------------------------------------------- /Chapter12/P_12-1.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 12-1 6 | * 名称: Binary search trees with equal keys 7 | * 作者: windmissing 8 | * 语言: C++ 9 | * 内容摘要: 带有相同关键字的二叉搜索树 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | /* b) 布尔标志 */ 17 | // 二叉查找树结点的结构 18 | struct node 19 | { 20 | int key; // 关键字 21 | int data; // 卫星数据 22 | bool b; // 布尔标志 23 | node *left; // 左孩子 24 | node *right;// 右孩子 25 | node *p; // 父结点 26 | node(int x):key(x),data(x),b(0),left(NULL),right(NULL),p(NULL){} 27 | }; 28 | // 二叉查找树的结构 29 | struct tree 30 | { 31 | node *root; 32 | tree():root(NULL){} 33 | }; 34 | // 二叉查找树的插入 35 | void Tree_Insert(tree *T, node *z) 36 | { 37 | // 找到要插入的位置 38 | node *x = T->root, *y = NULL; 39 | // 若x为空,x是要插入的位置,x的父是z->p 40 | while(x != NULL) 41 | { 42 | y = x; 43 | // 等式成立时,由b决定插入到哪个子树 44 | if(z->key == x->key) 45 | { 46 | if(x->b == 0) 47 | x = x->left; 48 | else 49 | x = x->right; 50 | // 对b取反(每次访问时布尔标志在 TRUE & FALSE 交替切换) 51 | x->b = !x->b; 52 | } 53 | else if(z->key < x->key) 54 | x = x->left; 55 | else 56 | x = x->right; 57 | } 58 | // 修改指针,注意树为空的情况 59 | z->p = y; 60 | if(y == NULL) 61 | T->root = z; 62 | else if(z->key == y->key) 63 | { 64 | if(y->b == 0) 65 | y->left = z; 66 | else y->right = z; 67 | y->b = !y->b; 68 | } 69 | else if(z->key < y->key) 70 | y->left = z; 71 | else y->right = z; 72 | } 73 | 74 | 75 | /* c) 结点列表 */ 76 | // 二叉查找树结点的结构 77 | struct node 78 | { 79 | int key; // 关键字 80 | int data; // 卫星数据 81 | node *next; // 指向具体相同关键字的链表 82 | node *left; // 左孩子 83 | node *right;// 右孩子 84 | node *p; // 父结点 85 | node(int x):key(x),data(x),left(NULL),right(NULL),p(NULL),next(NULL){} 86 | }; 87 | // 二叉查找树的结构 88 | struct tree 89 | { 90 | node *root; 91 | tree():root(NULL){} 92 | }; 93 | // 二叉查找树的插入 94 | void Tree_Insert(tree *T, node *z) 95 | { 96 | // 找到要插入的位置 97 | node *x = T->root, *y = NULL; 98 | // 若x为空,x是要插入的位置,x的父是z->p 99 | while(x != NULL) 100 | { 101 | y = x; 102 | // 等式成立时,不继续插入到子树中,而是链入链表中 103 | if(z->key == x->key) 104 | { 105 | z->next = x->next; 106 | x->next = z; 107 | return; 108 | } 109 | else if(z->key < x->key) 110 | x = x->left; 111 | else 112 | x = x->right; 113 | } 114 | // 修改指针,注意树为空的情况 115 | z->p = y; 116 | if(y == NULL) 117 | T->root = z; 118 | // 等式成立时,不是插入到子树中,而是链入链表中 119 | else if(z->key == y->key) 120 | { 121 | z->next = y->next; 122 | y->next = z; 123 | } 124 | else if(z->key < y->key) 125 | y->left = z; 126 | else y->right = z; 127 | } 128 | 129 | 130 | /* d) 随机 */ 131 | // 二叉查找树结点的结构 132 | struct node 133 | { 134 | int key; //关键字 135 | int data; //卫星数据 136 | node *left; //左孩子 137 | node *right;//右孩子 138 | node *p; //父结点 139 | node(int x):key(x),data(x),left(NULL),right(NULL),p(NULL){} 140 | }; 141 | // 二叉查找树的结构 142 | struct tree 143 | { 144 | node *root; 145 | tree():root(NULL){} 146 | }; 147 | // 二叉查找树的插入 148 | void Tree_Insert(tree *T, node *z) 149 | { 150 | // 找到要插入的位置 151 | node *x = T->root, *y = NULL; 152 | // 若x为空,x是要插入的位置,x的父是z->p 153 | while(x != NULL) 154 | { 155 | y = x; 156 | // 若等式成立,随机地决定插入到哪个子树中 157 | if(z->key == x->key) 158 | { 159 | if(rand()%2 == 0) // 随机判断条件 160 | x = x->left; 161 | else 162 | x = x->right; 163 | } 164 | else if(z->key < x->key) 165 | x = x->left; 166 | else 167 | x = x->right; 168 | } 169 | // 修改指针,注意树为空的情况 170 | z->p = y; 171 | if(y == NULL) 172 | T->root = z; 173 | else if(z->key == y->key) 174 | { 175 | if(rand()%2 == 0) 176 | x = x->left; 177 | else 178 | x = x->right; 179 | } 180 | else if(z->key < y->key) 181 | y->left = z; 182 | else y->right = z; 183 | } 184 | -------------------------------------------------------------------------------- /Chapter12/P_12-2.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 12-2 6 | * 名称: Radix Tree 7 | * 作者: windmissing 8 | * 语言: C++ 9 | * 内容摘要: 基数树 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | using namespace std; 19 | 20 | //基数树结点结构 21 | struct node 22 | { 23 | node *left; // 左子节点 24 | node *right;// 右子节点 25 | node *p; // 父节点 26 | string str; // 位串 27 | node():left(NULL),right(NULL),p(NULL),str(""){} 28 | }; 29 | // 基数树结点 30 | struct Radix_Tree 31 | { 32 | node *root; 33 | Radix_Tree(){root = new node;} 34 | }; 35 | // 向基数树中插入一个位串 36 | void Insert(Radix_Tree *T, string s) 37 | { 38 | int i; 39 | node *t = T->root, *p; 40 | // 顺着串依次向下找 41 | for(i = 0; i left == NULL) 48 | { 49 | p = new node; 50 | p->p = t; 51 | t->left = p; 52 | } 53 | else 54 | p = t->left; 55 | } 56 | // 如果第i位是1,把串插入到右子树的某个位置 57 | else 58 | { 59 | //还没有右子树,就开辟一个 60 | if(t->right == NULL) 61 | { 62 | p = new node; 63 | p->p = t; 64 | t->right = p; 65 | } 66 | else 67 | p = t->right; 68 | } 69 | // 一直找到串的最后一个字符,把串的内容存入这个节点中 70 | if(i == s.length() - 1) 71 | p->str = s; 72 | else t = p; 73 | } 74 | } 75 | // 按字典序输出,其实是先序遍历的过程 76 | void Print(node *t) 77 | { 78 | if(t == NULL) 79 | return; 80 | // 如果某个节点有串的信息,就将它输出 81 | if(t->str != "") 82 | cout<str<left); 84 | Print(t->right); 85 | } 86 | int main() 87 | { 88 | string str, x; 89 | Radix_Tree *T = new Radix_Tree; 90 | while(1) 91 | { 92 | cin>>str; 93 | if(str == "I") 94 | { 95 | cin>>x; 96 | Insert(T, x); 97 | } 98 | else if(str == "P") 99 | { 100 | Print(T->root); 101 | cout<root, *f, *f2; // f为旧结点,f2为新结点 21 | //首先根结点是一定要改变的 22 | T->root = new node(p); 23 | //改变p结点的孩子,不需要改变的那个,还是指向原来的孩子 24 | while(p->key != k) 25 | { 26 | if(k < p->key) 27 | { 28 | //为要改的那个孩子建立一个和它一样的新结点 29 | f = p->left; 30 | //若孩子为空,把新结点加入进去 31 | if(!f) 32 | f2 = new node(k); 33 | else 34 | f2 = new node(f); 35 | //p指向新孩子 36 | p->left = f2; 37 | } 38 | else 39 | { 40 | f = p->right; 41 | if(!f) 42 | f2 = new node(k); 43 | else 44 | f2 = new node(f); 45 | p->right = f2; 46 | } 47 | //以新结点为父结点,做同样的更新操作 48 | p = f2; 49 | } 50 | //返回树 51 | return T; 52 | } 53 | -------------------------------------------------------------------------------- /Chapter13/P_13-4.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Problem 13-4 6 | * 名称: Treap树 7 | * 作者: Microgoogle 8 | * 语言: C++ 9 | * 内容摘要: Treap树 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | #include 19 | 20 | typedef struct node_t* Node; 21 | typedef struct treap_t* Treap; 22 | 23 | //构造结点 24 | struct node_t 25 | { 26 | Node left; //左节点 27 | Node right; //右节点 28 | int priority; //优先级 29 | int key; //存储的关键字 30 | }; 31 | 32 | //构造树 33 | struct treap_t 34 | { 35 | Node root; 36 | }; 37 | 38 | //左旋转 39 | void rotate_left(Node* node) 40 | { 41 | Node x = (*node)->right; 42 | (*node)->right = x->left; 43 | x->left = *node; 44 | *node = x; 45 | } 46 | 47 | //右旋转 48 | void rotate_right(Node* node) 49 | { 50 | Node x = (*node)->left; 51 | (*node)->left = x->right; 52 | x->right = *node; 53 | *node = x; 54 | } 55 | 56 | //插入操作 57 | void treap_insert(Node* root, int key, int priority) 58 | { 59 | //根为NULL,则直接创建此结点为根结点 60 | if (*root == NULL) 61 | { 62 | *root = (Node)malloc(sizeof(struct node_t)); 63 | (*root)->left = NULL; 64 | (*root)->right = NULL; 65 | (*root)->priority = priority; 66 | (*root)->key = key; 67 | } 68 | //向右插入结点 69 | else if (key < (*root)->key) 70 | { 71 | treap_insert(&((*root)->left), key, priority); 72 | if ((*root)->left->priority < (*root)->priority) 73 | rotate_right(root); 74 | } 75 | //向左插入结点 76 | else 77 | { 78 | treap_insert(&((*root)->right), key, priority); 79 | if ((*root)->right->priority < (*root)->priority) 80 | rotate_left(root); 81 | } 82 | } 83 | 84 | //删除操作 85 | void treap_delete(Node* root, int key) 86 | { 87 | if (*root != NULL) 88 | { 89 | if (key < (*root)->key) 90 | treap_delete(&((*root)->left), key); 91 | else if (key > (*root)->key) 92 | treap_delete(&((*root)->right), key); 93 | else 94 | { 95 | //左右孩子都为空不用单独写出来 96 | if ((*root)->left == NULL) 97 | *root = (*root)->right; 98 | else if ((*root)->right == NULL) 99 | *root = (*root)->left; 100 | else 101 | { 102 | //先旋转,然后再删除 103 | if ((*root)->left->priority < (*root)->right->priority) 104 | { 105 | rotate_right(root); 106 | treap_delete(&((*root)->right), key); 107 | } 108 | else 109 | { 110 | rotate_left(root); 111 | treap_delete(&((*root)->left), key); 112 | } 113 | } 114 | } 115 | } 116 | } 117 | 118 | //中序遍历 119 | void in_order_traverse(Node root) 120 | { 121 | if (root != NULL) 122 | { 123 | in_order_traverse(root->left); 124 | printf("%d\t", root->key); 125 | in_order_traverse(root->right); 126 | } 127 | } 128 | 129 | //计算树的高度 130 | int depth(Node node) 131 | { 132 | if(node == NULL) 133 | return -1; 134 | int l = depth(node->left); 135 | int r = depth(node->right); 136 | 137 | return (l < r)?(r+1):(l+1); 138 | } 139 | 140 | int main() 141 | { 142 | Treap treap = (Treap)malloc(sizeof(struct treap_t)); 143 | treap->root = NULL; 144 | int i = 0; 145 | 146 | srand(time(0)); 147 | 148 | for (i = 0; i < 100; i++) 149 | treap_insert(&(treap->root), i, rand()); 150 | in_order_traverse(treap->root); 151 | printf("\n高度:%d\n", depth(treap->root)); 152 | 153 | printf("---分割线---\n"); 154 | 155 | for (i = 23; i < 59; i++) 156 | treap_delete(&(treap->root), i); 157 | in_order_traverse(treap->root); 158 | printf("\n高度:%d\n", depth(treap->root)); 159 | return 0; 160 | } 161 | -------------------------------------------------------------------------------- /Chapter13/README.md: -------------------------------------------------------------------------------- 1 | #红黑树 RED-BLACK TREE 2 | ####RB-INSERT-FIXUP 3 | ![img](https://cloud.githubusercontent.com/assets/9131176/8700581/33833360-2b3f-11e5-9002-563737eb2557.png)
4 | ####RB-DELETE-FIXUP 5 | ![img](https://cloud.githubusercontent.com/assets/9131176/8700580/3380bcc0-2b3f-11e5-8d7f-aecf9bb791d0.png) 6 | -------------------------------------------------------------------------------- /Chapter14/C_14.3.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Chapter 14.3 6 | * 名称: 区间树 7 | * 作者: windmissing 8 | * 语言: C++ 9 | * 内容摘要: 区间树 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | using namespace std; 18 | 19 | /* Interval_Tree.h */ 20 | #define BLACK 0 21 | #define RED 1 22 | 23 | //取三者最大值 24 | int Max(int a, int b, int c) 25 | { 26 | if(a > b) 27 | return a > c ? a : c; 28 | else 29 | return b > c ? b : c; 30 | } 31 | //区间结构 32 | struct interval 33 | { 34 | int low; 35 | int high; 36 | interval(int l, int h):low(l), high(h){} 37 | }; 38 | //区间树结点结构 39 | struct node 40 | { 41 | node *left; //左孩子 42 | node *right; //右孩子 43 | node *p; //父结点 44 | int key; //关键字 45 | bool color; //颜色(红/黑) 46 | interval inte; //区间 47 | int max; //附加信息:包含本结点的二叉树中所有区间端点的最大值 48 | node(node *init, int l, int h):left(init),right(init),p(init),key(l),inte(l,h),max(h),color(BLACK){} 49 | }; 50 | //判断a和b是否重叠,若重叠,返回1 51 | bool Overlap(interval a, interval b) 52 | { 53 | //a在b的左边 54 | if(a.high < b.low) 55 | return 0; 56 | //a在b的右边 57 | if(a.low > b.high) 58 | return 0; 59 | return 1; 60 | } 61 | 62 | //区间树结构 63 | class Interval_Tree 64 | { 65 | public: 66 | node *root;//根结点 67 | node *nil;//哨兵 68 | /*构造函数*/ 69 | Interval_Tree(){nil = new node(NULL, -1, -1);root = nil;}; 70 | /*红黑树相关函数*/ 71 | void Left_Rotate(node *x);//左旋 72 | void Right_Rotate(node *x);//右旋 73 | void Insert_Fixup(node *z);//插入调整 74 | void Insert(node *z);//插入 75 | void Delete_Fixup(node *x);//删除调整 76 | node *Delete(node *z);//删除 77 | void Print();//输出 78 | void Print(node *x);//输出 79 | node *Search(node *x, int k);//在x的子树中查找关键字为k的结点 80 | node *Tree_Successor(node *x);//求后继 81 | node *Tree_Minimum(node *x);//求关键字最小的点 82 | /*区间树相关函数*/ 83 | node *Interval_Search(interval i); 84 | }; 85 | //左旋,令y = x->right, 左旋是以x和y之间的链为支轴进行旋转 86 | //涉及到的结点包括:x,y,y->left,令node={p,l,r},具体变化如下: 87 | //x={x->p,x->left,y}变为{y,x->left,y->left} 88 | //y={x,y->left,y->right}变为{x->p,x,y->right} 89 | //y->left={y,y->left->left,y->left->right}变为{x,y->left->left,y->left->right} 90 | void Interval_Tree::Left_Rotate(node *x) 91 | { 92 | //令y = x->right 93 | node *y = x->right; 94 | //按照上面的方式修改三个结点的指针,注意修改指针的顺序 95 | x->right = y->left; 96 | if(y->left != nil) 97 | y->left->p = x; 98 | y->p = x->p; 99 | if(x->p == nil)//特殊情况:x是根结点 100 | root = y; 101 | else if(x == x->p->left) 102 | x->p->left = y; 103 | else 104 | x->p->right = y; 105 | y->left = x; 106 | x->p = y; 107 | //对附加信息的维护 108 | y->max = x->max; 109 | x->max = Max(x->inte.high, x->left->max, x->right->max); 110 | } 111 | //右旋,令y = x->left, 左旋是以x和y之间的链为支轴进行旋转 112 | //旋转过程与上文类似 113 | void Interval_Tree::Right_Rotate(node *x) 114 | { 115 | node *y = x->left; 116 | x->left = y->right; 117 | if(y->right != nil) 118 | y->right->p = x; 119 | y->p = x->p; 120 | if(x->p == nil) 121 | root = y; 122 | else if(x == x->p->right) 123 | x->p->right = y; 124 | else 125 | x->p->left = y; 126 | y->right = x; 127 | x->p = y; 128 | //对附加信息的维护 129 | y->max = x->max; 130 | x->max = Max(x->inte.high, x->left->max, x->right->max); 131 | } 132 | //红黑树调整 133 | void Interval_Tree::Insert_Fixup(node *z) 134 | { 135 | node *y; 136 | //唯一需要调整的情况,就是违反性质2的时候,如果不违反性质2,调整结束 137 | while(z->p->color == RED) 138 | { 139 | //p[z]是左孩子时,有三种情况 140 | if(z->p == z->p->p->left) 141 | { 142 | //令y是z的叔结点 143 | y = z->p->p->right; 144 | //第一种情况,z的叔叔y是红色的 145 | if(y->color == RED) 146 | { 147 | //将p[z]和y都着为黑色以解决z和p[z]都是红色的问题 148 | z->p->color = BLACK; 149 | y->color = BLACK; 150 | //将p[p[z]]着为红色以保持性质5 151 | z->p->p->color = RED; 152 | //把p[p[z]]当作新增的结点z来重复while循环 153 | z = z->p->p; 154 | } 155 | else 156 | { 157 | //第二种情况:z的叔叔是黑色的,且z是右孩子 158 | if(z == z->p->right) 159 | { 160 | //对p[z]左旋,转为第三种情况 161 | z = z->p; 162 | Left_Rotate(z); 163 | } 164 | //第三种情况:z的叔叔是黑色的,且z是左孩子 165 | //交换p[z]和p[p[z]]的颜色,并右旋 166 | z->p->color = BLACK; 167 | z->p->p->color = RED; 168 | Right_Rotate(z->p->p); 169 | } 170 | } 171 | //p[z]是右孩子时,有三种情况,与上面类似 172 | else if(z->p == z->p->p->right) 173 | { 174 | y = z->p->p->left; 175 | if(y->color == RED) 176 | { 177 | z->p->color = BLACK; 178 | y->color = BLACK; 179 | z->p->p->color = RED; 180 | z = z->p->p; 181 | } 182 | else 183 | { 184 | if(z == z->p->left) 185 | { 186 | z = z->p; 187 | Right_Rotate(z); 188 | } 189 | z->p->color = BLACK; 190 | z->p->p->color = RED; 191 | Left_Rotate(z->p->p); 192 | } 193 | } 194 | } 195 | //根结点置为黑色 196 | root->color = BLACK; 197 | } 198 | //插入一个结点 199 | void Interval_Tree::Insert(node *z) 200 | { 201 | node *y = nil, *x = root; 202 | //找到应该插入的位置,与二叉查找树的插入相同 203 | while(x != nil) 204 | { 205 | x->max = max(x->max, z->max); 206 | y = x; 207 | if(z->key < x->key) 208 | x = x->left; 209 | else 210 | x = x->right; 211 | } 212 | z->p = y; 213 | if(y == nil) 214 | root = z; 215 | else if(z->key < y->key) 216 | y->left = z; 217 | else 218 | y->right = z; 219 | z->left = nil; 220 | z->right = nil; 221 | //将新插入的结点转为红色 222 | z->color = RED; 223 | //从新插入的结点开始,向上调整 224 | Insert_Fixup(z); 225 | } 226 | //对树进行调整,x指向一个红黑结点,调整的过程是将额外的黑色沿树上移 227 | void Interval_Tree::Delete_Fixup(node *x) 228 | { 229 | node *w; 230 | //如果这个额外的黑色在一个根结点或一个红结点上,结点会吸收额外的黑色,成为一个黑色的结点 231 | while(x != root && x->color == BLACK) 232 | { 233 | //若x是其父的左结点(右结点的情况相对应) 234 | if(x == x->p->left) 235 | { 236 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 237 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 238 | w = x->p->right; 239 | //第一种情况:w是红色的 240 | if(w->color == RED) 241 | { 242 | //改变w和p[x]的颜色 243 | w->color = BLACK; 244 | x->p->color = RED; 245 | //对p[x]进行一次左旋 246 | Left_Rotate(x->p); 247 | //令w为x的新兄弟 248 | w = x->p->right; 249 | //转为2.3.4三种情况之一 250 | } 251 | //第二情况:w为黑色,w的两个孩子也都是黑色 252 | if(w->left->color == BLACK && w->right->color == BLACK) 253 | { 254 | //去掉w和x的黑色 255 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 256 | w->color = RED; 257 | //在p[x]上补一层黑色 258 | x = x->p; 259 | //现在新x上有个额外的黑色,转入for循环继续处理 260 | } 261 | //第三种情况,w是黑色的,w->left是红色的,w->right是黑色的 262 | else 263 | { 264 | if(w->right->color == BLACK) 265 | { 266 | //改变w和left[x]的颜色 267 | w->left->color = BLACK; 268 | w->color = RED; 269 | //对w进行一次右旋 270 | Right_Rotate(w); 271 | //令w为x的新兄弟 272 | w = x->p->right; 273 | //此时转变为第四种情况 274 | } 275 | //第四种情况:w是黑色的,w->left是黑色的,w->right是红色的 276 | //修改w和p[x]的颜色 277 | w->color =x->p->color; 278 | x->p->color = BLACK; 279 | w->right->color = BLACK; 280 | //对p[x]进行一次左旋 281 | Left_Rotate(x->p); 282 | //此时调整已经结束,将x置为根结点是为了结束循环 283 | x = root; 284 | } 285 | } 286 | //若x是其父的左结点(右结点的情况相对应) 287 | else if(x == x->p->right) 288 | { 289 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 290 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 291 | w = x->p->left; 292 | //第一种情况:w是红色的 293 | if(w->color == RED) 294 | { 295 | //改变w和p[x]的颜色 296 | w->color = BLACK; 297 | x->p->color = RED; 298 | //对p[x]进行一次左旋 299 | Right_Rotate(x->p); 300 | //令w为x的新兄弟 301 | w = x->p->left; 302 | //转为2.3.4三种情况之一 303 | } 304 | //第二情况:w为黑色,w的两个孩子也都是黑色 305 | if(w->right->color == BLACK && w->left->color == BLACK) 306 | { 307 | //去掉w和x的黑色 308 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 309 | w->color = RED; 310 | //在p[x]上补一层黑色 311 | x = x->p; 312 | //现在新x上有个额外的黑色,转入for循环继续处理 313 | } 314 | //第三种情况,w是黑色的,w->right是红色的,w->left是黑色的 315 | else 316 | { 317 | if(w->left->color == BLACK) 318 | { 319 | //改变w和right[x]的颜色 320 | w->right->color = BLACK; 321 | w->color = RED; 322 | //对w进行一次右旋 323 | Left_Rotate(w); 324 | //令w为x的新兄弟 325 | w = x->p->left; 326 | //此时转变为第四种情况 327 | } 328 | //第四种情况:w是黑色的,w->right是黑色的,w->left是红色的 329 | //修改w和p[x]的颜色 330 | w->color =x->p->color; 331 | x->p->color = BLACK; 332 | w->left->color = BLACK; 333 | //对p[x]进行一次左旋 334 | Right_Rotate(x->p); 335 | //此时调整已经结束,将x置为根结点是为了结束循环 336 | x = root; 337 | } 338 | } 339 | } 340 | //吸收了额外的黑色 341 | x->color = BLACK; 342 | } 343 | //找最小值 344 | node *Interval_Tree::Tree_Minimum(node *x) 345 | { 346 | //只要有比当前结点小的结点 347 | while(x->left != nil) 348 | x = x->left; 349 | return x; 350 | } 351 | //查找中序遍历下x结点的后继,后继是大于key[x]的最小的结点 352 | node *Interval_Tree::Tree_Successor(node *x) 353 | { 354 | //如果有右孩子 355 | if(x->right != nil) 356 | //右子树中的最小值 357 | return Tree_Minimum(x->right); 358 | //如果x的右子树为空且x有后继y,那么y是x的最低祖先结点,且y的左儿子也是 359 | node *y = x->p; 360 | while(y != NULL && x == y->right) 361 | { 362 | x = y; 363 | y = y->p; 364 | } 365 | return y; 366 | } 367 | //递归地查询二叉查找树 368 | node *Interval_Tree::Search(node *x, int k) 369 | { 370 | //找到叶子结点了还没找到,或当前结点是所查找的结点 371 | if(x->key == -1 || k == x->key) 372 | return x; 373 | //所查找的结点位于当前结点的左子树 374 | if(k < x->key) 375 | return Search(x->left, k); 376 | //所查找的结点位于当前结点的左子树 377 | else 378 | return Search(x->right, k); 379 | } 380 | //红黑树的删除 381 | node *Interval_Tree::Delete(node *z) 382 | { 383 | //找到结点的位置并删除,这一部分与二叉查找树的删除相同 384 | node *x, *y, *p; 385 | if(z->left == nil || z->right == nil) 386 | { 387 | y = z; 388 | p = y->p; 389 | p->max = p->inte.high; 390 | p = p->p; 391 | while(p->max == y->max) 392 | { 393 | p->max = Max(p->max, p->left->max, p->right->max); 394 | p = p->p; 395 | } 396 | } 397 | else y = Tree_Successor(z); 398 | //对附加信息的维护 399 | p = y->p; 400 | p->max = p->inte.high; 401 | p = p->p; 402 | while(p->max == y->max) 403 | { 404 | p->max = Max(p->max, p->left->max, p->right->max); 405 | p = p->p; 406 | } 407 | //删除y结点 408 | if(y->left != nil) 409 | x = y->left; 410 | else x = y->right; 411 | x->p = y->p; 412 | if(y->p == nil) 413 | root = x; 414 | else if(y == y->p->left) 415 | y->p->left = x; 416 | else 417 | y->p->right = x; 418 | //替换 419 | if(y != z) 420 | { 421 | z->inte = y->inte; 422 | z->key = y->key; 423 | z->max = y->max; 424 | p = z->p; 425 | while(p->max < z->max) 426 | { 427 | p->max = z->max; 428 | p = p->p; 429 | } 430 | } 431 | //如果被删除的结点是黑色的,则需要调整 432 | if(y->color == BLACK) 433 | Delete_Fixup(x); 434 | return y; 435 | } 436 | void Interval_Tree::Print(node *x) 437 | { 438 | if(x->key == -1) 439 | return; 440 | Print(x->left); 441 | cout<inte.low<<' '<inte.high<right); 443 | } 444 | 445 | void Interval_Tree::Print() 446 | { 447 | Print(root); 448 | cout<inte)) 458 | { 459 | //在左子树中 460 | if(x->left != nil && x->left->max >= i.low) 461 | x = x->left; 462 | //在右子树中 463 | else 464 | x = x->right; 465 | } 466 | return x; 467 | } 468 | 469 | /* main.cpp */ 470 | int main() 471 | { 472 | char ch; 473 | int x, y; 474 | //生成一棵顺序统计树 475 | Interval_Tree *T = new Interval_Tree; 476 | while(1) 477 | { 478 | cin>>ch; 479 | switch(ch) 480 | { 481 | //插入一个元素 482 | case 'I': 483 | { 484 | //cin>>x>>y; 485 | x = rand() % 100; 486 | y = rand() % 100; 487 | if(x > y)swap(x, y); 488 | node *z = new node(T->nil, x, y); 489 | T->Insert(z); 490 | break; 491 | } 492 | //删除一个元素 493 | case 'D': 494 | { 495 | cin>>x; 496 | node *z = T->Search(T->root, x); 497 | if(z == NULL) 498 | cout<<"not exist"<Delete(z); 501 | break; 502 | } 503 | //求第一个与[x,y]相交的区间 504 | case 'S': 505 | { 506 | cin>>x>>y; 507 | node *z = T->Interval_Search(interval(x, y)); 508 | if(z == NULL) 509 | cout<<"not exist"<inte.low<<' '<inte.high<Print(); 516 | break; 517 | default: 518 | break; 519 | } 520 | } 521 | return 0; 522 | } 523 | -------------------------------------------------------------------------------- /Chapter14/E_14.3-1~5.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 14.3-1~5 6 | * 名称: 习题 7 | * 作者: 8 | * 语言: 9 | * 内容摘要: 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | /* EXERCISE 14.3-1 17 | * LEFT-ROTATE(T, x) 18 | * 伪代码 */ 19 | y = x.right //令y为x的右孩子 20 | x.right = y.left //x的右孩子(指针)指向y的左孩子(有可能为T.nil) 21 | if y.left != T.nil //如果y的左孩子不为T.nil 22 | then y.left.p = x //y的左孩子父结点(指针)指向x 23 | y.p = x.p //y的父结点(指针)指向x的父结点(指针) 24 | if x.p = T.nil //如果x是根结点 25 | then T.root = y //T.root指向y 26 | else if x = x.p.left //如果x是左孩子 27 | then x.p.left = y //y成为左孩子 28 | else x.p.right = y //y成为右孩子 29 | y.left = x //y的左孩子(指针)指向x 30 | x.p = y //x的父结点(指针)指向y 31 | y.max = x.max //y.max取整棵x结点树的最大值(x.max>=y.max) 32 | x.max = max(x.int.high, x.left.max, x.right.max) //x.max重新取值 33 | 34 | 35 | /* EXERCISE 14.3-3 36 | * 给定区间i,返回一个与i重叠且具有最小低端点的区间; 37 | * 或者当这样的区间不存在时返回T.nil */ 38 | node* Intervel_Tree::Search_Min(node *root, interval i) 39 | { 40 | node *x = root, *y; //初始化,x指向根结点 41 | /* 先从左子树开始搜索 */ 42 | if (x->left && x->left->max >= i.low) 43 | { 44 | y = Search_Min(x->left, i); 45 | if (y != nil) 46 | return y; 47 | } 48 | /* 如果x与i重叠,就不搜索左子树 */ 49 | if (Overlap(x->inte, i)) 50 | return x; 51 | /* 在右子树上找 */ 52 | if (x->right) 53 | return Search_Min(x->right, i); 54 | return nil; 55 | } 56 | 57 | /* EXERCISE 14.3-4 58 | * 给定区间树T和区间i,在O(min(n,klgn))时间内列出T中所有与i重叠的区间, 59 | * 其中k为输出的区间数 */ 60 | void Interval_Tree::Search_All(node *root, interval i) 61 | { 62 | node *x = root, *y; 63 | //如果当前结点与i重叠 64 | if (Overlap(x->inte, i)) 65 | cout<inte.low<<' '<inte.high<left && x->left->max >= i.low) 68 | Search_All(x->left, i); 69 | //从右子树上找 70 | if (x->right && x->key <= i.high) 71 | Search_All(x->right, i); 72 | } 73 | 74 | /* EXERCISE 14.3-5 75 | * 给定区间树T和区间i,返回一个指向T中结点x的指针, 76 | * 使得 x.int.low=i.low 且 x.int.high=i.high; 77 | * 或,如果T不包含这样的区间时返回T.nil 78 | * INTERVAL-SEARCH-EXACTLy(T, i) */ 79 | node* Interval_Tree::Search_Exactly(interval i) 80 | { 81 | //从根节点开始 82 | node *x = root; 83 | //不是叶子且不重叠 84 | while (x != nil) 85 | { 86 | if (x->inte.low == i.low && x->inte.high == i.high) 87 | return x; 88 | //在左子树中 89 | if (x->left != nil && x->key >= i.low) 90 | x = x->left; 91 | //在右子树中 92 | else 93 | x = x->right; 94 | } 95 | return nil; 96 | } 97 | 98 | 99 | -------------------------------------------------------------------------------- /Chapter14/E_14.3-6.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Exercise 14.3-6 6 | * 名称: MIN-GAP 7 | * 作者: windmissing 8 | * 语言: C++ 9 | * 内容摘要: 区间树的MIN-GAP操作 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150709 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | using namespace std; 18 | 19 | #define BLACK 0 20 | #define RED 1 21 | 22 | //MIN-GAP树结点结构 23 | struct node 24 | { 25 | node *left; //左孩子 26 | node *right;//右孩子 27 | node *p; //父 28 | int key; //关键字 29 | bool color; //颜色,红或黑 30 | int min_gap;//记录以x为根结点的树的min-gap。当x为叶子结点时,min-gap[x]=0x7fffffff 31 | int min_val;//记录以x为根结点的树中最小的关键字 32 | int max_val;//记录以x为根结点的树中最大的关键字 33 | node(node *init, int k) 34 | :left(init),right(init),p(init),key(k),color(BLACK),min_gap(0x7fffffff),min_val(k),max_val(k){} 35 | }; 36 | 37 | //区间树结构 38 | struct Min_Gap_Tree 39 | { 40 | node *root; //根结点 41 | node *nil; //哨兵 42 | Min_Gap_Tree(){nil = new node(NULL, -1);root = nil;}; 43 | }; 44 | 45 | //取三者最小值 46 | int Min(int a, int b, int c, int d) 47 | { 48 | a = a < b ? a : b; 49 | c = c < d ? c : d; 50 | return a < c ? a : c; 51 | } 52 | 53 | //对信息的维护 54 | void Maintaining(Min_Gap_Tree *T, node *x) 55 | { 56 | while(x != T->nil) 57 | { 58 | //对min_val信息的维护 59 | x->min_val = (x->left != T->nil) ? x->left->min_val : x->key; 60 | //对max_val信息的维护 61 | x->max_val = (x->right != T->nil) ? x->right->max_val : x->key; 62 | //对min_gap信息的维护 63 | int a = (x->left != T->nil) ? x->left->min_gap : 0x7fffffff; 64 | int b = (x->right != T->nil) ? x->right->min_gap : 0x7fffffff; 65 | int c = (x->left != T->nil) ? (x->key - x->left->max_val) : 0x7fffffff; 66 | int d = (x->right != T->nil) ? (x->right->min_val - x->key) : 0x7fffffff; 67 | x->min_gap = Min(a, b, c, d); 68 | //向上更新 69 | x = x->p; 70 | } 71 | } 72 | 73 | //左旋,令y = x->right, 左旋是以x和y之间的链为支轴进行旋转 74 | //涉及到的结点包括:x,y,y->left,令node={p,l,r},具体变化如下: 75 | //x={x->p,x->left,y}变为{y,x->left,y->left} 76 | //y={x,y->left,y->right}变为{x->p,x,y->right} 77 | //y->left={y,y->left->left,y->left->right}变为{x,y->left->left,y->left->right} 78 | void Left_Rotate(Min_Gap_Tree *T, node *x) 79 | { 80 | //令y = x->right 81 | node *y = x->right; 82 | //按照上面的方式修改三个结点的指针,注意修改指针的顺序 83 | x->right = y->left; 84 | if(y->left != T->nil) 85 | y->left->p = x; 86 | y->p = x->p; 87 | if(x->p == T->nil)//特殊情况:x是根结点 88 | T->root = y; 89 | else if(x == x->p->left) 90 | x->p->left = y; 91 | else 92 | x->p->right = y; 93 | y->left = x; 94 | x->p = y; 95 | Maintaining(T, x); 96 | } 97 | 98 | //右旋,令y = x->left, 左旋是以x和y之间的链为支轴进行旋转 99 | //旋转过程与上文类似 100 | void Right_Rotate(Min_Gap_Tree *T, node *x) 101 | { 102 | node *y = x->left; 103 | x->left = y->right; 104 | if(y->right != T->nil) 105 | y->right->p = x; 106 | y->p = x->p; 107 | if(x->p == T->nil) 108 | T->root = y; 109 | else if(x == x->p->right) 110 | x->p->right = y; 111 | else 112 | x->p->left = y; 113 | y->right = x; 114 | x->p = y; 115 | Maintaining(T, x); 116 | } 117 | 118 | //红黑树调整 119 | void MG_Insert_Fixup(Min_Gap_Tree *T, node *z) 120 | { 121 | node *y; 122 | //唯一需要调整的情况,就是违反性质2的时候,如果不违反性质2,调整结束 123 | while(z->p->color == RED) 124 | { 125 | //p[z]是左孩子时,有三种情况 126 | if(z->p == z->p->p->left) 127 | { 128 | //令y是z的叔结点 129 | y = z->p->p->right; 130 | //第一种情况,z的叔叔y是红色的 131 | if(y->color == RED) 132 | { 133 | //将p[z]和y都着为黑色以解决z和p[z]都是红色的问题 134 | z->p->color = BLACK; 135 | y->color = BLACK; 136 | //将p[p[z]]着为红色以保持性质5 137 | z->p->p->color = RED; 138 | //把p[p[z]]当作新增的结点z来重复while循环 139 | z = z->p->p; 140 | } 141 | else 142 | { 143 | //第二种情况:z的叔叔是黑色的,且z是右孩子 144 | if(z == z->p->right) 145 | { 146 | //对p[z]左旋,转为第三种情况 147 | z = z->p; 148 | Left_Rotate(T, z); 149 | } 150 | //第三种情况:z的叔叔是黑色的,且z是左孩子 151 | //交换p[z]和p[p[z]]的颜色,并右旋 152 | z->p->color = BLACK; 153 | z->p->p->color = RED; 154 | Right_Rotate(T, z->p->p); 155 | } 156 | } 157 | //p[z]是右孩子时,有三种情况,与上面类似 158 | else if(z->p == z->p->p->right) 159 | { 160 | y = z->p->p->left; 161 | if(y->color == RED) 162 | { 163 | z->p->color = BLACK; 164 | y->color = BLACK; 165 | z->p->p->color = RED; 166 | z = z->p->p; 167 | } 168 | else 169 | { 170 | if(z == z->p->left) 171 | { 172 | z = z->p; 173 | Right_Rotate(T, z); 174 | } 175 | z->p->color = BLACK; 176 | z->p->p->color = RED; 177 | Left_Rotate(T, z->p->p); 178 | } 179 | } 180 | } 181 | //根结点置为黑色 182 | T->root->color = BLACK; 183 | } 184 | 185 | //插入一个结点 186 | void Min_Gap_Insert(Min_Gap_Tree *T, node *z) 187 | { 188 | node *y = T->nil, *x = T->root; 189 | //找到应该插入的位置,与二叉查找树的插入相同 190 | while(x != T->nil) 191 | { 192 | y = x; 193 | if(z->key < x->key) 194 | x = x->left; 195 | else 196 | x = x->right; 197 | } 198 | z->p = y; 199 | if(y == T->nil) 200 | T->root = z; 201 | else if(z->key < y->key) 202 | y->left = z; 203 | else 204 | y->right = z; 205 | z->left = T->nil; 206 | z->right = T->nil; 207 | //将新插入的结点转为红色 208 | z->color = RED; 209 | //从新插入的结点开始,向上调整 210 | MG_Insert_Fixup(T, z); 211 | //对信息的维护 212 | Maintaining(T, z); 213 | } 214 | 215 | //对树进行调整,x指向一个红黑结点,调整的过程是将额外的黑色沿树上移 216 | void MG_Delete_Fixup(Min_Gap_Tree *T, node *x) 217 | { 218 | node *w; 219 | //如果这个额外的黑色在一个根结点或一个红结点上,结点会吸收额外的黑色,成为一个黑色的结点 220 | while(x != T->root && x->color == BLACK) 221 | { 222 | //若x是其父的左结点(右结点的情况相对应) 223 | if(x == x->p->left) 224 | { 225 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 226 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 227 | w = x->p->right; 228 | //第一种情况:w是红色的 229 | if(w->color == RED) 230 | { 231 | //改变w和p[x]的颜色 232 | w->color = BLACK; 233 | x->p->color = RED; 234 | //对p[x]进行一次左旋 235 | Left_Rotate(T, x->p); 236 | //令w为x的新兄弟 237 | w = x->p->right; 238 | //转为2.3.4三种情况之一 239 | } 240 | //第二情况:w为黑色,w的两个孩子也都是黑色 241 | if(w->left->color == BLACK && w->right->color == BLACK) 242 | { 243 | //去掉w和x的黑色 244 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 245 | w->color = RED; 246 | //在p[x]上补一层黑色 247 | x = x->p; 248 | //现在新x上有个额外的黑色,转入for循环继续处理 249 | } 250 | //第三种情况,w是黑色的,w->left是红色的,w->right是黑色的 251 | else 252 | { 253 | if(w->right->color == BLACK) 254 | { 255 | //改变w和left[x]的颜色 256 | w->left->color = BLACK; 257 | w->color = RED; 258 | //对w进行一次右旋 259 | Right_Rotate(T, w); 260 | //令w为x的新兄弟 261 | w = x->p->right; 262 | //此时转变为第四种情况 263 | } 264 | //第四种情况:w是黑色的,w->left是黑色的,w->right是红色的 265 | //修改w和p[x]的颜色 266 | w->color =x->p->color; 267 | x->p->color = BLACK; 268 | w->right->color = BLACK; 269 | //对p[x]进行一次左旋 270 | Left_Rotate(T, x->p); 271 | //此时调整已经结束,将x置为根结点是为了结束循环 272 | x = T->root; 273 | } 274 | } 275 | //若x是其父的左结点(右结点的情况相对应) 276 | else if(x == x->p->right) 277 | { 278 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 279 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 280 | w = x->p->left; 281 | //第一种情况:w是红色的 282 | if(w->color == RED) 283 | { 284 | //改变w和p[x]的颜色 285 | w->color = BLACK; 286 | x->p->color = RED; 287 | //对p[x]进行一次左旋 288 | Right_Rotate(T, x->p); 289 | //令w为x的新兄弟 290 | w = x->p->left; 291 | //转为2.3.4三种情况之一 292 | } 293 | //第二情况:w为黑色,w的两个孩子也都是黑色 294 | if(w->right->color == BLACK && w->left->color == BLACK) 295 | { 296 | //去掉w和x的黑色 297 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 298 | w->color = RED; 299 | //在p[x]上补一层黑色 300 | x = x->p; 301 | //现在新x上有个额外的黑色,转入for循环继续处理 302 | } 303 | //第三种情况,w是黑色的,w->right是红色的,w->left是黑色的 304 | else 305 | { 306 | if(w->left->color == BLACK) 307 | { 308 | //改变w和right[x]的颜色 309 | w->right->color = BLACK; 310 | w->color = RED; 311 | //对w进行一次右旋 312 | Left_Rotate(T, w); 313 | //令w为x的新兄弟 314 | w = x->p->left; 315 | //此时转变为第四种情况 316 | } 317 | //第四种情况:w是黑色的,w->right是黑色的,w->left是红色的 318 | //修改w和p[x]的颜色 319 | w->color =x->p->color; 320 | x->p->color = BLACK; 321 | w->left->color = BLACK; 322 | //对p[x]进行一次左旋 323 | Right_Rotate(T, x->p); 324 | //此时调整已经结束,将x置为根结点是为了结束循环 325 | x = T->root; 326 | } 327 | } 328 | } 329 | //吸收了额外的黑色 330 | x->color = BLACK; 331 | } 332 | 333 | //找最小值 334 | node *Tree_Minimum(Min_Gap_Tree *T, node *x) 335 | { 336 | //只要有比当前结点小的结点 337 | while(x->left != T->nil) 338 | x = x->left; 339 | return x; 340 | } 341 | 342 | //查找中序遍历下x结点的后继,后继是大于key[x]的最小的结点 343 | node *Tree_Successor(Min_Gap_Tree *T, node *x) 344 | { 345 | //如果有右孩子 346 | if(x->right != T->nil) 347 | //右子树中的最小值 348 | return Tree_Minimum(T, x->right); 349 | //如果x的右子树为空且x有后继y,那么y是x的最低祖先结点,且y的左儿子也是 350 | node *y = x->p; 351 | while(y != NULL && x == y->right) 352 | { 353 | x = y; 354 | y = y->p; 355 | } 356 | return y; 357 | } 358 | 359 | //红黑树的删除 360 | node *Min_Gap_Delete(Min_Gap_Tree *T, node *z) 361 | { 362 | //找到结点的位置并删除,这一部分与二叉查找树的删除相同 363 | node *x, *y; 364 | if(z->left == T->nil || z->right == T->nil) 365 | y = z; 366 | else y = Tree_Successor(T, z); 367 | if(y->left != T->nil) 368 | x = y->left; 369 | else x = y->right; 370 | x->p = y->p; 371 | if(y->p == T->nil) 372 | T->root = x; 373 | else if(y == y->p->left) 374 | y->p->left = x; 375 | else 376 | y->p->right = x; 377 | //对信息的维护 378 | Maintaining(T, x); 379 | if(y != z) 380 | { 381 | z->key = y->key; 382 | //对信息的维护 383 | Maintaining(T, z); 384 | } 385 | //如果被删除的结点是黑色的,则需要调整 386 | if(y->color == BLACK) 387 | MG_Delete_Fixup(T, x); 388 | return y; 389 | } 390 | 391 | //递归地查询二叉查找树 392 | node *Min_Gap_Search(node *x, int k) 393 | { 394 | //找到叶子结点了还没找到,或当前结点是所查找的结点 395 | if(x->key == -1 || k == x->key) 396 | return x; 397 | //所查找的结点位于当前结点的左子树 398 | if(k < x->key) 399 | return Min_Gap_Search(x->left, k); 400 | //所查找的结点位于当前结点的左子树 401 | else 402 | return Min_Gap_Search(x->right, k); 403 | } 404 | 405 | void Print(node *x) 406 | { 407 | if(x->key == -1) 408 | return; 409 | Print(x->left); 410 | cout<key<<' '<color<right); 412 | } 413 | 414 | int Min_Gap(node *r) 415 | { 416 | return r->min_gap; 417 | } 418 | 419 | void Print(Min_Gap_Tree *T) 420 | { 421 | Print(T->root); 422 | cout<>ch; 437 | switch (ch) 438 | { 439 | //插入一个关键字 440 | case 'I': 441 | { 442 | //生成一个待插入的随机数 443 | x = rand() % 100; 444 | //显示刚刚插入的数 445 | cout<<"插入的数字是"<nil, x); 447 | Min_Gap_Insert(T, z); 448 | //输出min-gap 449 | cout<<"min-gap = "<root)<>x; 457 | //先从集合中找到值为x的数 458 | node *ret = Min_Gap_Search(T->root, x); 459 | //集合中有这个数,则删除,没有则不处理 460 | if(ret == T->nil) 461 | cout<<"not exist"<A[i],就跳出循环 62 | while(A[PARENT(i)] > 0 && A[PARENT(i)] < A[i]) 63 | { 64 | swap(A[PARENT(i)], A[i]); 65 | i = PARENT(i); 66 | } 67 | } 68 | //把key插入到集合A中 69 | void Max_Heap_Insert(int *A, int key) 70 | { 71 | if(heap_size == 99) 72 | { 73 | cout<<"heap is full"< heap_size) 107 | { 108 | cout<<"there's no node i"< A[i]) 116 | Heap_Increase_Key(A, i, key); 117 | else//否则,向下调整 118 | { 119 | A[i] = key; 120 | Max_Heapify(A, i); 121 | } 122 | } 123 | 124 | /***************************** main.cpp ****************************/ 125 | // main.cpp 126 | #include 127 | #include "Heap.h" 128 | using namespace std; 129 | 130 | #define N 11 131 | //用于存储每个活动的信息 132 | struct node 133 | { 134 | int id;//记录它是第几个活动 135 | int start;//开始时间 136 | int finish;//结束时间 137 | }A[N+1]; 138 | //用于排序 139 | bool cmp(node a, node b) 140 | { 141 | return a.finish < b.finish; 142 | } 143 | //最大堆 144 | int H[N+1]; 145 | //O(lgn)贪心算法 146 | void Greedy() 147 | { 148 | //对所有活动的结束时间从小到大排序 149 | sort(A+1, A+N+1, cmp); 150 | int i, ret = 0; 151 | //从最后一个活动开始,向第一个活动,依次针对每个活动做以下处理 152 | for(i = N; i >= 1; i--) 153 | { 154 | //1)获取堆顶元素的信息(4)更新堆(5)选择下一个活动,直到所有活动都处理过 155 | int temp = Heap_Maximum(H); 156 | //(2)如果堆顶的活动开始时间早于当前活动的结束时间,则: 157 | if(temp < A[i].finish) 158 | { 159 | //申请一个新的教室 160 | ret++; 161 | //把活动的开始时间填入其中,再把教室作为一个结点存入堆中 162 | Max_Heap_Insert(H, A[i].start); 163 | } 164 | //(3)如果堆顶的活动开始时间晚于当前活动的结束时间,则: 165 | else 166 | { 167 | //就把当前活动填入堆顶元素中 168 | Heap_Extract_Max(H); 169 | Max_Heap_Insert(H, A[i].start); 170 | } 171 | //选择下一个活动,直到所有活动都处理过 172 | } 173 | cout<>A[i].start>>A[i].finish; 196 | } 197 | //贪心算法 198 | Greedy(); 199 | return 0; 200 | } 201 | -------------------------------------------------------------------------------- /Chapter17/C_17.1.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Chapter 17.1 6 | * 名称: 二进制计数器递增 7 | * 作者: wuzhiyi 8 | * 语言: c 9 | * 内容摘要: 二进制计数器递增16次 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150713 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #define N 8 18 | 19 | //递增函数 20 | void INCREMENT(int A[]) { 21 | int i=0, j; 22 | while (i-1; j--) { 30 | printf("%d\t", A[j]); 31 | } 32 | printf("\n"); 33 | } 34 | 35 | //主函数 36 | int main() { 37 | //初始化 38 | int A[N-1]; 39 | int x,y; 40 | 41 | //调用递增函数 42 | for (x=0; x<16; x++) { 43 | printf("x=%d:\t", x); 44 | INCREMENT(A); 45 | } 46 | 47 | //输出 48 | printf("Final:\n"); 49 | for (y=N-1; y>-1; y--) { 50 | printf("%d\t", A[y]); 51 | } 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /Images/RB-INSERT-FIXUP-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuzhiyi/CLRS-solution/c5a699ac054e89b02e108c31b7f6126da461d037/Images/RB-INSERT-FIXUP-01.png -------------------------------------------------------------------------------- /Images/区间树-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuzhiyi/CLRS-solution/c5a699ac054e89b02e108c31b7f6126da461d037/Images/区间树-02.png -------------------------------------------------------------------------------- /Images/红黑树 RB-DELETE-FIXUP 路线图 .png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuzhiyi/CLRS-solution/c5a699ac054e89b02e108c31b7f6126da461d037/Images/红黑树 RB-DELETE-FIXUP 路线图 .png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 vinci 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Others/Brute-Force-Additive-Cipher.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: 6 | * 名称: 暴力破解additive cipher 7 | * 作者: wuzhiyi 8 | * 语言: c 9 | * 内容摘要: 输出所有 key 情况 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150718 V1.0 wuzhiyi 创建 15 | **************************************************************/ 16 | #include 17 | #include 18 | 19 | 20 | int main() { 21 | //输入 ciphertext 22 | char s[]="OTWEWNGWCBPQABIZVQAPMLJGZWTTQVOBQUMAPMIDGZCABEQVBMZLZIXMLAXZQVOQVLMMXAVWEIVLLIZSNZWABJQZLWNLMTQOPBVIUMLGWCBPAEQNBTGTMNBBPMVMABITIAKWCTLVBBQUMQBEPQTMQBEIAQVUGBZCAB"; 23 | int A[162], i=0, j; 24 | 25 | //转化为小写 26 | printf("tolower:\n"); 27 | for (i=0; i<162; i++) { 28 | s[i]=tolower(s[i]); 29 | printf("%c", s[i]); 30 | } 31 | 32 | //将字母转为 ascii 码 33 | printf("\ntoascii\n"); 34 | //key 从1到26,所有情况 35 | for (j=1; j<26; j++) { 36 | printf("\nkey = %d:\n", j); 37 | for (i=0; i<162; i++) { 38 | A[i]=toascii(s[i])-j; 39 | if (A[i]<97) { //若超出小写字母数字范围,取模,使数值合理 40 | A[i]=A[i]+26; 41 | } 42 | printf("%c", A[i]); //每个小循环输出给定 key 值下的转换结果,即 plaintext 43 | } 44 | printf("\n"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Others/Ext-Euclid.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Extended Euclidean Algorithm 6 | * 名称: 扩展欧几里得算法 7 | * 作者: wuzhiyi 8 | * 语言: c 9 | * 内容摘要: 辗转相除法求最大公约数,满足贝祖等式:ax+by=gcd(a,b) 10 | * 若a为负数,则令|a|(-x)+by=gcd(|a|,b), x'=(-x). 11 | * 12 | * 修改记录: 13 | * 修改日期 版本号 修改人 修改内容 14 | * ------------------------------------------------------------ 15 | * 20150725 V1.0 wuzhiyi 创建 16 | **************************************************************/ 17 | #include 18 | 19 | int Ext_Euclid_Gcd(int a, int b, int *x, int *y) { 20 | if (b==0) { //若b=0,则 ax=gcd(a,0)=a 21 | *x = 1, *y = 0; 22 | return a; 23 | } 24 | else { 25 | int r = Ext_Euclid_Gcd(b, a%b, x, y); 26 | int t = *x; 27 | *x = *y; 28 | *y = t - a/b * (*y); 29 | return r; 30 | } 31 | } 32 | 33 | int main() { 34 | int x, y; 35 | int a=400, b=577; 36 | printf ("贝祖等式 %dx + %dy = gcd(%d, %d)\n", a, b, a, b); 37 | printf ("gcd(%d,%d)=%d,\tx=%d, y=%d", a, b, Ext_Euclid_Gcd(a, b, &x, &y), x, y); 38 | } 39 | -------------------------------------------------------------------------------- /Others/Modular-Exp.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Modular_Exponentiation 6 | * 名称: 指数取模算法 7 | * 作者: wuzhiyi 8 | * 语言: c 9 | * 内容摘要: 不同方法对指数取模 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150723 V1.0 wuzhiyi 创建 15 | * 20150724 V2.0 wuzhiyi 添加快速指数取模函数 16 | * 20150724 V2.1 wuzhiyi 添加同余公式和反复平法 17 | **************************************************************/ 18 | #include 19 | 20 | //define A^B mod M 21 | #define A 9 22 | #define B 29 23 | #define M 264 24 | 25 | //二分指数取余 26 | int Divide_Remainder(int a) { 27 | if (a > 1) { 28 | if (a%2 != 0){ 29 | //printf ("Remainder(%d) & Remainder(%d)\n", a/2, a/2+1); 30 | return (Divide_Remainder(a/2)*Divide_Remainder((a/2)+1))%M; 31 | } 32 | else { 33 | //printf ("Remainder(%d) & Remainder(%d)\n", a/2, a/2); 34 | return (Divide_Remainder(a/2)*Divide_Remainder(a/2))%M; 35 | } 36 | } 37 | return A%M; 38 | } 39 | /* 此处二分幂算法存在优化空间 40 | * (1)找到指数二分中的临界值,直接计算取余,则不需要继续将指数二分到 1; 41 | * (2)增加一个备忘数组,每次二分时先搜索备忘数组,如果结果已经存在,则直接调用备忘数组中的结果. 42 | */ 43 | 44 | //利用同余公式(Congruence Formula)对幂取模 45 | int Congru_Mod (int a, int b, int m) { 46 | int result = 1; 47 | for (int i=0; i>=1) { //b>>=1:先将变量b的各二进制位顺序右移1位,最高位补二进制0,再将结果返回给b 58 | z++; 59 | if (b%2==0) I[z]=0; 60 | else I[z]=1; 61 | } 62 | y=(a*a)%m; 63 | for (; z>0; z--) { 64 | if (I[z]) y=((y*a%m)*(y*a%m))%m; 65 | else y=(y*y)%m; 66 | } 67 | if (I[0]) y = (y*a%m); 68 | return y; 69 | } 70 | /* 此处快速指数取模有一个问题:当A=3,B=1,C=5时不成立 71 | */ 72 | 73 | //反复平方法(Right-to-Left Bianry Method) 74 | //也叫 Montgomery 算法 75 | //将幂B转换为二进制表示,并从右至左扫描其每一位(从低到高) 76 | int Montgomery(int a, int b, int m) { 77 | int result = 1; 78 | int base = a; 79 | while (b>0) { 80 | if ((b & 1)==1) { //如果第i位为1,则表示该位需要参与模运算 81 | result = (result*base)%m; 82 | } 83 | base = (base*base)%m; //第i位位0,不需要参与模运算 84 | b>>=1; //b右移一位 85 | } 86 | return result; 87 | } 88 | 89 | int main() { 90 | printf ("求 A^B mod M\n"); 91 | printf ("A = %d, B = %d, M = %d\n", A, B, M); 92 | printf ("二分指数取余:%d^%d mod %d = %d\n", A, B, M, Divide_Remainder(B)); 93 | printf ("同余公式取模:%d^%d mod %d = %d\n", A, B, M, Congru_Mod(A, B, M)); 94 | printf ("快速指数取模:%d^%d mod %d = %d\n", A, B, M, Quick_Index_Mod(A, B, M)); 95 | printf ("反复平方法: %d^%d mod %d = %d\n", A, B, M, Montgomery(A, B, M)); 96 | } 97 | -------------------------------------------------------------------------------- /Others/Multiplicative-Inverse.c: -------------------------------------------------------------------------------- 1 | /************************************************************** 2 | * Copyright (c) Wuzhiyi 3 | * Introduction to Algorithms 4 | * 5 | * 题目: Multiplicative-Inverse 6 | * 名称: 乘法逆元 7 | * 作者: wuzhiyi 8 | * 语言: c 9 | * 内容摘要: 暴力法,费马小定理,扩展欧几里得算法,(预处理法,神奇推倒公式法) 10 | * 11 | * 修改记录: 12 | * 修改日期 版本号 修改人 修改内容 13 | * ------------------------------------------------------------ 14 | * 20150724 V1.0 wuzhiyi 创建 15 | * 20150725 V2.0 wuzhiyi 添加扩展欧几里得算法 16 | **************************************************************/ 17 | #include 18 | 19 | //初始定义 A*B = 1 mod M 20 | #define A 89 21 | #define M 191 22 | 23 | int Divide_Remainder (int, int ,int); 24 | int inv[M]; //Pre_Inv 变量数组声明 25 | 26 | //暴力求解逆元 27 | int Brute_Inv(int a, int m) { 28 | int i=0; 29 | //判断 a 与 m 是否互素 30 | if (a%m!=0 && m%a!=0) { 31 | //循环求解 32 | for (; i 1) { 77 | if (b%2 != 0){ 78 | return (Divide_Remainder(a, b/2, m)*Divide_Remainder(a, b/2+1, m)%m); 79 | } 80 | else { 81 | return (Divide_Remainder(a, b/2, m)*Divide_Remainder(a, b/2, m))%m; 82 | } 83 | } 84 | return a%m; 85 | } 86 | 87 | //扩展欧几里得算法 88 | int Ext_Euclid_Gcd(int a, int b, int *x, int *y) { 89 | if (b==0) { //若b=0,则 ax=gcd(a,0)=a 90 | *x = 1, *y = 0; 91 | return a; 92 | } 93 | else { 94 | if (Prime(A) && Prime(M)) { //A 与 M 互素, gcd(A,M)=1 时成立 95 | int r = Ext_Euclid_Gcd(b, a%b, x, y); 96 | int t = *x; 97 | *x = *y; 98 | *y = t - a/b * (*y); 99 | if (*x < 0) *x = (*x%M + M)%M; //如果 x 为负数,取模对称的正数 100 | return r; 101 | } 102 | else { 103 | printf ("A 与 MOD 不互素,不能使用扩展欧几里得定理\n"); 104 | return 0; 105 | } 106 | } 107 | } 108 | 109 | //预处理法和神奇推倒公式法都还没完善 110 | 111 | /* 预处理法 112 | * 遍历所有 1~i 关于 M 逆元,因为逆元是积性函数,所以只要 M>i 成立即可,不需要 M 必须为素数 113 | */ 114 | void Pre_Inv() { 115 | inv[0] = inv[1] = 1; 116 | for (int i=2; i 7 | 8 | #### Contents 9 | 10 | - [Chapter 2 Getting Started](#chapter-2) 11 | - [Chapter 4 Divide-and-Conquer](#chapter-4) 12 | - [Chapter 5 Probabilistic Analysis and Randomized Algorithms](#chapter-5) 13 | - [Chapter 6 Heapsort](#chapter-6) 14 | - [Chapter 7 Quicksort](#chapter-7) 15 | - [Chapter 8 Sorting in Linear Time](#chapter-8) 16 | - [Chapter 10 Data Structures](#chapter-10) 17 | - [Chapter 12 Binary Search Trees](#chapter-12) 18 | - [Chapter 13 Red-Black Trees](#chapter-13) 19 | - [Chapter 14 Augmenting Data Structures](#chapter-14) 20 | - [Chapter 15 Dynamic Programming](#chapter-15) 21 | - [Chapter 16 Greedy Algorithms](#chapter-16) 22 | - [Chapter 17 Amortized Analysis](#chapter-17) 23 | - [Others](#chapter-others) 24 | 25 | ## INFO 26 | 27 | Introduction to Algorithms, 3rd edition
28 | 29 | If you have any questions or intend to improve my solution,
you could directly post an issue or fork a repository by yourself
30 | 31 | Thanks for your contribution. 32 | 33 | Continuous Updating
34 | 35 | _wuzhiyi_ 36 | 37 | ## NAME FORMAT 38 | 39 | C - Chapter
40 | E - Exercise
41 | P - Problem
42 | 43 | #### Example: 44 | 45 | C_2.3.1: Chapter 2.3.1
46 | E_2.3-5.2: Exercise 2.3-5, 2nd version
47 | E_10.1-5~7: Exercise 10.1-5 ~ 10.1-7
48 | 49 | ## INDEX 50 | 51 | #### [Chapter 2 Getting Started](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter02) 52 | 53 | - [Chapter 2.3.1](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/C_2.3.1.c) - MERGE SORT 54 | - [Exercise 2.1-4](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/E_2.1-4.c) - ADD BINARY 55 | - [Exercise 2.2-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/E_2.2-2.c) - SELECTION SORT| 56 | - [Exercise 2.3-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/E_2.3-2.c) - MERGE SORT (no sentinel) 57 | - [Exericse 2.3-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/E_2.3-5.c) - BINARY SEARCH 58 | - [Exercise 2.3-6](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/E_2.3-6.c) - use BINARY SEARCH improve INSERTION SORT 59 | - [Exercise 2.3-7](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/E_2.3-7.c) - find sum 60 | - [Problem 2-1](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/P_2-1.c) - INSERTION SORT on small arrays in MERGE SORT 61 | - [Problem 2-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/P_2-2.c) - correctness of BUBBLESORT 62 | - [Problem 2-4](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter02/P_2-4.c)- inversions 63 | 64 | #### [Chapter 4 Divide-and-Conquer](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter04) 65 | 66 | - [Chapter 4.1](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter04/C_4.1.c) - the maximum-subarray problem 67 | - [Exercise 4.1-3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter04/E_4.1-3.c) - crossover point of brute-force & recursive algorithm for the maximum-subarray problem 68 | - [Exercise 4.1-4](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter04/E_4.1-4.c) - the maximum-subarray problem (allow empty subarray) 69 | - [Exercise 4.1-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter04/E_4.1-5.c) - the maximum-subarray problem (nonrecursive & linear-time) 70 | - [Exercise 4.2-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter04/E_4.2-2.c) - Strassen's algorithm 71 | - [Problem 4-6](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter04/P_4-6.c) - Monge arrays 72 | 73 | #### [Chapter 5 Probabilistic Analysis and Randomized Algorithms](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter05) 74 | 75 | - [Exercise 5.1-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter05/E_5.1-2.c) - RANDOM(a,b) makes calls to RANDOM(0,1) 76 | - [Exercise 5.1-3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter05/E_5.1-3.c) - BIASED-RANDOM 77 | 78 | 79 | 80 | #### [Chapter 6 Heapsort](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter06) 81 | 82 | - [Chapter 6](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter06/C_6.c) - heap sort 83 | - [Exercise 6.2-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter06/E_6.2-5.c) - MAX-HEAPIFY (iterative) 84 | - [Exercise 6.5-3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter06/E_6.5-3.c) - min-heap 85 | - [Exercise 6.5-6](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter06/E_6.5-6.c) - HEAP-INCREASE-KEY (INSERTION-SORT) 86 | - [Exercise 6.5-9](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter06/E_6.5-9.cpp) - min-heap for k-way merging 87 | - [Problem 6-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter06/P_6-2.c) - analysis of d-ary heaps 88 | - [Problem 6-3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter06/P_6-3.c) - Young tableaus 89 | 90 | #### [Chapter 7 Quicksort](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter07) 91 | 92 | - [Chapter 7.3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter07/C_7.3.c) - RANDOMIZED-QUICKSORT 93 | - [Exercise 7.4-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter07/E_7.4-5.c) - improve QUICKSORT by INSERTION SORT 94 | - [Problem 7-1](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter07/P_7-1.2.c) - Hoare partition correctness 95 | 96 | #### [Chapter 8 Sorting in Linear Time](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter08) 97 | 98 | - [Problem 8-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter08/P_8-2.c) - sorting in place in linear time 99 | - [Problem 8-3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter08/P_8-3.c) - sorting variable-length items 100 | - [Problem 8-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter08/P_8-5.c) - averaging sorting 101 | - [Problem 8-7](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter08/P_8-7.c) - the 0-1 sorting lemma and columnsort 102 | 103 | #### [Chapter 10 Data Structures](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter10) 104 | 105 | - [Exercise 10.1-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.1-5.c) - deque (double-ended queue) 106 | - [Exercise 10.2-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.2-2.2.c) - implement a stack using a singly linked list 107 | - [Exercise 10.2-3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.2-3.c) - implement a queue by a singly linked list 108 | - [Exercise 10.2-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.2-5.c) - implement the dictionary operations using singly linked, circular lists 109 | - [Exercise 10.2-7](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.2-7.c) - nonrecursively reverse a singly linked list 110 | - [Exercise 10.3-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.3-2.c) - implement ALLOCATE-OBJECT & FREE-OBJECT by singly-array 111 | - [Exercise 10.3-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.3-5.c) - COMPACTIFY-LIST (doubly linked list) 112 | - [Exercise 10.4-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.4-2.c) - recursively print out the key of each node in a binary tree 113 | - [Exercise 10.4-3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/E_10.4-3.c) - nonrecursively print out the key of each node in a binary tree 114 | - [Problem 10-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter10/P_10-2.c) - mergeable heaps using linked lists 115 | 116 | #### [Chapter 12 Binary Search Trees](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter12) 117 | 118 | - [Problem 12-1](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter12/P_12-1.c) - binary search trees with equal keys 119 | - [Problem 12-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter12/P_12-2.c) - radix trees 120 | 121 | #### [Chapter 13 Red-Black Trees](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter13) 122 | 123 | - [Problem 13-1](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter13/P_13-1.cpp) - persistent dynamic sets 124 | - [Problem 13-4](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter13/P_13-4.cpp) - Treaps 125 | 126 | #### [Chapter 14 Augmenting Data Structures](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter14) 127 | 128 | - [Chapter 14.3](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter14/C_14.3.cpp) - interval trees 129 | - [Exercise 14.3-6](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter14/E_14.3-6.cpp) - maintain a dynamic set that supports the operation MIN-GAP 130 | 131 | #### [Chapter 15 Dynamic Programming](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter15) 132 | 133 | - [Exercise 15.1-5](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter15/E_15.1-5.cpp) - the Fibonacci numbers (dynamic-programming algorithm) 134 | 135 | #### [Chapter 16 Greedy Algorithms](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter16) 136 | 137 | - [Exercise 16.1-2](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter16/E_16.1-2.cpp) - the last activity to start (greedy algorithm) 138 | - [Exercise 16.1-4](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter16/E_16.1-4.cpp) - interval-graph coloring problem 139 | 140 | #### [Chapter 17 Amortized Analysis](https://github.com/wuzhiyi/CLRS-solution/tree/master/Chapter17) 141 | 142 | - [Chapter 17.1](https://github.com/wuzhiyi/CLRS-solution/blob/master/Chapter17/C_17.1.c) - incrementing a binary counter 143 | 144 | #### [Others](https://github.com/wuzhiyi/CLRS-solution/tree/master/Others) 145 | 146 | - [Additive-Cipher](https://github.com/wuzhiyi/CLRS-solution/blob/master/Others/Brute-Force-Additive-Cipher.c) - additive cipher (BRUTE-FORCE) 147 | - [Ext-Euclid](https://github.com/wuzhiyi/CLRS-solution/blob/master/Others/Ext-Euclid.c) - extended Euclidean algorithm 148 | - [Modular-Exp](https://github.com/wuzhiyi/CLRS-solution/blob/master/Others/Modular-Exp.c) - modular exponentiation algorithm 149 | - [Multiplicative-Inverse](https://github.com/wuzhiyi/CLRS-solution/blob/master/Others/Multiplicative-Inverse.c) - multiplicative inverse (Fermat's little theorem & extended Euclidean algorithm) 150 | 151 | ## LICENSE 152 | The MIT License (MIT) 153 | 154 | Copyright (c) 2015 vinci 155 | 156 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 157 | 158 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 159 | 160 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 161 | 162 | --- 163 | connect to my repository [data-structure](https://github.com/wuzhiyi/data-structure)
164 | --------------------------------------------------------------------------------