├── .gitignore ├── README.md ├── chapter_2 ├── 2.2.3 │ ├── 2.2.3_10.cpp │ ├── 2.2.3_11.cpp │ ├── 2.2.3_12.cpp │ ├── 2.2.3_13.cpp │ ├── 2.2.3_14.cpp │ ├── 2.2.3_1_mach4101.cpp │ ├── 2.2.3_2_mach4101.cpp │ ├── 2.2.3_3_mach4101.cpp │ ├── 2.2.3_4_mach4101.cpp │ ├── 2.2.3_5_mach4101.cpp │ ├── 2.2.3_6_mach4101.cpp │ ├── 2.2.3_7.cpp │ ├── 2.2.3_7_mach4101.cpp │ ├── 2.2.3_8.cpp │ ├── 2.2.3_9.cpp │ ├── 2.3.3_8_mach4101.cpp │ └── 2.3.3_9_mach4101.cpp └── 2.3.7 │ ├── 2.3.7_1.cpp │ ├── 2.3.7_10_mach4101.cpp │ ├── 2.3.7_11_mach4101.cpp │ ├── 2.3.7_12_mach4101.cpp │ ├── 2.3.7_13_mach4101.cpp │ ├── 2.3.7_14_mach4101.cpp │ ├── 2.3.7_15_mach4101.cpp │ ├── 2.3.7_16_mach4101.cpp │ ├── 2.3.7_1_mach4101.cpp │ ├── 2.3.7_2.cpp │ ├── 2.3.7_2_mach4101.cpp │ ├── 2.3.7_3.cpp │ ├── 2.3.7_3_mach4101.cpp │ ├── 2.3.7_4.cpp │ ├── 2.3.7_4_mach4101.cpp │ ├── 2.3.7_5.cpp │ ├── 2.3.7_5_mach4101.cpp │ ├── 2.3.7_6_mach4101.cpp │ ├── 2.3.7_7_mach4101.cpp │ ├── 2.3.7_8_mach4101.cpp │ └── 2.3.7_9_mach4101.cpp ├── chapter_3 ├── 3.1.4 │ ├── 3.1.4_3_mach4101.cpp │ ├── 3.1.4_4_mach4101.cpp │ └── 3.1.4_5_mach4101.cpp ├── 3.2.5 │ ├── 3.2.5_1_mach4101.cpp │ ├── 3.2.5_2_mach4101.cpp │ └── 3.2.5_3_mach4101.cpp └── 3.3.6 │ ├── 3.3.6_1_mach4101.cpp │ ├── 3.3.6_2_mach4101.cpp │ ├── 3.3.6_3_栈版本_mach4101.cpp │ └── 3.3.6_3_递归版_mach4101.cpp ├── chapter_5 ├── 5.2.3 │ ├── .DS_Store │ ├── 5.2.3_5_mach4101.cpp │ └── 例图.png ├── 5.3.3 │ ├── 5.3.3_10_mach4101.cpp │ ├── 5.3.3_11_mach4101.cpp │ ├── 5.3.3_12_mach4101.cpp │ ├── 5.3.3_13_mach4101.cpp │ ├── 5.3.3_14_mach4101.cpp │ ├── 5.3.3_15_mach4101.cpp │ ├── 5.3.3_16_mach4101.cpp │ ├── 5.3.3_17_mach4101.cpp │ ├── 5.3.3_3_mach4101.cpp │ ├── 5.3.3_4_mach4101.cpp │ ├── 5.3.3_5_mach4101.cpp │ ├── 5.3.3_6_mach4101.cpp │ ├── 5.3.3_7_mach4101.cpp │ ├── 5.3.3_8_mach4101.cpp │ ├── 5.3.3_9_mach4101.cpp │ ├── 例图.png │ ├── 第11题的例图.png │ └── 第十五题例图.jpeg └── 5.4.4 │ ├── 5.4.4_4_mach4101.cpp │ ├── 5.4.4_5_mach4101.cpp │ ├── 树及其对应的二叉树的例图.jpeg │ └── 森林及其对应的二叉树例图.jpeg ├── chapter_6 ├── .DS_Store ├── 6.2.6 │ ├── .DS_Store │ ├── 6.2.6_4_mach4101.cpp │ ├── Example_AList_ALGraph.cpp │ ├── Example_Matrix_Graph.cpp │ └── 样例图.png └── 6.3.4 │ ├── 6.3.4_2_mach4101.cpp │ ├── 6.3.4_3_mach4101.cpp │ ├── 6.3.4_4_mach4101.cpp │ ├── 6.3.4_5_mach4101.cpp │ └── 样例图.png ├── chapter_7 ├── 7.2.4 │ ├── 7.2.4_5_mach4101.cpp │ ├── 7.2.4_6_LinkedList_mach4101.cpp │ └── 7.2.4_6_mach4101.cpp └── 7.3.4 │ ├── 7.3.4_10_mach4101.cpp │ ├── 7.3.4_6_mach4101.cpp │ ├── 7.3.4_6_例图.jpeg │ ├── 7.3.4_7_mach4101.cpp │ ├── 7.3.4_8_mach4101.cpp │ └── 7.3.4_9_mach4101.cpp └── chapter_8 ├── 8.3.3 ├── 8.3.3_2_mach4101.cpp ├── 8.3.3_3_mach4101.cpp ├── 8.3.3_4_mach4101.cpp ├── 8.3.3_5_mach4101.cpp └── 8.3.3_6_mach4101.cpp └── 8.4.3 ├── 8.4.3_4_mach4101.cpp └── 8.4.3_5_mach4101.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Clion配置文件 2 | .idea 3 | 4 | # vscode配置文件 5 | .vscode 6 | 7 | # CMake文件 8 | CMakeLists.txt 9 | cmake-build-debug 10 | 11 | # debug配置文件 12 | /cmake-build-debug 13 | /cmake-build-debug-raspberry 14 | 15 | # CPP编译产生的目标文件 16 | *.exe 17 | *.txt 18 | *.out 19 | *.app 20 | *.c 21 | *.obj 22 | 23 | # 配置文件 24 | .xml 25 | .js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wangdao_exercise 2 | 王道课后习题代码 3 | 目前的更新情况:已经全部更新,408真题或者少量较麻烦的题目未写 4 | 5 | Note:由于目前本仓库有两位作者,mach4101和wulnut,因此目前有两种代码风格供大家查看,其中以mach4101作为后缀名的文件为mach4101所写。 6 | 7 | 视频讲解:(暂不更新) 8 | 9 | ## 第二章 线性表 10 | 11 | ### 2.2.3 综合应用题 😉 12 | - ✔ 第一题:删除顺序表中最小元素 13 | - ✔ 第二题:顺序表逆置 14 | - ✔ 第三题:删除所有值为x的元素 15 | - ✔ 第四题:有序顺序表中删除s到t之间的元素 16 | - ✔ 第五题:顺序表中删除s到t之间的元素 17 | - ✔ 第六题:有序表去重 18 | - ✔ 第七题:合并两个顺序表 19 | - ✔ 第八题:将两个线性表的位置互换 20 | - ✔ 第九题:递增有序的线性表查找x 21 | - ✔ 第十题:统考题 22 | - ✔ 第十一题:统考题 23 | - ✔ 第十二题:统考题 24 | - ✔ 第十三题:统考题 25 | - ✔ 第十四题:统考题 26 | 27 | ### 2.3.7 综合应用题 😉 28 | 29 | - ✔ 第一题:删除不带头结点L的所有值为x的结点 30 | - ✔ 第二题:带头结点的链表L中,删除所有值为x的结点 31 | - ✔ 第三题:逆向输出单链表 32 | - ✔ 第四题:带头结点的单链表L中删除最小值的结点 33 | - ✔ 第五题:逆置单链表 34 | - ✔ 第六题:带头结点的单链表L,设计算法使其递增有序 35 | - ✔ 第七题:无序单链表中删除介于两个给定值之间的元素 36 | - ✔ 第八题:寻找两个单链表的公共结点 37 | - ✔ 第九题:按照递增次序输出单链表中各结点的数据元素并释放空间 38 | - ✔ 第十题:按照奇偶拆分链表 39 | - ✔ 第十一题:按照题目要求拆分链表 40 | - ✔ 第十二题:有序单链表去重 41 | - ✔ 第十三题:两个递增排列的线性表,归并为一个递减的链表 42 | - ✔ 第十四题:单链表A和B中的公共结点组成链表C,不破坏原结点 43 | - ✔ 第十五题:将单链表A和B的元素交集存放到A链表中 44 | - ✔ 第十六题:判断单链表B是否是单链表A的连续子序列 45 | - 后面的循环链表先暂时放一放,考的不多,之后有空就写,没空就不写了。 46 | 47 | ## 第三章 栈、队列和数组 48 | 49 | ### 3.1.4 综合应用题 😉 50 | 51 | * ✔ 前两题不是编程题,skip 52 | * ✔ 第三题:判断序列合法性 53 | * ✔ 第四题:判断带头结点的链表是否中心对称 54 | * ✔ 第五题:两栈共享空间 55 | 56 | ### 3.2.5 综合应用题 😉 57 | 58 | * ✔ 第一题:循环队列添加tag识别队空队满 59 | * ✔ 第二题:利用栈来实现队列中的元素逆置 60 | * ✔ 第三题:利用两个栈来模拟队列 61 | 62 | ### 3.3.6 综合应用题 😉 63 | * ✔ 第一题:括号匹配 64 | * ✔ 第二题:栈道模拟 65 | * ✔ 第三题:用栈实现递归函数的非递归 66 | * 第四题有空再看 67 | 68 | ## 第四章 串 69 | 串我们不考,而且也没有什么代码题,考场上不可能让你手写KMP的,所以跳过 70 | 71 | ## 第五章 树与二叉树 72 | 73 | ### 5.2.3 综合应用题 😉 74 | 75 | * ✔ 第五题:顺序存储结构的二叉树求编号i和j的最近公共祖先 76 | 77 | ### 5.3.3 综合应用题 😉 78 | * ✔ 第三题:后序遍历非递归 79 | * ✔ 第四题:二叉树自下而上,自右到左的层次遍历算法 80 | * ✔ 第五题:二叉链表结构的二叉树,非递归求高度 81 | * ✔ 第六题:知道先序和中序,建立二叉树的二叉链表 82 | * ✔ 第七题:判断一棵二叉树是否是完全二叉树 83 | * ✔ 第八题:计算一颗给定二叉树的所有双分支结点个数 84 | * ✔ 第九题:交换二叉树的左右子树 85 | * ✔ 第十题:先序遍历的第k个结点的值 86 | * ✔ 第十一题:对于每个元素值为x的结点,删除以它为根的子树并释放空间 87 | * ✔ 第十二题:打印值为x的结点的所有祖先 88 | * ✔ 第十三题:最近公共祖先 89 | * ✔ 第十四题:二叉链表结构的二叉树算树的宽度 90 | * ✔ 第十五题:一颗满二叉树,知道先序求后序 91 | * ✔ 第十六题:将二叉树的叶子结点从左到右串成一个链表 92 | * ✔ 第十七题:判断两个二叉树是否相似 93 | * 第十八题线索二叉树考代码不多, skip 94 | 95 | ### 5.4.4 综合应用题 😉 96 | * ✔ 第四题:孩子兄弟表示法的森林叶子结点数 97 | * ✔ 第五题:孩子兄弟表示法:递归求深度 98 | * 第六题不会... 99 | 100 | ## 第六章 图 101 | ### 6.2.6 综合应用题 😉 102 | * ✔ 第四题:图的邻接表转换成邻接矩阵 103 | * ✔ 邻接表的写法 104 | * ✔ 邻接矩阵的写法 105 | 106 | ### 6.3.4 综合应用题 😉 107 | * ✔ 第二题:无向图G是否是一棵树 108 | * ✔ 第三题:DFS的非递归形式 109 | * ✔ 第四题:使用DFS和BFS判断有向图中是否有vi到vj的路径 110 | * ✔ 第五题:输出从顶点vi到vj的所有路径 111 | 112 | ## 第七章 查找 113 | ### 7.2.4 综合应用题 😉 114 | * ✔ 第五题:折半查找递归算法 115 | * ✔ 第六题(顺序表):找到指定结点,与其后面的元素交换位置 116 | * ✔ 第六题(链表) 117 | 118 | ### 7.3.4 综合应用题 😉 119 | * ✔ 第六题:判断给定的二叉树是否是二叉排序树 120 | * ✔ 第七题:求出指定结点再二叉排序树中的层次 121 | * ✔ 第八题:利用二叉树的遍历思想判断二叉树是否是高度平衡的二叉树 122 | * ✔ 第九题:求出给定二叉排序树中的最小和最大关键字 123 | * ✔ 第十题 :从大到小输出二叉排序树中值不小于k的关键字 124 | * 第十一题,有些复杂,放了 125 | 126 | ## 第八章 排序 127 | 128 | ### 8.3.3 综合应用题 😉 129 | * ✔ 第二题:双向冒泡排序 130 | * ✔ 第三题:将顺序表的奇数元素移动到偶数前面 131 | * ✔ 第四题:重写快排,枢纽随机 132 | * ✔ 第五题:第k小元素 133 | * ✔ 第六题:荷兰国旗问题 134 | 135 | ### 8.4.3 综合应用题 😉 136 | * ✔ 第四题:在单链表上进行选择排序 137 | * ✔ 第五题:判断数据序列是否构成一个小根堆 138 | 139 | ## Stargazers over time 140 | 141 | [![Stargazers over time](https://starchart.cc/mach4101/wangdao_exercise.svg)](https://starchart.cc/mach4101/wangdao_exercise) 142 | -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_10.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.2.3_10.cpp 3 | * Create: 2022-05-28 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | typedef int ElemType; 11 | 12 | void reverse(ElemType arr[], int begin, int end) { 13 | int i = begin; 14 | int j = end; 15 | int temp; 16 | 17 | while (i < j) { 18 | temp = arr[i]; 19 | arr[i ++] = arr[j]; // 先把arr[j]放入arr[i], i在往后移动 20 | arr[j --] = temp; 21 | } 22 | } 23 | 24 | void converse(ElemType arr[], int length, int round) { 25 | int m = round % length; 26 | reverse(arr, 0, m - 1); 27 | reverse(arr, m, length - 1); 28 | reverse(arr, 0, length - 1); 29 | 30 | for (int i =0; i < length; ++ i) { 31 | printf("%d ", arr[i]); 32 | } 33 | } 34 | 35 | int main() { 36 | int arr[] = {1, 2, 3, 4, 5, 6}; 37 | converse(arr, 6, 2); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_11.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.2.3_11.cpp 3 | * Create: 2022-05-28 4 | * Author: Wulnut 5 | * *************************************************/ 6 | /** 7 | * 分别求两个升序序列A、B的中位数,设为a和b。 8 | * 1.若a=b,则a或b即为所求的中位数,算法结束。 9 | * 2.若ab,舍弃B中较小者所在序列之较小一半,同时舍弃A所在序列之较大一半,要求两次舍弃的元素个数相同。 11 | * 在保留的两个升序序列中,重复上述过程,直到两个序列中均只含一个元素时为止,则较小者即为所求的中位数。 12 | * 13 | * 若ab时,原理同上。当A长度为奇数时,左半边=右半边,直接舍弃即可当A长度为偶数时,左半边+1=右半边。 16 | * 若a 20 | using namespace std; 21 | 22 | //寻找两个有序数组的中位数 23 | int middle_search(int A[], int B[], int n) 24 | { 25 | int m1, m2, s1, s2, d1, d2; 26 | s1 = s2 = 0; 27 | d1 = d2 = n - 1; 28 | while (s1 != d1 || s2 != d2) 29 | { 30 | m1 = (s1 + d1) / 2; 31 | m2 = (s2 + d2) / 2; 32 | if (A[m1] == B[m2]) 33 | return A[m1]; 34 | if (A[m1] < B[m2])//A的中位数比B的中位数小 35 | { 36 | if ((s1 + d1) % 2 == 0)//当前比较元素为奇数 37 | { 38 | s1 = m1;//A的比较范围向后移动,保留中间点 39 | } else { 40 | s1 = m1 + 1;//A的比较范围向后移动,不保留中间点 41 | } 42 | d2 = m2;//B的比较范围向前移动,保留中间点 43 | } else {//A的中位数比B的中位数大 44 | d1 = m1;//A的比较范围向前移动,保留中间点 45 | if ((s2 + d2) % 2 == 0)//当前比较元素为偶数 46 | { 47 | s2 = m2;//B的比较范围向后移动,保留中间点 48 | } else { 49 | s2 = m2 + 1;//B的比较范围向后移动,保留中间点 50 | } 51 | } 52 | } 53 | if (A[s1] < B[s2])//取小即为中位数点 54 | return A[s1]; 55 | else return B[s2]; 56 | 57 | } 58 | 59 | int main() { 60 | int A[] = {11, 13, 15, 17, 19}; 61 | int B[] = {2, 4, 6, 8, 20}; 62 | int mid = middle_search(A, B, 5); 63 | printf("%d", mid); 64 | return 0; 65 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_12.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.2.3_12.cpp 3 | * Create: 2022-05-28 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | // 摩尔投票法 11 | int MooreVoting(int arr[],int n){ 12 | 13 | int x,count; 14 | x=0; 15 | count=0; //表示一个虚拟数组 16 | for (int i=0; i n / 2) { 68 | 69 | return c; 70 | } 71 | else 72 | return -1; 73 | } 74 | 75 | int main() { 76 | int A[] = {0, 5, 5, 3, 5, 7, 5}; // True 77 | int B[] = {0, 5, 5, 3, 5, 1, 5, 7}; // False 78 | 79 | if (MajorNum(A, 7) != -1) printf("A:True\n"); 80 | else printf("A:False\n"); 81 | 82 | if (MajorNum(B, 8) != -1) printf("B:True"); 83 | else printf("B:False"); 84 | 85 | return 0; 86 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_13.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.2.3_13.cpp 3 | * Create: 2022-05-28 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | int missMinNum(int arr[], int n) 11 | { 12 | int l = 0; 13 | int r = n; 14 | 15 | while(l < r) 16 | { 17 | if(arr[l] == l + 1)//在理想的位置 18 | { 19 | l++; 20 | } 21 | else if(arr[l] > r || arr[l] <= l || arr[arr[l] - 1] == arr[l])//不合法的数据 22 | { 23 | arr[l] = arr[--r]; 24 | } 25 | else//合法但是没有在理想的位置上 26 | { 27 | int temp= arr[l]; 28 | arr[l] = arr[arr[l] - 1]; 29 | arr[temp - 1] = temp; 30 | } 31 | 32 | }//while 33 | 34 | return l + 1; 35 | 36 | }//missMinMun() 37 | 38 | int main() { 39 | int arr[] = {-1, 2, 3, 4}; 40 | 41 | printf("%d", missMinNum(arr, 4)); 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_14.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.2.3_14.cpp 3 | * Create: 2022-05-28 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | /* 8 | * 输入样例: 9 | * 3 4 5 10 | * -1 0 9 11 | * -25 -10 10 11 12 | * 2 9 17 30 41 13 | * 输出结果: 14 | * 2 15 | */ 16 | 17 | #include 18 | using namespace std; 19 | 20 | typedef long long LL; 21 | 22 | const int N = 100010; 23 | 24 | int l, m, n; 25 | int a[N], b[N], c[N]; 26 | 27 | int main() 28 | { 29 | cin >> l >> m >> n; 30 | 31 | for (int i = 0; i < l; i++) 32 | cin >> a[i]; 33 | for (int i = 0; i < m; i++) 34 | cin >> b[i]; 35 | for (int i = 0; i < n; i++) 36 | cin >> c[i]; 37 | 38 | LL res = 1e18; 39 | 40 | for (int i = 0, j = 0, k = 0; i < l && j < m && k < n;) { 41 | 42 | int x= a[i], y = b[j], z = c[k]; 43 | res = min( res, (LL)max( max(x, y), z ) - min( min(x, y), z ) ); 44 | 45 | if(x <= y && x <= z) 46 | i++; 47 | else if(y <= x && y <= z) 48 | j++; 49 | else 50 | k++; 51 | } 52 | 53 | cout << res * 2 << endl; 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_1_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/3/13. 3 | // 4 | // 1. 删除最小值的元素 5 | // 2. 返回最小值 6 | // 3. 最小值的地方用最后一个元素填补 7 | #include 8 | using namespace std; 9 | 10 | #define MaxSize 100 11 | 12 | typedef struct SqList { 13 | int a[MaxSize] = {1, 1, 4, 5, 1, 4, 0, 9, 1, 9, 8, 1, 10}; 14 | int length = 13; 15 | 16 | } SqList; 17 | 18 | 19 | // 处理过程 20 | void process(SqList & sqList) { 21 | int minx = sqList.a[0], index = 0; // 首先假设数组中的第一个元素是最小的元素,index用于记录最小值所在的数组下标 22 | for(int i = 0; i < sqList.length; ++i) { // 遍历顺序表 23 | if(sqList.a[i] < minx) { // 如果有元素比最小的元素还要小 24 | index = i; // 把这个元素的位置记录 25 | minx = sqList.a[i]; // 并且更新当前元素为最小值元素 26 | } 27 | } 28 | 29 | sqList.a[index] = sqList.a[sqList.length - 1]; // 将空出的位置由最后一个元素填补 30 | sqList.length -= 1; // 顺序表的长度减一 31 | } 32 | 33 | int main() { 34 | SqList sqList; 35 | if(sqList.length == 0) { 36 | cout << "error, the array is empty"; 37 | return 0; 38 | } 39 | 40 | cout << "原数组为:"; 41 | for(int i = 0; i < sqList.length; ++i) { 42 | cout << sqList.a[i] << " "; 43 | } 44 | cout << endl; 45 | 46 | process(sqList); 47 | 48 | cout << "现在的元素为:"; 49 | for(int i = 0; i < sqList.length; ++i) { 50 | cout << sqList.a[i] << " "; 51 | } 52 | cout << endl; 53 | return 0; 54 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_2_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/3/13. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | #define MaxSize 100 8 | typedef struct SqList{ 9 | int length = 13; 10 | int a[MaxSize] = {1, 1, 4, 5, 1, 4, 0, 9, 1, 9, 8, 1, 10}; 11 | } SqList; 12 | 13 | void swap(int & a, int & b) { 14 | int t = a; 15 | a = b; 16 | b = t; 17 | } 18 | 19 | void process(SqList & sqList) { 20 | int mid = sqList.length / 2; 21 | for(int i = 0; i < mid; ++i){ 22 | swap(sqList.a[i], sqList.a[sqList.length - i - 1]); 23 | } 24 | } 25 | 26 | int main() { 27 | SqList sqList; 28 | 29 | cout << "原数组为:"; 30 | for(int i = 0; i < sqList.length; ++i) { 31 | cout << sqList.a[i] << " "; 32 | } 33 | cout << endl; 34 | 35 | process(sqList); 36 | 37 | cout << "逆置后的数组为:"; 38 | for (int i = 0; i < sqList.length; ++i) { 39 | cout << sqList.a[i] << " "; 40 | } 41 | cout << endl; 42 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_3_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/3/16. 3 | // 4 | /** 5 | * 删除线性表中所有值为x的元素 6 | * 7 | * */ 8 | #include 9 | using namespace std; 10 | 11 | #define MAX 100 12 | 13 | typedef struct SqList { 14 | int a[MAX] = {1, 2, 4, 5, 6, 7, 7, 6, 5, 4, 2, 7}; 15 | int length = 12; 16 | }; 17 | 18 | void process(SqList & sqList, int x) { 19 | //往后面扫描的同时记录x的数量 20 | int count = 0; 21 | for(int i = 0; i < sqList.length; ++i) { 22 | if(sqList.a[i] == x) count++; //如果当前元素为x,将其跳过,并且记录count的个数 23 | else 24 | sqList.a[i - count] = sqList.a[i]; //如果不是x,就需要往前移动x的数量的位置 25 | } 26 | sqList.length -= count; //更新长度 27 | } 28 | 29 | int main() { 30 | SqList sqList; 31 | cout << "原数组为:"; 32 | for(int i = 0; i < sqList.length; ++i) { 33 | cout << sqList.a[i] << " "; 34 | } 35 | cout << endl; 36 | 37 | process(sqList, 6); 38 | 39 | cout << "删除x后的数组为:"; 40 | for(int i = 0; i < sqList.length; ++i) { 41 | cout << sqList.a[i] << " "; 42 | } 43 | cout << endl; 44 | return 0; 45 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/3/17. 3 | //从有序表中删除s到t之间的元素s 6 | using namespace std; 7 | #define MAX 100 8 | 9 | typedef struct SqList{ 10 | int a[MAX] = {1, 2, 3, 4, 5, 6, 7, 7, 7, 8, 8, 9, 10, 11}; 11 | int length = 14; 12 | } SqList; 13 | 14 | void process(SqList & sqList, int s, int t) { 15 | int count = 0; 16 | for(int i = 0; i < sqList.length; ++i) { 17 | if(sqList.a[i] > s && sqList.a[i] < t) { 18 | count ++; 19 | } else { 20 | sqList.a[i - count] = sqList.a[i]; 21 | } 22 | } 23 | sqList.length -= count; 24 | } 25 | 26 | int main() { 27 | SqList sqList; 28 | int s = 3, t = 5; 29 | if(s >= t || sqList.length == 0) { 30 | cout << "error" << endl; 31 | return 0; 32 | } 33 | cout << "原数组元素为:"; 34 | for(int i = 0; i < sqList.length; ++i) { 35 | cout << sqList.a[i] << " "; 36 | } 37 | cout << endl; 38 | 39 | process(sqList, s, t); 40 | 41 | cout << "处理后的数组为:"; 42 | for(int i = 0; i < sqList.length; ++i) { 43 | cout << sqList.a[i] << " "; 44 | } 45 | cout << endl; 46 | return 0; 47 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/3/17. 3 | // 从顺序表中删除s到t之间的元素 4 | 5 | // 6 | // Created by mach4101 on 2022/3/17. 7 | //从有序表中删除s到t之间的元素s 10 | using namespace std; 11 | #define MAX 100 12 | 13 | typedef struct SqList{ 14 | int a[MAX] = {1, 1, 4, 5, 1, 4, 1, 9, 1, 9, 8, 1, 0}; 15 | int length = 13; 16 | } SqList; 17 | 18 | void process(SqList & sqList, int s, int t) { 19 | int count = 0; 20 | for(int i = 0; i < sqList.length; ++i) { 21 | if(sqList.a[i] >= s && sqList.a[i] <= t) { 22 | count ++; 23 | } else { 24 | sqList.a[i - count] = sqList.a[i]; 25 | } 26 | } 27 | sqList.length -= count; 28 | } 29 | 30 | int main() { 31 | SqList sqList; 32 | int s = 3, t = 5; 33 | if(s >= t || sqList.length == 0) { 34 | cout << "error" << endl; 35 | return 0; 36 | } 37 | 38 | cout << "原数组元素为:"; 39 | for(int i = 0; i < sqList.length; ++i) { 40 | cout << sqList.a[i] << " "; 41 | } 42 | cout << endl; 43 | 44 | process(sqList, s, t); 45 | 46 | cout << "处理后的数组为:"; 47 | for(int i = 0; i < sqList.length; ++i) { 48 | cout << sqList.a[i] << " "; 49 | } 50 | cout << endl; 51 | return 0; 52 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_6_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/3/17. 3 | //从有序表中删除s到t之间的元素s 6 | using namespace std; 7 | #define MAX 100 8 | 9 | typedef struct SqList{ 10 | int a[MAX] = {1, 2, 3, 3,3, 5, 6, 7, 7, 7, 8, 8,9 ,9, 10, 11}; 11 | int length = 16; 12 | } SqList; 13 | 14 | void process(SqList & sqList) { 15 | int count = 1; 16 | for(int i = 1; i < sqList.length; ++i) { 17 | if(sqList.a[i] == sqList.a[i - count]) { //当前元素和前count个元素相同 18 | count++; 19 | } else { 20 | sqList.a[i - count + 1] = sqList.a[i]; 21 | } 22 | } 23 | sqList.length = sqList.length - count + 1; 24 | } 25 | 26 | int main() { 27 | SqList sqList; 28 | 29 | cout << "原数组元素为:"; 30 | for(int i = 0; i < sqList.length; ++i) { 31 | cout << sqList.a[i] << " "; 32 | } 33 | cout << endl; 34 | 35 | process(sqList); 36 | 37 | cout << "处理后的数组为:"; 38 | for(int i = 0; i < sqList.length; ++i) { 39 | cout << sqList.a[i] << " "; 40 | } 41 | cout << endl; 42 | return 0; 43 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_7.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.2.3_7.cpp 3 | * Create: 2022-05-25 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | typedef int ElemType; 11 | #define MAXSIZE 100 12 | #define ERROR 0 13 | #define OK 1 14 | 15 | typedef struct { 16 | ElemType *elem; 17 | int length; 18 | }SqList; 19 | 20 | int InitOrderList(SqList &L1, SqList &L2, SqList &L3) { 21 | L1.elem = new ElemType [MAXSIZE]; 22 | L2.elem = new ElemType [MAXSIZE]; 23 | L3.elem = new ElemType [MAXSIZE]; 24 | 25 | // 如果元素部分在初始化时有数据,就需要重新分配 26 | if (!L1.elem || !L2.elem || !L2.elem) return ERROR; 27 | 28 | return OK; 29 | } 30 | 31 | int DestroyOrderList(SqList &L1, SqList &L2, SqList &L3) { 32 | delete L1.elem; 33 | delete L2.elem; 34 | delete L3.elem; 35 | 36 | if (L1.elem || L2.elem || L3.elem) return ERROR; 37 | 38 | return OK; 39 | } 40 | 41 | int MergeOrderList(SqList &L1, SqList &L2, SqList &L3) { 42 | if (L1.length + L2.length > L3.length) return ERROR; 43 | 44 | int i = 0, j = 0, k = 0; 45 | 46 | // 从小到大进行排序 47 | while (i < L1.length && j < L2.length) { 48 | if (L1.elem[i] <= L2.elem[j]) L3.elem[k ++] = L1.elem[i ++]; 49 | else L3.elem[k ++] = L2.elem[j ++]; 50 | } 51 | 52 | // 将剩下的元素传入列表种 53 | while (i < L1.length) L3.elem[k ++] = L1.elem[i ++]; 54 | while (j < L2.length) L3.elem[k ++] = L1.elem[i ++]; 55 | 56 | L3.length = k; 57 | return OK; 58 | } 59 | 60 | int main() { 61 | 62 | SqList L1, L2, L3; 63 | InitOrderList(L1, L2, L3); 64 | 65 | L1.elem[0] = 3, L1.elem[1] = 5, L1.elem[2] = 7, L1.elem[3] = 9; 66 | L2.elem[0] = 2, L2.elem[1] = 4, L2.elem[2] = 6, L2.elem[3] = 8; 67 | 68 | MergeOrderList(L1, L2, L3); 69 | 70 | for (int i = 0; i < L3.length; ++ i) cout << L3.elem[i]; 71 | 72 | DestroyOrderList(L1, L2, L3); 73 | return 0; 74 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_7_mach4101.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define MAX 100 4 | 5 | typedef struct SqList{ 6 | int a[MAX]; 7 | int length; 8 | } SqList; 9 | 10 | // 合并sqList1与sqList2,然后将合并后的结果返回 11 | SqList process(SqList sqList1, SqList sqList2) { 12 | SqList sqList3; 13 | int i = 0, j = 0, cur = 0; //i为sqList1的索引,j为sqList2的索引,cur为sqList3的索引 14 | while(i < sqList1.length && j < sqList2.length) { //如果i和j都没有越界 15 | if(sqList1.a[i] < sqList2.a[j]) { //比较两个表的元素,开始进行二路归并,谁小就先保存谁 16 | sqList3.a[cur++] = sqList1.a[i++]; //归并之后指针后移 17 | } else { 18 | sqList3.a[cur++] = sqList2.a[j++]; 19 | } 20 | } 21 | 22 | while(i < sqList1.length) { //若j已经到头了,i还没有到头,说明sqList1中的元素还没有归并到sqList3中 23 | sqList3.a[cur++] = sqList1.a[i++]; 24 | } 25 | 26 | while(j < sqList2.length) { //也有可能出现i已经到头了,但是j还没有到头 27 | sqList3.a[cur++] = sqList2.a[j++]; 28 | } 29 | 30 | sqList3.length = cur; //更新顺序表长度 31 | return sqList3; //返回表 32 | } 33 | 34 | 35 | int main() { 36 | SqList sqList1, sqList2; 37 | for(int i = 0; i < 5; ++i) { 38 | sqList1.a[i] = i; 39 | } 40 | sqList1.length = 5; 41 | 42 | for(int i = 0; i < 5; ++i) { 43 | sqList2.a[i] = i + 5; 44 | } 45 | sqList2.length = 5; 46 | 47 | SqList sqList3; 48 | sqList3 = process(sqList1, sqList2); 49 | 50 | cout << "处理后的数组为:"; 51 | for(int i = 0; i < sqList3.length; ++i) { 52 | cout << sqList3.a[i] << " "; 53 | } 54 | cout << endl; 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.2.3_8.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.2.3_8.cpp 3 | * Create: 2022-05-25 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | #define MaxSize 100 11 | 12 | //已知在一维数组A[m+n]中依次存放两个线性表(a1-am),(b1-bm)。将数组中两个顺序表位置互换 13 | 14 | //三次逆置,整体逆置,两次内部逆置 15 | void reverse(int A[], int left, int right, int arraySize) { 16 | if(left >= right || right >= arraySize) return; 17 | 18 | int mid = (left + right) / 2; 19 | for(int i = 0; i <= mid - left; i ++) {//上限错了 20 | int tmp = A[left + i]; // 首部放入寄存器 21 | A[left + i] = A[right - i]; // 尾部放入首部 22 | A[right - i] = tmp; // 首部数据放入尾部 23 | } 24 | } 25 | 26 | //控制三次逆置 27 | void Exchange(int A[], int m, int n, int arraySize) { 28 | reverse(A,0,m + n - 1, arraySize); 29 | reverse(A,0,n - 1, arraySize); 30 | reverse(A,n,m + n - 1, arraySize); 31 | } 32 | 33 | int main() { 34 | int m, n;//分别代表两个线性表A,B的长度 35 | int A[MaxSize]; 36 | cout << "请输入线性表A和线性表B的长度:"; 37 | cin >> m >> n; 38 | 39 | cout << "请输入线性表A的值:"; 40 | for (int i=0;i> A[i]; 41 | 42 | cout << "请输入线性表B的值:"; 43 | 44 | for(int i=m;i> A[i]; 45 | cout << "数组为:" << endl; 46 | 47 | for(int i=0;i 7 | using namespace std; 8 | 9 | typedef int ElemType; 10 | 11 | void SearchExchangeInsert(ElemType A[], ElemType x, int n) { 12 | 13 | // 二分查找 14 | int low = 0, high = n - 1, mid; 15 | while (low <= high) { 16 | mid = (low + high) / 2; 17 | if (A[mid] == x) break; 18 | else if(A[mid] < x) low = mid + 1; 19 | else high = mid - 1; 20 | } 21 | // 查找到数据,并且坐标不在最后一位 22 | if (A[mid] == x && mid != n - 1) { 23 | int t = A[mid]; 24 | A[mid] = A[mid + 1]; 25 | A[mid + 1] = t; 26 | } 27 | 28 | // 如果查找失败,插入元素x 29 | if (low > high) { 30 | int i; 31 | for (i = n - 1; i > high; -- i) A[i + 1] = A[i]; // 插入数据之后会把最后一位数据丢弃,可以提前设置一个MAXSIZE 32 | A[i + 1] = x; 33 | } 34 | } 35 | 36 | int main() { 37 | int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 38 | 39 | SearchExchangeInsert(A, 0, 10); 40 | 41 | for (int m : A) { 42 | printf("%d ", m); 43 | } 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.3.3_8_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/3. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | #define MAX 100 8 | 9 | typedef struct SqList{ 10 | int a[MAX] = {1, 2, 3, 4, 5, 6, 10, 11, 12}; 11 | int length = 9; 12 | } SqList; 13 | 14 | void swap(int & a, int & b) { 15 | int t = a; 16 | a = b; 17 | b = t; 18 | } 19 | 20 | void reverse(SqList & sqList, int start, int end) { //逆置start到end这一段区间的顺序表 21 | int mid = (end + start) / 2; 22 | for (int i = start; i < mid; ++i) { 23 | swap(sqList.a[i], sqList.a[end - i + start]); 24 | } 25 | } 26 | 27 | //将sqList中的前m个元素与后n个元素互换位置, start和end表示要逆置的顺序表的下标区间 28 | void process(SqList & sqList, int m, int n) { 29 | //先将整个表逆置,然后将前n个元素逆置,再将后m个元素逆置 30 | reverse(sqList, 0, sqList.length - 1); 31 | reverse(sqList, 0, n - 1); 32 | reverse(sqList, n, m + n - 1); 33 | } 34 | 35 | void print(SqList sqlist){ 36 | for (int i = 0; i < sqlist.length; ++i) { 37 | cout << sqlist.a[i] << " "; 38 | } 39 | cout << endl; 40 | } 41 | 42 | int main() { 43 | SqList sqList; 44 | 45 | cout << "处理前的数组为:"; 46 | print(sqList); 47 | 48 | process(sqList, 6, 3); 49 | 50 | cout << "处理后的数组为:"; 51 | print(sqList); 52 | return 0; 53 | } -------------------------------------------------------------------------------- /chapter_2/2.2.3/2.3.3_9_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/3. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | #define MAX 100 8 | 9 | typedef struct SqList{ 10 | int a[MAX] = {1, 2, 3, 4, 5, 6, 10, 11, 12}; 11 | int length = 9; 12 | } SqList; 13 | 14 | void process(SqList & sqList, int x) { 15 | int index; 16 | 17 | for(int i = 0; i < sqList.length; ++i) { 18 | if(sqList.a[i] == x) { //若找到 19 | swap(sqList.a[i], sqList.a[i + 1]); 20 | return; 21 | } 22 | 23 | if(sqList.a[i] > x) { //已经比x大了,说明没有找到 24 | //从尾部开始往右挪动一个单元,留出位置插入x 25 | for(int j = sqList.length - 1; j >= i; --j) { 26 | sqList.a[j + 1] = sqList.a[j]; 27 | } 28 | sqList.a[i] = x; 29 | sqList.length ++; 30 | return; 31 | } 32 | } 33 | } 34 | 35 | void print(SqList sqList){ 36 | for (int i = 0; i < sqList.length; ++i) { 37 | cout << sqList.a[i] << " "; 38 | } 39 | cout << endl; 40 | } 41 | 42 | int main() { 43 | SqList sqList; 44 | 45 | cout << "处理前的数组为:"; 46 | print(sqList); 47 | 48 | process(sqList, 7); 49 | 50 | cout << "处理后的数组为:"; 51 | print(sqList); 52 | 53 | process(sqList, 6); 54 | 55 | cout << "处理后的数组为:"; 56 | print(sqList); 57 | return 0; 58 | } -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_1.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.3.7_1.cpp 3 | * Create: 2022-06-01 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | typedef struct SqNode{ 11 | int data; 12 | struct SqNode* next; 13 | }SqNode, *SqList; 14 | 15 | SqList CreateList(SqList L) { 16 | L = (SqList) malloc(sizeof (SqNode)); 17 | SqList s; // 创建节点 18 | SqList r; // 创建链表 19 | 20 | int val = 0; 21 | printf("请输入您需要创建的链表(最多1000个)\n"); 22 | scanf("%d", &val); 23 | getchar(); 24 | 25 | while (val != 1000) { 26 | s = (SqList) malloc(sizeof (SqNode)); 27 | s->data = val; 28 | s->next = r->next; 29 | r->next = s; 30 | r = s; 31 | scanf("%d", &val); 32 | getchar(); 33 | } 34 | } 35 | 36 | // 递归删除 37 | SqList DeleteElement(SqList *L, int val) { 38 | SqList s; 39 | 40 | if (*L == nullptr) return nullptr; 41 | 42 | if ((*L)->data == val) { 43 | s = *L; 44 | *L = (*L)->next; 45 | free(s); 46 | DeleteElement(L, val); 47 | } else { 48 | DeleteElement(&((*L)->next), val); 49 | } 50 | } 51 | 52 | void PrintList(SqList L) { 53 | SqList s; 54 | s = L; 55 | while (s != nullptr) { 56 | printf("%d\n", s->data); 57 | s = s->next; 58 | } 59 | printf("\n"); 60 | } 61 | 62 | int main() { 63 | SqList L = nullptr; 64 | L = CreateList(L); 65 | PrintList(L); 66 | DeleteElement(&L, 3); 67 | PrintList(L); 68 | } 69 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_10_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/7. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[5] = {3, 2, 1, 4, 5}; 14 | int b[5] = {0, 1, 2, 3, 4}; 15 | int c[5] = {5, 4, 3, 2, 1}; 16 | 17 | void Build(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 5; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Print(LinkedList L) { 33 | LinkedList p = L -> next; 34 | while(p) { 35 | cout << p -> data << " "; 36 | p = p -> next; 37 | } 38 | 39 | cout << endl; 40 | } 41 | 42 | LinkedList SplitLinkedList(LinkedList & L, LinkedList & A, LinkedList & B) { 43 | LinkedList p = L -> next, a_ptr = A, b_ptr = B; // 定义p指向L的第一个节点,a_ptr指向A链表的头节点,b_ptr指向B链表的头节点 44 | 45 | // 为了在插入的过程中保持原数组中的次序,因此不能使用头插法,只能用尾插法,定义尾指针 46 | LinkedList a_tail = A, b_tail = B; 47 | 48 | L -> next = NULL; 49 | int i = 1; 50 | 51 | while(p) { 52 | if(i % 2 == 1) { // 将p节点从链表上摘下,然后插入到A中 53 | LinkedList q = p -> next; // q为临时指针,防止断链 54 | a_tail -> next = p; // 将p接在A链表的尾部 55 | p -> next = NULL; // 尾部元素指针域设置为空 56 | a_tail = p; // 由于插入了新元素,因此需要更新尾指针 57 | p = q; // p重新接回来 58 | } else { // 插入到B链表中 59 | LinkedList q = p -> next; // q为临时指针,防止断链 60 | b_tail -> next = p; // 将p接在B链表的尾部 61 | p -> next = NULL; // 尾部元素指针域设置为空 62 | b_tail = p; // 由于插入了新元素,因此需要更新尾指针 63 | p = q; // p重新接回来 64 | } 65 | i ++; 66 | } 67 | } 68 | 69 | 70 | int main(){ 71 | LinkedList L; 72 | 73 | // 将两个带头节点的链表准备好,然后将L拆分成A和B 74 | LinkedList A, B; 75 | A = (LinkedList) malloc (sizeof (Node)); 76 | A -> next = NULL; 77 | B = (LinkedList) malloc(sizeof (Node)); 78 | B -> next = NULL; 79 | 80 | 81 | Build(L); 82 | Print(L); 83 | SplitLinkedList(L, A, B); 84 | Print(A); 85 | Print(B); 86 | return 0; 87 | }; 88 | 89 | 90 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_11_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/7. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[10] = {1, 5,2, 4,3, 3,4, 2,5, 1}; 14 | int b[5] = {0, 1, 2, 3, 4}; 15 | int c[5] = {5, 4, 3, 2, 1}; 16 | 17 | void Build(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 10; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Print(LinkedList L) { 33 | LinkedList p = L -> next; 34 | while(p) { 35 | cout << p -> data << " "; 36 | p = p -> next; 37 | } 38 | 39 | cout << endl; 40 | } 41 | 42 | LinkedList SplitLinkedList_version2(LinkedList & L, LinkedList & A, LinkedList & B) { 43 | LinkedList p = L -> next; // 定义p指向L的第一个节点,a_ptr指向A链表的头节点,b_ptr指向B链表的头节点 44 | 45 | // A要保持原来的顺序,因此A使用尾插法,而b的顺序与原来的正好相反,因此可以使用头插法 46 | LinkedList a_tail = A, b_ptr = B; // a_tail定义为指向A的尾部,b_ptr定义为指向b的头部 47 | 48 | L -> next = NULL; 49 | int i = 1; 50 | 51 | while(p) { 52 | if(i % 2 == 1) { // 将p节点从链表上摘下,然后插入到A中 53 | LinkedList q = p -> next; // q为临时指针,防止断链 54 | a_tail -> next = p; // 将p接在A链表的尾部 55 | p -> next = NULL; // 尾部元素指针域设置为空 56 | a_tail = p; // 由于插入了新元素,因此需要更新尾指针 57 | p = q; // p重新接回来 58 | } else { // 插入到B链表中 59 | LinkedList q = p -> next; // q为临时指针,防止断链 60 | p -> next = b_ptr -> next; // 下面两个语句即为头插法 61 | b_ptr -> next = p; 62 | p = q; // p重新接回来 63 | } 64 | i ++; 65 | } 66 | } 67 | 68 | 69 | int main(){ 70 | LinkedList L; 71 | 72 | // 将两个带头节点的链表准备好,然后将L拆分成A和B 73 | LinkedList A, B; 74 | A = (LinkedList) malloc (sizeof (Node)); 75 | A -> next = NULL; 76 | B = (LinkedList) malloc(sizeof (Node)); 77 | B -> next = NULL; 78 | 79 | 80 | Build(L); 81 | Print(L); 82 | SplitLinkedList_version2(L, A, B); 83 | Print(A); 84 | Print(B); 85 | return 0; 86 | }; 87 | 88 | 89 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_12_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/7. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[10] = {7, 10, 10, 21, 30, 42, 42, 42, 51, 70}; 14 | int b[5] = {0, 1, 2, 3, 4}; 15 | int c[5] = {5, 4, 3, 2, 1}; 16 | 17 | void Build(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 10; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Print(LinkedList L) { 33 | LinkedList p = L -> next; 34 | while(p) { 35 | cout << p -> data << " "; 36 | p = p -> next; 37 | } 38 | 39 | cout << endl; 40 | } 41 | 42 | // 唯一化:由于链表有序,因此重复元素会扎堆,如果一个元素与它后面的元素重复,那么就删除掉后面的元素 43 | LinkedList Unique(LinkedList & L) { 44 | LinkedList p = L -> next; 45 | 46 | while(p -> next) { //看看存不存在下一个元素 47 | if(p -> data == p -> next -> data) { // 若相同,删掉后面的 48 | LinkedList q = p -> next; 49 | p -> next = p -> next -> next; 50 | free(q); 51 | } else { 52 | p = p -> next; 53 | } 54 | } 55 | } 56 | 57 | 58 | int main(){ 59 | LinkedList L; 60 | Build(L); 61 | Print(L); 62 | Unique(L); 63 | Print(L); 64 | return 0; 65 | }; 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_13_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/7. 3 | // 4 | 5 | 6 | #include 7 | using namespace std; 8 | 9 | typedef struct Node { 10 | struct Node * next; 11 | int data; 12 | } Node, * LinkedList; 13 | 14 | int a[7] = {1, 1, 4, 5, 8, 9, 10}; 15 | int b[5] = {0, 1, 2, 3, 4}; 16 | int c[5] = {5, 4, 3, 2, 1}; 17 | 18 | void Build1(LinkedList & L) { 19 | LinkedList s, r; 20 | s = (LinkedList) malloc(sizeof(Node)); 21 | L = s; 22 | r = L; 23 | r -> next = NULL; 24 | for(int i = 0; i < 7; ++i) { 25 | s = (LinkedList) malloc (sizeof(Node)); 26 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 27 | r -> next = s; 28 | r = s; 29 | } 30 | r -> next = NULL; 31 | } 32 | 33 | void Build2(LinkedList & L) { 34 | LinkedList s, r; 35 | s = (LinkedList) malloc(sizeof(Node)); 36 | L = s; 37 | r = L; 38 | r -> next = NULL; 39 | for(int i = 0; i < 5; ++i) { 40 | s = (LinkedList) malloc (sizeof(Node)); 41 | s -> data = b[i]; //测试数组a,b,c只需改这个地方即可 42 | r -> next = s; 43 | r = s; 44 | } 45 | r -> next = NULL; 46 | } 47 | 48 | void Print(LinkedList L) { 49 | LinkedList p = L -> next; 50 | while(p) { 51 | cout << p -> data << " "; 52 | p = p -> next; 53 | } 54 | 55 | cout << endl; 56 | } 57 | 58 | // 二路归并链表版,将两个表合并起来,变成新的L1 59 | void MergeList(LinkedList & L1, LinkedList & L2) { 60 | LinkedList p1 = L1 -> next, p2 = L2 -> next; 61 | L1 -> next = NULL; 62 | while(p1 && p2) { // 前提是p1和p2不为空 63 | if(p1 -> data <= p2 -> data) { // 小的先来 64 | 65 | LinkedList q = p1 -> next; // 防止断链,用q记录下p1的下一个元素 66 | p1 -> next = L1 -> next; // p1摘下来,插入到L1的后面,因为题目要求逆序,所以用头插法 67 | L1 -> next = p1; // L1把p链上去 68 | p1 = q; // 恢复p的位置 69 | } else { 70 | LinkedList q = p2 -> next; // 与上面的逻辑一样 71 | p2 -> next = L1 -> next; 72 | L1 -> next = p2; 73 | p2 = q; 74 | } 75 | } 76 | 77 | // 若p1后面还有,那么将p1后面的元素一起接过去 78 | while(p1) { 79 | LinkedList q = p1 -> next; 80 | p1 -> next = L1 -> next; 81 | L1 -> next = p1; 82 | p1 = q; 83 | } 84 | 85 | while(p2) { 86 | LinkedList q = p2 -> next; 87 | p2 -> next = L1 -> next; 88 | L1 -> next = p2; 89 | p2 = q; 90 | } 91 | } 92 | 93 | 94 | int main(){ 95 | LinkedList L1, L2; 96 | Build1(L1); 97 | Build2(L2); 98 | Print(L1); 99 | Print(L2); 100 | MergeList(L1, L2); // 将L1和L2归并,接到L1上 101 | Print(L1); 102 | return 0; 103 | }; 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_14_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/7. 3 | // 4 | 5 | 6 | #include 7 | using namespace std; 8 | 9 | typedef struct Node { 10 | struct Node * next; 11 | int data; 12 | } Node, * LinkedList; 13 | 14 | int a[7] = {1, 1, 4, 5, 8, 9, 10}; 15 | int b[5] = {0, 1, 2, 3, 4}; 16 | int c[5] = {5, 4, 3, 2, 1}; 17 | 18 | void Build1(LinkedList & L) { 19 | LinkedList s, r; 20 | s = (LinkedList) malloc(sizeof(Node)); 21 | L = s; 22 | r = L; 23 | r -> next = NULL; 24 | for(int i = 0; i < 7; ++i) { 25 | s = (LinkedList) malloc (sizeof(Node)); 26 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 27 | r -> next = s; 28 | r = s; 29 | } 30 | r -> next = NULL; 31 | } 32 | 33 | void Build2(LinkedList & L) { 34 | LinkedList s, r; 35 | s = (LinkedList) malloc(sizeof(Node)); 36 | L = s; 37 | r = L; 38 | r -> next = NULL; 39 | for(int i = 0; i < 5; ++i) { 40 | s = (LinkedList) malloc (sizeof(Node)); 41 | s -> data = b[i]; //测试数组a,b,c只需改这个地方即可 42 | r -> next = s; 43 | r = s; 44 | } 45 | r -> next = NULL; 46 | } 47 | 48 | void Print(LinkedList L) { 49 | LinkedList p = L -> next; 50 | while(p) { 51 | cout << p -> data << " "; 52 | p = p -> next; 53 | } 54 | 55 | cout << endl; 56 | } 57 | 58 | // 由于两个链表都有序,因此可以使用两个指针分别指向两个链表的表头,谁小谁就往后走,若发现有公共元素,则在L3中插入新节点 59 | void FindCommon(LinkedList & L1, LinkedList & L2, LinkedList & L3) { 60 | LinkedList p1 = L1 -> next, p2 = L2 -> next; 61 | LinkedList r = L3; // r是L3的尾指针 62 | while(p1 && p2) { // 若都不空 63 | if(p1 -> data < p2 -> data) // 谁小往后挪谁 64 | p1 = p1 -> next; 65 | else if(p1 -> data > p2 -> data) 66 | p2 = p2 -> next; 67 | else { // 若相同,说明是公共节点 68 | LinkedList s = (LinkedList) malloc (sizeof(Node)); 69 | s -> data = p1 -> data; 70 | r -> next = s; // 将s挂到r后面 71 | s -> next = NULL; // 尾部元素指针域设置为空 72 | r = s; // 更新尾指针 73 | p1 = p1 -> next; // 一起往后跳 74 | p2 = p2 -> next; 75 | } 76 | } 77 | r -> next = NULL; 78 | } 79 | 80 | 81 | int main(){ 82 | LinkedList L1, L2; 83 | Build1(L1); 84 | Build2(L2); 85 | Print(L1); 86 | Print(L2); 87 | 88 | LinkedList L3; 89 | //给L3弄个头 90 | L3 = (LinkedList) malloc(sizeof(Node)); 91 | L3 -> next = NULL; 92 | 93 | FindCommon(L1, L2, L3); // 将L1和L2归并,接到L1上 94 | Print(L3); 95 | return 0; 96 | }; 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_15_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/8. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[7] = {1, 1, 4, 5, 8, 9, 10}; 14 | int b[5] = {0, 1, 2, 3, 4}; 15 | int c[5] = {5, 4, 3, 2, 1}; 16 | 17 | void Build1(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 7; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Build2(LinkedList & L) { 33 | LinkedList s, r; 34 | s = (LinkedList) malloc(sizeof(Node)); 35 | L = s; 36 | r = L; 37 | r -> next = NULL; 38 | for(int i = 0; i < 5; ++i) { 39 | s = (LinkedList) malloc (sizeof(Node)); 40 | s -> data = b[i]; //测试数组a,b,c只需改这个地方即可 41 | r -> next = s; 42 | r = s; 43 | } 44 | r -> next = NULL; 45 | } 46 | 47 | void Print(LinkedList L) { 48 | LinkedList p = L -> next; 49 | while(p) { 50 | cout << p -> data << " "; 51 | p = p -> next; 52 | } 53 | 54 | cout << endl; 55 | } 56 | 57 | // 由于两个链表都有序,因此可以使用两个指针分别指向两个链表的表头,谁小谁就往后走,若发现有公共元素,则在L3中插入新节点 58 | void FindCommon(LinkedList & L1, LinkedList & L2) { 59 | LinkedList p1 = L1 -> next, p2 = L2 -> next, r = L1; 60 | 61 | while(p1 && p2) { 62 | if(p1 -> data < p2 -> data) { //若不是交集 63 | LinkedList q = p1 -> next; 64 | free(p1); 65 | p1 = q; 66 | } else if(p1 -> data > p2 -> data) { // 不是交集 67 | LinkedList q = p2 -> next; 68 | free(p2); 69 | p2 = q; 70 | } else { 71 | r -> next = p1; 72 | r = p1; 73 | p1 = p1 -> next; 74 | LinkedList q = p2; 75 | p2 = p2 -> next; 76 | free(q); 77 | } 78 | } 79 | 80 | while(p1) { 81 | LinkedList q = p1 -> next; 82 | free(p1); 83 | p1 = q; 84 | } 85 | 86 | while(p2) { 87 | LinkedList q = p2 -> next; 88 | free(p2); 89 | p2 = q; 90 | } 91 | 92 | r -> next = NULL; 93 | free(L2); 94 | } 95 | 96 | 97 | int main(){ 98 | LinkedList L1, L2; 99 | Build1(L1); 100 | Build2(L2); 101 | Print(L1); 102 | Print(L2); 103 | 104 | FindCommon(L1, L2); // 求L1和L2的交集 105 | Print(L1); 106 | return 0; 107 | }; 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_16_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/17. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[7] = {1, 1, 4, 5, 8, 9, 10}; 14 | int b[4] = {4, 5, 8, 9}; 15 | int c[5] = {1, 2, 3, 4}; 16 | 17 | void Build1(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 7; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Build2(LinkedList & L) { 33 | LinkedList s, r; 34 | s = (LinkedList) malloc(sizeof(Node)); 35 | L = s; 36 | r = L; 37 | r -> next = NULL; 38 | for(int i = 0; i < 4; ++i) { 39 | s = (LinkedList) malloc (sizeof(Node)); 40 | s -> data = b[i]; //测试数组a,b,c只需改这个地方即可 41 | r -> next = s; 42 | r = s; 43 | } 44 | r -> next = NULL; 45 | } 46 | 47 | void Print(LinkedList L) { 48 | LinkedList p = L -> next; 49 | while(p) { 50 | cout << p -> data << " "; 51 | p = p -> next; 52 | } 53 | 54 | cout << endl; 55 | } 56 | 57 | bool check(LinkedList L1, LinkedList L2) { 58 | LinkedList p1 = L1 -> next, p2 = L2 -> next; 59 | while(p1) { 60 | LinkedList q = p1; // 记录p1目前所在的位置 61 | while(p1 && p2 && p1 -> data == p2 -> data) { // 若p1 p2为扫描完并且有相同的元素,则一起往后跳 62 | p1 = p1 -> next; 63 | p2 = p2 -> next; 64 | } 65 | 66 | if(p2 == NULL) //如果p2扫描完了,则说明是L1中连续的序列 67 | return true; 68 | p1 = q -> next; // 否则的话就把p1 往后面跳一格 69 | p2 = L2 -> next; // p2归位到首节点 70 | } 71 | return false; // 如果在整个遍历过程中都没有发现有相同的序列,那么返回false 72 | } 73 | 74 | int main(){ 75 | LinkedList L1, L2; 76 | Build1(L1); 77 | Build2(L2); 78 | Print(L1); 79 | Print(L2); 80 | 81 | 82 | if(check(L1, L2)) { // 求L1和L2的交集 83 | cout << "是连续的子序列" << endl; 84 | } else { 85 | cout << "不是连续的子序列" << endl; 86 | } 87 | return 0; 88 | }; 89 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_1_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/3. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node{ 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | 14 | //使用尾插法建立一个链表, 建立的链表依次从1到n 15 | void Build(LinkedList & L, int n) { 16 | LinkedList s, r = L; 17 | //给首节点赋值 18 | r -> data = 1; 19 | //若只有一个节点,那就只需要首节点即可,将首节点的指针域设置为NULL 20 | if (n == 1) { 21 | r -> next = NULL; 22 | return; 23 | } 24 | 25 | //否则就需要使用malloc或者new关键字来动态创建剩余节点,并使用尾插法,尾插法的好处是可以保持顺序,而不是像头插法那样为逆序 26 | for(int i = 2; i <= n; ++i) { 27 | s = (LinkedList)malloc(sizeof(Node)); 28 | s -> data = i; 29 | r -> next = s; 30 | r = s; 31 | } 32 | r -> next = NULL; 33 | } 34 | 35 | // 输出链表 36 | void Print(LinkedList L) { 37 | LinkedList p = L; 38 | while(p) { 39 | cout << p -> data << " "; 40 | p = p -> next; 41 | } 42 | cout << endl; 43 | } 44 | 45 | // 使用递归的方法删除链表中所有值为x的结点(recursive是递归的意思) 46 | void DEL_X_Recursive(LinkedList & L, int x) { 47 | if(L == NULL) 48 | return; 49 | if(L -> data == x) { 50 | LinkedList p = L; 51 | L = L -> next; 52 | free(p); 53 | DEL_X_Recursive(L, x); 54 | } 55 | else 56 | DEL_X_Recursive(L -> next, x); 57 | 58 | } 59 | 60 | int main(){ 61 | Node s; 62 | LinkedList L = &s; 63 | Build(L, 5); 64 | cout << "处理前的链表元素:"; 65 | Print(L); 66 | DEL_X_Recursive(L, 3); 67 | cout << "处理后的链表元素:"; 68 | Print(L); 69 | } 70 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_2.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.3.7_2.cpp 3 | * Create: 2022-06-01 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | typedef int ElemType; 11 | 12 | typedef struct SqNode { 13 | int data; 14 | struct SqNode* next; 15 | }SqNode, *SqList; 16 | 17 | SqList CreateList(SqList L) { 18 | L = (SqList) malloc(sizeof (SqNode)); 19 | SqList s; // 创建节点 20 | SqList r; // 创建链表 21 | 22 | int val = 0; 23 | printf("请输入您需要创建的链表(最多1000个)\n"); 24 | scanf("%d", &val); 25 | getchar(); 26 | 27 | while (val != 1000) { 28 | s = (SqList) malloc(sizeof (SqNode)); 29 | s->data = val; 30 | s->next = r->next; 31 | r->next = s; 32 | r = s; 33 | scanf("%d", &val); 34 | getchar(); 35 | } 36 | } 37 | 38 | void DeleteElement(SqList &L, ElemType x) { 39 | while(L != nullptr && L->next != nullptr) { 40 | if (L->next->data == x) { 41 | SqNode *temp = L->next; 42 | if (L->next->next != nullptr) { 43 | L->next = L->next->next; 44 | } else { 45 | L->next = nullptr; 46 | } 47 | free(temp); 48 | } else { 49 | L = L->next; 50 | } 51 | } 52 | } 53 | 54 | void PrintList(SqList L) { 55 | SqList s; 56 | s = L; 57 | while (s != nullptr) { 58 | printf("%d\n", s->data); 59 | s = s->next; 60 | } 61 | printf("\n"); 62 | } 63 | 64 | int main() { 65 | SqList L = nullptr; 66 | L = CreateList(L); 67 | PrintList(L); 68 | DeleteElement(L, 3); 69 | PrintList(L); 70 | return 0; 71 | } -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_2_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/3. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[5] = {1, 2, 2, 3, 2}; 14 | 15 | //尾插法建立链表 16 | void Build(LinkedList &L, int n) { 17 | L = (LinkedList) malloc (sizeof (Node)); //头节点 18 | 19 | LinkedList s, r = L; 20 | for(int i = 0; i < n; ++i) { 21 | s = (LinkedList) malloc (sizeof (Node)); 22 | s -> data = a[i]; 23 | r -> next = s; 24 | r = s; 25 | } 26 | r -> next = NULL; 27 | } 28 | 29 | void Print(LinkedList L) { 30 | LinkedList p = L -> next; 31 | while(p) { 32 | cout << p -> data << " "; 33 | p = p -> next; 34 | } 35 | cout << endl; 36 | } 37 | 38 | void DEL_X_Normal(LinkedList & L, int x){ 39 | LinkedList p = L; // 让p指向头节点 40 | while(p -> next) { // 然后观察p的下一个节点是否为x 41 | if(p -> next -> data == x) { //如果是 42 | LinkedList q = p -> next; //将p -> next删除 43 | p -> next = p -> next -> next; 44 | free(q); 45 | } else { 46 | p = p->next; //若不是则p指向下一个 47 | } 48 | } 49 | } 50 | 51 | int main() { 52 | LinkedList L; 53 | Build(L, 5); 54 | cout << "处理前的链表元素:"; 55 | Print(L); 56 | DEL_X_Normal(L, 2); 57 | cout << "处理后的链表元素:"; 58 | Print(L); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_3.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.3.7_3.cpp 3 | * Create: 2022-06-01 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | typedef int ElemType; 11 | 12 | typedef struct SqNode { 13 | int data; 14 | struct SqNode* next; 15 | }SqNode, *SqList; 16 | 17 | SqList CreateList(SqList L) { 18 | L = (SqList) malloc(sizeof (SqNode)); 19 | SqList s; // 创建节点 20 | SqList r; // 创建链表 21 | 22 | int val = 0; 23 | printf("请输入您需要创建的链表(最多1000个)\n"); 24 | scanf("%d", &val); 25 | getchar(); 26 | 27 | while (val != 1000) { 28 | s = (SqList) malloc(sizeof (SqNode)); 29 | s->data = val; 30 | s->next = r->next; 31 | r->next = s; 32 | r = s; 33 | scanf("%d", &val); 34 | getchar(); 35 | } 36 | } 37 | 38 | //从链表头部开始遍历,利用头插法生成新链表,再遍历输出新链表的值即可。 39 | SqList headInsert(SqList &head, ElemType value) {//该方法默认链表带有头节点 40 | SqNode temp = *(SqNode*)malloc(sizeof(SqNode)); 41 | temp.data = value; 42 | temp.next = head->next; 43 | head->next = &temp; 44 | } 45 | 46 | //利用递归实现。 47 | void printReverse(SqList &L) { 48 | if (L->next != nullptr) { 49 | printReverse(L->next); //递归到链表尾部,出栈 50 | } 51 | if (L != nullptr) { 52 | cout << L->data; //输出结果 53 | } 54 | } 55 | 56 | int main() { 57 | SqList L = nullptr; 58 | L = CreateList(L); 59 | printReverse(L); 60 | return 0; 61 | } -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_3_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/3. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[5] = {1, 2, 3, 4, 5}; 14 | 15 | //尾插法建立链表 16 | void Build(LinkedList &L, int n) { 17 | L = (LinkedList) malloc (sizeof (Node)); //头节点 18 | 19 | LinkedList s, r = L; 20 | for(int i = 0; i < n; ++i) { 21 | s = (LinkedList) malloc (sizeof (Node)); 22 | s -> data = a[i]; 23 | r -> next = s; 24 | r = s; 25 | } 26 | r -> next = NULL; 27 | } 28 | 29 | void Print(LinkedList L) { 30 | LinkedList p = L -> next; 31 | while(p) { 32 | cout << p -> data << " "; 33 | p = p -> next; 34 | } 35 | cout << endl; 36 | } 37 | 38 | void TraverseReverse(LinkedList L){ 39 | if(L -> next != NULL) 40 | TraverseReverse(L -> next); 41 | cout << L -> data << " "; 42 | } 43 | 44 | int main() { 45 | LinkedList L; 46 | Build(L, 5); 47 | cout << "处理前的链表元素:"; 48 | Print(L); 49 | TraverseReverse(L -> next); 50 | } -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_4.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.3.7_4.cpp 3 | * Create: 2022-06-06 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | typedef int ElemType; 11 | typedef struct LNode { 12 | ElemType data; 13 | LNode *next; 14 | } LNode, *LinkList; 15 | 16 | void init_list(LinkList &L) { 17 | L = (LinkList) malloc(sizeof (LNode)); // 产生头节点,并使指向此节点 18 | if (!L) return ; // 存储分配失败 19 | L->next = nullptr; // 头节点为空 20 | } 21 | 22 | // 前插法 23 | void create_list(LinkList &L, int n) { 24 | 25 | L = (LinkList) malloc(sizeof (LNode)); 26 | L->next = nullptr; 27 | printf("输入%d个数字", n); 28 | 29 | for (int i = n; i > 0; i --) { 30 | auto p = (LinkList) malloc(sizeof (LNode)); 31 | scanf("%d", &p->data); 32 | p->next = L->next; 33 | L->next = p; 34 | } 35 | } 36 | 37 | LinkList delete_min(LinkList &L) { 38 | // L是带头节点的单链表、该函数是删除其中最小值的节点 39 | LNode* pre = L; 40 | LNode* p = pre->next; //p 为工作指针,pre 指向其前驱 41 | LNode *min_pre = pre, *min_p = p; //保存最小值结点及其前驱 42 | 43 | while (p != nullptr) { 44 | if (p->data < min_p->data) { 45 | min_p = p; //找到比之前找到的最小值结点更小的结点 46 | min_pre = pre; 47 | } 48 | pre = p; //继续扫描下一个结点 49 | p = p->next; 50 | } 51 | 52 | min_pre->next = min_p->next; //删除最小值结点 53 | free(min_p); 54 | return L; 55 | } 56 | 57 | void print(LinkList &L) { 58 | LinkList p = L->next; 59 | while (p) { 60 | printf("%d ", p->data); 61 | p = p->next; 62 | } 63 | } 64 | 65 | int main() { 66 | LinkList L; 67 | init_list(L); 68 | create_list(L, 5); 69 | L = delete_min(L); 70 | print(L); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/6. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[5] = {3, 2, 1, 4, 5}; 14 | int b[5] = {0, 1, 2, 3, 4}; 15 | int c[5] = {5, 4, 3, 2, 1}; 16 | 17 | void Build(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 5; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Print(LinkedList L) { 33 | LinkedList p = L -> next; 34 | while(p) { 35 | cout << p -> data << " "; 36 | p = p -> next; 37 | } 38 | 39 | cout << endl; 40 | } 41 | 42 | LinkedList DEL_MIN(LinkedList & L) { 43 | LinkedList p = L, minp =L -> next; //设置p为第一个元素,minp为当前假定的最小元素 44 | 45 | //p从头节点开始,每次往后看一格,最后minp记录的是最小值的前一个元素,方便删除 46 | while(p -> next) { 47 | if (p -> next -> data < minp -> data) { 48 | minp = p; 49 | } 50 | p = p -> next; 51 | } 52 | 53 | //直接执行对minp的后继节点的删除 54 | LinkedList q = minp -> next; 55 | minp -> next = minp -> next -> next; 56 | free(q); 57 | return L; 58 | } 59 | 60 | 61 | int main(){ 62 | LinkedList L; 63 | Build(L); 64 | Print(L); 65 | L = DEL_MIN(L); 66 | Print(L); 67 | return 0; 68 | }; 69 | 70 | 71 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_5.cpp: -------------------------------------------------------------------------------- 1 | /* ************************************************** 2 | * Filename: 2.3.7_56.cpp 3 | * Create: 2022-06-06 4 | * Author: Wulnut 5 | * *************************************************/ 6 | 7 | #include 8 | using namespace std; 9 | 10 | typedef int ElemType; 11 | typedef struct LNode { 12 | ElemType data; 13 | LNode *next; 14 | } LNode, *LinkList; 15 | 16 | void init_list(LinkList &L) { 17 | L = (LinkList) malloc(sizeof (LNode)); // 产生头节点,并使指向此节点 18 | if (!L) return ; // 存储分配失败 19 | L->next = nullptr; // 头节点为空 20 | } 21 | 22 | // 前插法 23 | void create_list(LinkList &L, int n) { 24 | 25 | L = (LinkList) malloc(sizeof (LNode)); 26 | L->next = nullptr; 27 | printf("输入%d个数字", n); 28 | 29 | for (int i = n; i > 0; i --) { 30 | auto p = (LinkList) malloc(sizeof (LNode)); 31 | scanf("%d", &p->data); 32 | p->next = L->next; 33 | L->next = p; 34 | } 35 | } 36 | 37 | void print(LinkList &L) { 38 | LinkList p = L->next; 39 | while (p) { 40 | printf("%d ", p->data); 41 | p = p->next; 42 | } 43 | } 44 | 45 | LinkList reverse(LinkList &L) { 46 | LNode *cur_ptr = L->next; 47 | L->next = nullptr; 48 | 49 | while (cur_ptr) { 50 | LNode *next_ptr = cur_ptr->next; 51 | cur_ptr->next = L->next; 52 | L->next = cur_ptr; 53 | cur_ptr = next_ptr; 54 | } 55 | 56 | return L; 57 | } 58 | 59 | int main() { 60 | LinkList L; 61 | init_list(L); 62 | create_list(L, 5); 63 | L = reverse(L); 64 | print(L); 65 | return 0; 66 | } -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/6. 3 | // 4 | #include 5 | using namespace std; 6 | 7 | typedef struct Node { 8 | struct Node * next; 9 | int data; 10 | } Node, * LinkedList; 11 | 12 | int a[5] = {3, 2, 1, 4, 5}; 13 | int b[5] = {0, 1, 2, 3, 4}; 14 | int c[5] = {5, 4, 3, 2, 1}; 15 | 16 | void Build(LinkedList & L) { 17 | LinkedList s, r; 18 | s = (LinkedList) malloc(sizeof(Node)); 19 | L = s; 20 | r = L; 21 | r -> next = NULL; 22 | for(int i = 0; i < 5; ++i) { 23 | s = (LinkedList) malloc (sizeof(Node)); 24 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 25 | r -> next = s; 26 | r = s; 27 | } 28 | r -> next = NULL; 29 | } 30 | 31 | void Print(LinkedList L) { 32 | LinkedList p = L -> next; 33 | while(p) { 34 | cout << p -> data << " "; 35 | p = p -> next; 36 | } 37 | 38 | cout << endl; 39 | } 40 | 41 | // 使用头插法进行链表反转 42 | void Reverse_LinkedList(LinkedList & L) { 43 | LinkedList p = L -> next; // 从首节点开始 44 | L -> next = NULL; // 将头节点单独取出 45 | while(p) { 46 | LinkedList q = p -> next; // q指向p的下一个元素,防止断链 47 | p -> next = L -> next; // 头插法1 48 | L -> next = p; // 头插法2 49 | p = q; // 借尸还魂 50 | } 51 | } 52 | 53 | 54 | int main(){ 55 | LinkedList L; 56 | Build(L); 57 | Print(L); 58 | Reverse_LinkedList(L); 59 | Print(L); 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_6_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/6. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[5] = {3, 2, 1, 4, 5}; 14 | int b[5] = {0, 1, 2, 3, 4}; 15 | int c[5] = {5, 4, 3, 2, 1}; 16 | 17 | void Build(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 5; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Print(LinkedList L) { 33 | LinkedList p = L -> next; 34 | while(p) { 35 | cout << p -> data << " "; 36 | p = p -> next; 37 | } 38 | 39 | cout << endl; 40 | } 41 | 42 | // 使用插入排序的思想,将数组分为两段,前一段是orderd,后一段unordered,依次从后一段中取出一个与元素,插入到前一段中,使前一段保持有序 43 | LinkedList Sort(LinkedList & L) { 44 | LinkedList p = L -> next, left_head = p -> next; // left_head是unordered链表部分的头节点 45 | p -> next = NULL; // 有序的链表和无序的链表断开 46 | 47 | while(left_head) { // 依次取出无序链表中的每个节点,将其插入到有序链表中 48 | LinkedList q = left_head; // 首先摘一个节点下来 49 | left_head = left_head -> next; // 头节点往后走 50 | p = L; // 将摘下来的节点插入到有序表中,因此需要和L表中的节点进行对比 51 | 52 | // 开始寻找插入的地方 53 | while(p -> next && q -> data > p -> next -> data) { 54 | p = p -> next; 55 | } 56 | //将q插入到p的后面 57 | q -> next = p -> next; 58 | p -> next = q; 59 | } 60 | } 61 | 62 | int main() { 63 | LinkedList L; 64 | Build(L); 65 | Print(L); 66 | Sort(L); 67 | Print(L); 68 | return 0; 69 | } -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_7_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/6. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[5] = {3, 2, 1, 4, 5}; 14 | int b[5] = {0, 1, 2, 3, 4}; 15 | int c[5] = {5, 4, 3, 2, 1}; 16 | 17 | void Build(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 5; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Print(LinkedList L) { 33 | LinkedList p = L -> next; 34 | while(p) { 35 | cout << p -> data << " "; 36 | p = p -> next; 37 | } 38 | 39 | cout << endl; 40 | } 41 | 42 | // 将x到y之间的元素给删除掉 43 | LinkedList DEL_X2Y(LinkedList & L, int x, int y) { 44 | LinkedList p = L; 45 | while(p -> next) { 46 | if (p -> next -> data > x && p -> next -> data < y) { // 若在范围内 47 | LinkedList q = p -> next; // q先保存要删除的元素 48 | p -> next = p -> next -> next; // 执行删除操作 49 | free(q); // 将q释放掉 50 | } 51 | p = p -> next; // 看下一个 52 | } 53 | } 54 | 55 | int main() { 56 | LinkedList L; 57 | Build(L); 58 | Print(L); 59 | DEL_X2Y(L, 1, 4); 60 | Print(L); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_8_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/6. 3 | // 4 | // 5 | // Created by mach4101 on 2022/6/6. 6 | // 7 | 8 | #include 9 | using namespace std; 10 | 11 | typedef struct Node { 12 | struct Node * next; 13 | int data; 14 | } Node, * LinkedList; 15 | 16 | int a[7] = {5, 6, 3,2,1,4, 5}; 17 | int b[9] = {0, 1, 2, 3, 4, 2,1,4, 5}; 18 | int c[5] = {5, 4, 3, 2, 1}; 19 | 20 | void Build1(LinkedList & L) { 21 | LinkedList s, r; 22 | s = (LinkedList) malloc(sizeof(Node)); 23 | L = s; 24 | r = L; 25 | r -> next = NULL; 26 | for(int i = 0; i < 7; ++i) { 27 | s = (LinkedList) malloc (sizeof(Node)); 28 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 29 | r -> next = s; 30 | r = s; 31 | } 32 | r -> next = NULL; 33 | } 34 | 35 | void Build2(LinkedList & L) { 36 | LinkedList s, r; 37 | s = (LinkedList) malloc(sizeof(Node)); 38 | L = s; 39 | r = L; 40 | r -> next = NULL; 41 | for(int i = 0; i < 9; ++i) { 42 | s = (LinkedList) malloc (sizeof(Node)); 43 | s -> data = b[i]; //测试数组a,b,c只需改这个地方即可 44 | r -> next = s; 45 | r = s; 46 | } 47 | r -> next = NULL; 48 | } 49 | 50 | void Print(LinkedList L) { 51 | LinkedList p = L -> next; 52 | while(p) { 53 | cout << p -> data << " "; 54 | p = p -> next; 55 | } 56 | 57 | cout << endl; 58 | } 59 | 60 | int maxv(int a, int b) { 61 | if (a > b) 62 | return a; 63 | else 64 | return b; 65 | } 66 | 67 | int minv(int a, int b) { 68 | if (a < b) 69 | return a; 70 | else 71 | return b; 72 | } 73 | 74 | // 尾段有一段重合,首先在长的链表上走一段,让两个链表的剩余长度相同,然后一起走,如果发现有相同的节点,则说明不仅有公共节点,而且一直到最后一个节点,这一段都公共节点 75 | void CommonNode(LinkedList L1, LinkedList L2) { 76 | LinkedList p1 = L1 -> next; 77 | LinkedList p2 = L2 -> next; 78 | int len1 = 7, len2 = 9; 79 | 80 | int jump = maxv(len1, len2) - minv(len1, len1); 81 | 82 | if (len1 > len2) { 83 | while(jump--) { 84 | p1 = p1 -> next; 85 | } 86 | } else { 87 | while(jump--) { 88 | p2 = p2 -> next; 89 | } 90 | } 91 | 92 | while(p1) { //开始同步一起跳 93 | if(p1 -> data == p2 -> data) { //如果发现有相同的节点,那后面肯定也都是相同的,否则不可能叫Y型公共结点,因为链表中不可能存在X型公共节点(只有一个指针域) 94 | cout << "公共节点如下:"; 95 | while(p1) { 96 | cout << p1 -> data << " "; 97 | p1 = p1 -> next; 98 | } 99 | } else { 100 | p1 = p1 -> next; 101 | p2 = p2 -> next; 102 | } 103 | 104 | } 105 | } 106 | 107 | int main() { 108 | LinkedList L1, L2; 109 | Build1(L1); 110 | Build2(L2); 111 | Print(L1); 112 | Print(L2); 113 | CommonNode(L1, L2); 114 | return 0; 115 | } 116 | 117 | 118 | -------------------------------------------------------------------------------- /chapter_2/2.3.7/2.3.7_9_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/6. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | struct Node * next; 10 | int data; 11 | } Node, * LinkedList; 12 | 13 | int a[5] = {3, 2, 1, 4, 5}; 14 | int b[5] = {0, 1, 2, 3, 4}; 15 | int c[5] = {5, 4, 3, 2, 1}; 16 | 17 | void Build(LinkedList & L) { 18 | LinkedList s, r; 19 | s = (LinkedList) malloc(sizeof(Node)); 20 | L = s; 21 | r = L; 22 | r -> next = NULL; 23 | for(int i = 0; i < 5; ++i) { 24 | s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 26 | r -> next = s; 27 | r = s; 28 | } 29 | r -> next = NULL; 30 | } 31 | 32 | void Print(LinkedList L) { 33 | LinkedList p = L -> next; 34 | while(p) { 35 | cout << p -> data << " "; 36 | p = p -> next; 37 | } 38 | 39 | cout << endl; 40 | } 41 | 42 | // 暴力n方输出 43 | LinkedList SortAndDel(LinkedList & L) { 44 | LinkedList p = L; 45 | 46 | int len = 0; // len是链表长度,用来看需要循环多少次,每一次输出一个最小值,并且删除一个节点 47 | while(p -> next) { 48 | len++; 49 | p = p -> next; 50 | } 51 | 52 | while(len -- ) { // 每次循环删除一个节点 53 | p = L; 54 | int minv = p -> next -> data; 55 | LinkedList min_ptr = p; 56 | while(p -> next) { 57 | if(p -> next -> data < minv) { 58 | minv = p -> next -> data; 59 | min_ptr = p; 60 | } 61 | p = p -> next; 62 | } 63 | cout << minv << " "; 64 | LinkedList q = min_ptr -> next; 65 | min_ptr -> next = min_ptr -> next -> next; 66 | free(q); 67 | } 68 | 69 | free(L); 70 | } 71 | 72 | int main() { 73 | LinkedList L; 74 | Build(L); 75 | Print(L); 76 | SortAndDel(L); 77 | return 0; 78 | } -------------------------------------------------------------------------------- /chapter_3/3.1.4/3.1.4_3_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/17. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | bool check(char A[]) { 9 | int count = 0; // 用一个变量来判断 10 | for(int i = 0; i < 8; i ++) { // 扫描数组 11 | if(A[i] == 'I') // 如果是I就加,是O就减 12 | count++; 13 | else 14 | count--; 15 | if(count < 0) return false; //如果在某次操作中出现出栈过多,就返回false 16 | } 17 | return true; //如果至始至终都没出现false,那么返回true; 18 | } 19 | 20 | int main() { 21 | char a[8] = {'I', 'O', 'I', 'I', 'O', 'I', 'O', 'O'}; 22 | char b[8] = {'I', 'O', 'O', 'I', 'O', 'I', 'I', 'O'}; 23 | char c[8] = {'I', 'I', 'I', 'O', 'I', 'O', 'I', 'O'}; 24 | char d[8] = {'I', 'I', 'I', 'O', 'O', 'I', 'O', 'O'}; 25 | 26 | if(check(a)) { // 改这个地方测试序列是否满足要求 27 | cout << "true" << endl; 28 | } else { 29 | cout << "false" << endl; 30 | } 31 | } -------------------------------------------------------------------------------- /chapter_3/3.1.4/3.1.4_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/20. 3 | // 思路:先将链表中的元素一个一个push到栈中,然后再从链表头和栈顶元素依次比较,如果某次发现不等,则说明不是回文,如果一直到结束都没有不等的,则返回true 4 | // 5 | 6 | #include 7 | using namespace std; 8 | 9 | #define MaxSize 100 10 | 11 | typedef struct Node { 12 | struct Node * next; 13 | char data; 14 | } Node, * LinkedList; 15 | 16 | /* 17 | * 定义栈为空的时候栈顶指针为-1 18 | * 以后每次Push时,需要先移动指针,然后再将值放进去 19 | * 取栈顶元素时,直接取top 例如stack[top],即是栈顶元素 20 | * */ 21 | 22 | typedef struct Stack{ 23 | char data[MaxSize]; // 栈数组 24 | int top = -1; // 栈顶指针 25 | }Stack; 26 | 27 | void Push(Stack & S, char a) { 28 | if(S.top == MaxSize - 1) { 29 | cout << "栈满" << endl; 30 | return; 31 | } else { 32 | S.data[ ++ S.top] = a; 33 | } 34 | } 35 | 36 | void Pop(Stack & S, char & a) { 37 | if(S.top == - 1) { 38 | cout << "栈空" << endl; 39 | return; 40 | } else { 41 | a = S.data[S.top -- ]; 42 | } 43 | } 44 | 45 | char a[4] = {'x', 'x', 'x', 'x'}; 46 | 47 | void Build(LinkedList & L) { 48 | LinkedList s, r; 49 | s = (LinkedList) malloc(sizeof(Node)); 50 | L = s; 51 | r = L; 52 | r -> next = NULL; 53 | for(int i = 0; i < 4; ++i) { 54 | s = (LinkedList) malloc (sizeof(Node)); 55 | s -> data = a[i]; //测试数组a,b,c只需改这个地方即可 56 | r -> next = s; 57 | r = s; 58 | } 59 | r -> next = NULL; 60 | } 61 | 62 | void Print(LinkedList L) { 63 | LinkedList p = L -> next; 64 | while(p) { 65 | cout << p -> data << " "; 66 | p = p -> next; 67 | } 68 | 69 | cout << endl; 70 | } 71 | 72 | bool check (LinkedList L) { 73 | Stack stk; 74 | LinkedList p = L -> next; 75 | while(p) { // 将链表中的数据全部push到栈中 76 | Push(stk, p -> data); 77 | p = p -> next; 78 | } 79 | p = L -> next; 80 | 81 | while(p) { 82 | char a; 83 | 84 | Pop(stk, a); // 取出栈顶元素 85 | if (a != p -> data) // 如果和链表元素不相等 86 | return false; 87 | p = p -> next; 88 | } 89 | return true; // 如果在比较过程中未发现异常,则返回true 90 | } 91 | 92 | int main(){ 93 | LinkedList L; 94 | Build(L); 95 | Print(L); 96 | if(check(L)) 97 | cout << "是中心对称" << endl; 98 | else 99 | cout << "不是中心对称" << endl; 100 | return 0; 101 | }; 102 | -------------------------------------------------------------------------------- /chapter_3/3.1.4/3.1.4_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // Created by mach4101 on 2022/6/24. 2 | // 3 | 4 | // 两栈共享空间 [0, maxsize - 1] 5 | 6 | #include 7 | using namespace std; 8 | 9 | #define Maxsize 10 10 | typedef struct DoubleStack { 11 | int top1; //第一个栈的栈顶指针 12 | int top2; //第二个栈的栈顶指针 13 | int buffer[Maxsize]; //共享栈 14 | } DoubleStack; 15 | 16 | // 将data压入flag所标识的栈中 17 | void Push(DoubleStack & stack, int data, int flag) { // flag用于标识是哪一个栈,若flag为1表示是第一个栈,2为第二个栈 18 | if(flag == 1) { 19 | // 压数据之前需要判断是否已满 20 | if(stack.top1 + 1 == stack.top2) { 21 | cout << "栈满了哥" << endl; 22 | return; 23 | } 24 | 25 | stack.buffer[++ stack.top1] = data; // 压栈 26 | } else if(flag == 2) { 27 | if(stack.top2 - 1 == stack.top1) { 28 | cout << "栈真满了" << endl; 29 | return; 30 | } 31 | stack.buffer[-- stack.top2] = data; //压栈 32 | } 33 | } 34 | 35 | void Pop(DoubleStack & stack, int & data, int flag) { 36 | if(flag == 1) { 37 | //弹数据之前要判断是否为空,如果是空的那就不能弹 38 | if(stack.top1 == -1) { 39 | cout << "空的,弹不了哥" << endl; 40 | return; 41 | } 42 | data = stack.buffer[stack.top1 --]; 43 | } else if(flag == 2){ 44 | if(stack.top2 == Maxsize) { 45 | cout << "空的,弹不了哥" << endl; 46 | return; 47 | } 48 | 49 | data = stack.buffer[stack.top2 --]; 50 | } 51 | } 52 | 53 | int main() { 54 | DoubleStack stack; 55 | stack.top1 = -1; 56 | stack.top2 = Maxsize; 57 | Push(stack, 1, 1); 58 | Push(stack, 2, 1); 59 | Push(stack, 3, 1); 60 | Push(stack, 4, 1); 61 | Push(stack, 5, 1); 62 | 63 | Push(stack, 1, 2); 64 | Push(stack, 2, 2); 65 | Push(stack, 3, 2); 66 | Push(stack, 4, 2); 67 | Push(stack, 5, 2); 68 | 69 | int data; 70 | Pop(stack, data, 1); 71 | cout << data << endl; 72 | Pop(stack, data, 1); 73 | cout << data << endl; 74 | Pop(stack, data, 1); 75 | cout << data << endl; 76 | Pop(stack, data, 1); 77 | cout << data << endl; 78 | Pop(stack, data, 1); 79 | cout << data << endl; 80 | 81 | 82 | return 0; 83 | } -------------------------------------------------------------------------------- /chapter_3/3.2.5/3.2.5_1_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/24. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | # define Maxsize 100 9 | 10 | typedef struct Queue { 11 | int rear, front, tag; 12 | int buffer[Maxsize]; 13 | } Queue; 14 | 15 | // 入队 16 | void Enqueue(Queue & que, int data) { // 将data加入队列 17 | //判断队列是否已满 18 | if(que.rear == que.front && que.tag == 1) { 19 | cout << "塞不下啦!" << endl; 20 | return; 21 | } 22 | 23 | que.buffer[que.rear] = data; 24 | que.rear = (que.rear + 1) % Maxsize; 25 | que.tag = 1; 26 | } 27 | 28 | void Dequeue(Queue & que, int & data) { // 队列出队,将出队元素的值赋值给data 29 | // 判断队列是否为空 30 | if(que.rear == que.front && que.tag == 0) { 31 | cout << "真没有出的了哥" << endl; 32 | return; 33 | } 34 | 35 | data = que.buffer[que.front]; 36 | que.front = (que.front + 1) % Maxsize; 37 | que.tag = 0; 38 | } 39 | 40 | 41 | int main() { 42 | Queue que; 43 | que.rear = que.front = que.tag = 0; // 全部初始化为零 44 | 45 | int n = 50; 46 | while(n -- ) { 47 | Enqueue(que, n); 48 | } 49 | 50 | n = 25; 51 | while(n --) { 52 | int data; 53 | Dequeue(que, data); 54 | cout << data << endl; 55 | } 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /chapter_3/3.2.5/3.2.5_2_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/24. 3 | // 4 | #include 5 | using namespace std; 6 | 7 | # define Maxsize 100 8 | 9 | // 栈相关代码定义 10 | typedef struct Stack{ 11 | int data[Maxsize]; // 栈数组 12 | int top; // 栈顶指针 13 | }Stack; 14 | 15 | void Push(Stack & S, int a) { 16 | if(S.top == Maxsize - 1) { 17 | cout << "栈满" << endl; 18 | return; 19 | } else { 20 | S.data[ ++ S.top] = a; 21 | } 22 | } 23 | 24 | void Pop(Stack & S, int & a) { 25 | if(S.top == - 1) { 26 | cout << "栈空" << endl; 27 | return; 28 | } else { 29 | a = S.data[S.top -- ]; 30 | } 31 | } 32 | 33 | // 队列相关代码定义 34 | typedef struct Queue { 35 | int rear, front, tag; 36 | int buffer[Maxsize]; 37 | } Queue; 38 | 39 | // 入队 40 | void Enqueue(Queue & que, int data) { // 将data加入队列 41 | //判断队列是否已满 42 | if(que.rear == que.front && que.tag == 1) { 43 | cout << "塞不下啦!" << endl; 44 | return; 45 | } 46 | 47 | que.buffer[que.rear] = data; 48 | que.rear = (que.rear + 1) % Maxsize; 49 | que.tag = 1; 50 | } 51 | 52 | void Dequeue(Queue & que, int & data) { // 队列出队,将出队元素的值赋值给data 53 | // 判断队列是否为空 54 | if(que.rear == que.front && que.tag == 0) { 55 | cout << "真没有出的了哥" << endl; 56 | return; 57 | } 58 | 59 | data = que.buffer[que.front]; 60 | que.front = (que.front + 1) % Maxsize; 61 | que.tag = 0; 62 | } 63 | 64 | void InverseQueue(Queue & que, Stack & stack) { 65 | // 队列元素出队,然后入栈,然后出栈,入队 66 | for(int i = 0; i < 10; ++i) { 67 | int data; 68 | Dequeue(que, data); 69 | Push(stack, data); 70 | } 71 | 72 | for(int i = 0; i < 10; ++i) { 73 | int data; 74 | Pop(stack, data); 75 | Enqueue(que, data); 76 | } 77 | } 78 | 79 | int main() { 80 | Stack stack; 81 | Queue que; 82 | 83 | // 初始化数据结构的数据 84 | stack.top = -1; 85 | que.rear = que.front = que.tag = 0; 86 | 87 | //假设队列中的元素是 0到9; 88 | for(int i = 0; i < 10; ++i) { 89 | Enqueue(que, i); 90 | } 91 | 92 | InverseQueue(que, stack); // 利用stack将que的元素逆置 93 | 94 | // 一个一个出队查看结果: 95 | for(int i = 0; i < 10; ++i) { 96 | int data; 97 | Dequeue(que, data); 98 | cout << data << endl; 99 | } 100 | return 0; 101 | } 102 | 103 | 104 | -------------------------------------------------------------------------------- /chapter_3/3.2.5/3.2.5_3_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // Created by mach4101 on 2022/6/24. 2 | /* 3 | * 使用两个栈来模拟队列,当队列元素入队时,可以将元素push到一号栈中,若需要出队,则将元素全部弹出来,push到二号栈中 4 | * 此后,若需要入队,则push到一号栈,若需要出队,则从二号栈pop,若二号栈空了,那么就将一号栈中的元素全部弄到二号栈中 5 | * 当栈一和栈二都空时,队列为空 6 | * */ 7 | #include 8 | using namespace std; 9 | 10 | # define MaxSize 100 11 | 12 | // 栈相关代码定义 13 | typedef struct Stack{ 14 | int data[MaxSize]; // 栈数组 15 | int top; // 栈顶指针 16 | }Stack; 17 | 18 | bool StackOverflow(Stack S) { 19 | return S.top == MaxSize -1; 20 | } 21 | 22 | bool StackEmpty(Stack S) { 23 | return S.top == -1; 24 | } 25 | 26 | void Push(Stack & S, int a) { 27 | if(StackOverflow(S)) { 28 | cout << "栈满" << endl; 29 | return; 30 | } else 31 | S.data[ ++ S.top] = a; 32 | } 33 | 34 | void Pop(Stack & S, int & a) { 35 | if(StackEmpty(S)) { 36 | cout << "栈空" << endl; 37 | return; 38 | } else { 39 | a = S.data[S.top -- ]; 40 | } 41 | } 42 | 43 | bool QueueEmpty(Stack s1, Stack s2) { 44 | return StackEmpty(s1) && StackEmpty(s2); 45 | } 46 | 47 | void Enqueue(Stack & s1, Stack & s2, int data) { 48 | if(!StackOverflow(s1)) { 49 | Push(s1, data); 50 | } 51 | 52 | if(StackOverflow(s1) && !StackEmpty(s2)) { //一号栈满了,但是二号栈里面有东西,此时若冒然将一号栈中的东西弄到二号栈,则会导致顺序有问题,因此,此时说明队列满了 53 | cout << "队列满" << endl; 54 | return; 55 | } 56 | 57 | if(StackOverflow(s1) && StackEmpty(s2)) { // 一号栈满但是二号栈空,直接弄过去不会有什么顺序问题 58 | while(!StackEmpty(s1)) { 59 | int tmp; 60 | Pop(s1, tmp); 61 | Push(s2, tmp); 62 | } 63 | } 64 | } 65 | 66 | void Dequeue(Stack & s1, Stack & s2, int & data) { 67 | if(!StackEmpty(s2)) { //s2里面有,直接pop 68 | Pop(s2, data); 69 | } 70 | 71 | else if(StackEmpty(s2) && !StackEmpty(s1)) { //s2空了,但是s1有,全部弄过来 72 | while(!StackEmpty(s1)) { 73 | int tmp; 74 | Pop(s1, tmp); 75 | Push(s2, tmp); 76 | } 77 | Pop(s2, data); 78 | } 79 | 80 | else if(QueueEmpty(s1, s2)) { //两个栈都没了 81 | cout << "没了" << endl; 82 | data = 2147484620; 83 | } 84 | } 85 | 86 | int main() { 87 | Stack s1, s2; 88 | s1.top = s2.top = -1; 89 | Enqueue(s1, s2, 2); 90 | int data; 91 | Dequeue(s1, s2, data); 92 | cout << data << endl; 93 | return 0; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /chapter_3/3.3.6/3.3.6_1_mach4101.cpp: -------------------------------------------------------------------------------- 1 | /* 括号匹配 有圆括号、方括号和花括号 2 | * 算法思路:不管遇到什么括号,只要是左括号就入栈,若遇到右括号,则将当前所扫描的字符和栈顶的符号进行比较,如果可以匹配上,那么出栈,继续下一个,否则报错。如果字符串扫描完毕但是栈中依旧有元素,此时也说明有括号没有被匹配上,报错。 3 | * 4 | * */ 5 | #include 6 | using namespace std; 7 | 8 | #define MaxSize 100 9 | 10 | typedef struct Stack{ 11 | char data[MaxSize]; // 栈数组 12 | int top = -1; // 栈顶指针 13 | }Stack; 14 | bool IsEmpty(Stack S) { 15 | return S.top == -1; 16 | } 17 | void Push(Stack & S, char a) { 18 | if(S.top == MaxSize - 1) { 19 | cout << "栈满" << endl; 20 | return; 21 | } else { 22 | S.data[ ++ S.top] = a; 23 | } 24 | } 25 | 26 | void Pop(Stack & S, char & a) { 27 | if(S.top == - 1) { 28 | cout << "栈空" << endl; 29 | return; 30 | } else { 31 | a = S.data[S.top -- ]; 32 | } 33 | } 34 | 35 | bool match(char * s) { 36 | Stack stack; 37 | int i = 0; 38 | while(s[i] != '\0') { //遍历串 39 | if(s[i] == '(' || s[i] == '[' || s[i] == '{') //左括号入栈 40 | Push(stack, s[i]); 41 | 42 | // 若是三个右括号 43 | else if (s[i] == ')') { //若是右括号,取出栈顶元素,判断是否和左括号能够匹配,如果不能就直接false 44 | char tmp; 45 | Pop(stack, tmp); 46 | if(tmp != '(') return false; 47 | } else if(s[i] == ']') { 48 | char tmp; 49 | Pop(stack, tmp); 50 | if(tmp != '[') return false; 51 | } else if(s[i] == '}') { 52 | char tmp; 53 | Pop(stack, tmp); 54 | if(tmp != '{') return false; 55 | } 56 | 57 | i ++; //下一个 58 | } 59 | 60 | if(!IsEmpty(stack)) return false; //如果栈没空,说明有多的左括号,直接寄 61 | return true; 62 | } 63 | 64 | 65 | int main() { 66 | char * str = "(()[])"; //待检测的字符串 67 | if(match(str)) { //检查是否匹配 68 | cout << "匹配成功" << endl; 69 | } else { 70 | cout << "匹配失败" << endl; 71 | } 72 | 73 | } 74 | 75 | -------------------------------------------------------------------------------- /chapter_3/3.3.6/3.3.6_2_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/25. 3 | // 4 | /* 问题简化 5 | * 有一个序列前半段是是H,后半段是S 6 | * 有一个栈,现在需要利用和这个栈,将S弄到H前面 7 | * */ 8 | 9 | #include 10 | using namespace std; 11 | 12 | 13 | #define MaxSize 100 14 | 15 | typedef struct Stack{ 16 | char data[MaxSize]; // 栈数组 17 | int top = -1; // 栈顶指针 18 | }Stack; 19 | bool IsEmpty(Stack S) { 20 | return S.top == -1; 21 | } 22 | void Push(Stack & S, char a) { 23 | if(S.top == MaxSize - 1) { 24 | cout << "栈满" << endl; 25 | return; 26 | } else { 27 | S.data[ ++ S.top] = a; 28 | } 29 | } 30 | 31 | void Pop(Stack & S, char & a) { 32 | if(S.top == - 1) { 33 | cout << "栈空" << endl; 34 | return; 35 | } else { 36 | a = S.data[S.top -- ]; 37 | } 38 | } 39 | 40 | void dispatch(Stack stack, char s[]) { 41 | int cur = 0; 42 | for(int i = 0; s[i] != '\0'; i++) { 43 | if(s[i] == 'H') { // 前半段,压栈 44 | Push(stack, s[i]); 45 | } else { // 后半段,挪到前面 46 | s[cur++] = s[i]; 47 | } 48 | } 49 | 50 | while(!IsEmpty(stack)) { // 栈不空的话,就把栈里面的前半段弄到后半段去 51 | char tmp; 52 | Pop(stack, tmp); 53 | s[cur++] = tmp; 54 | } 55 | 56 | } 57 | 58 | int main() { 59 | char s[] = "HHHHHHHHHHSSSSSSSSSS"; //假设n等于10,则H和S各有十个 60 | 61 | Stack stack; 62 | dispatch(stack, s); //调度 63 | 64 | //输出查看结果 65 | int i = 0; 66 | while(s[i] != '\0') { 67 | cout << s[i] << " "; 68 | i++; 69 | } 70 | 71 | return 0; 72 | } -------------------------------------------------------------------------------- /chapter_3/3.3.6/3.3.6_3_栈版本_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/25. 3 | // 4 | 5 | 懒得写 -------------------------------------------------------------------------------- /chapter_3/3.3.6/3.3.6_3_递归版_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/25. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | int Pn(int n, int x) { 9 | if(n == 0) 10 | return 1; 11 | else if(n == 1) { 12 | return 2 * x; 13 | } else if(n > 1) { 14 | return 2 * x * Pn(n - 1, x) - 2 * (n - 1) * Pn(n - 2, x); 15 | } 16 | } 17 | 18 | int main() { 19 | int x = 10; 20 | int n = 2; 21 | cout << Pn(n, x) << endl; 22 | } -------------------------------------------------------------------------------- /chapter_5/5.2.3/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_5/5.2.3/.DS_Store -------------------------------------------------------------------------------- /chapter_5/5.2.3/5.2.3_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/29. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct SqTree { 9 | // 使用字母N来表示无意义的点 10 | char data[16] = {'N', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'N', 'N', 'N', 'N', 'H', 'I', 'N', 'N'}; 11 | }; 12 | 13 | char LCA(SqTree Tree, int i, int j) { 14 | // 寻找下标为i, j的最近公共祖先 15 | if (Tree.data[i] != 'N' && Tree.data[j] != 'N') { // 若能满足条件,说明肯定有公共祖先,最起码根节点是,因此如果不满足条件直接返回-1 16 | while(i != j) { // i和j谁大谁往上跳 17 | if(i > j) 18 | i = i / 2; 19 | else 20 | j = j / 2; 21 | } 22 | return Tree.data[i]; 23 | } 24 | return 'N'; 25 | } 26 | 27 | int main() { 28 | SqTree Tree; 29 | cout << LCA(Tree, 12, 13) << endl; // data[12] = H, data[13] = I,他们的最近公共祖先是F 30 | return 0; 31 | } -------------------------------------------------------------------------------- /chapter_5/5.2.3/例图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_5/5.2.3/例图.png -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_10_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/2. 3 | // 求先序遍历的第k个节点的值:可以参考非递归的思路,设置一个自增的变量来实现 4 | // 也可以直接用递归求(参考王道后面的解析) 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | struct BiNode * lchild, * rchild; 13 | } BiNode, * BiTree; 14 | 15 | // 二叉树的创建 16 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 17 | int i = 0; 18 | void Build(BiTree & T) { 19 | char ch = a[i]; i++; 20 | if(ch == '#') // 如果是#,则说明这个节点是空的 21 | T = NULL; 22 | else { 23 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 24 | T -> data = ch; // 为其赋值 25 | T -> lchild = NULL; // 左右孩子都设置为空 26 | T -> rchild = NULL; 27 | Build(T -> lchild); // 递归创建左孩子 28 | Build(T -> rchild); // 递归创建右孩子 29 | } 30 | } 31 | 32 | // 栈结构如下 ************************************************** 33 | # define MaxSize 100 34 | typedef struct Stack{ 35 | BiNode * data[MaxSize]; // 栈中存放的是指向节点的指针 36 | int top = -1; // 栈顶指针 37 | }Stack; 38 | 39 | void Push(Stack & S, BiNode * a) { 40 | if(S.top == MaxSize - 1) { 41 | cout << "栈满" << endl; 42 | return; 43 | } else { 44 | S.data[ ++ S.top] = a; 45 | } 46 | } 47 | 48 | void Pop(Stack & S, BiNode * & a) { 49 | if(S.top == - 1) { 50 | cout << "栈空" << endl; 51 | return; 52 | } else { 53 | a = S.data[S.top -- ]; 54 | } 55 | } 56 | 57 | void GetTop(Stack & S, BiNode * & a) { 58 | if(S.top == - 1) { 59 | cout << "栈空" << endl; 60 | return; 61 | } else { 62 | a = S.data[S.top]; 63 | } 64 | } 65 | // 判断栈S是否为空,若为空,则返回true,否则为false 66 | int IsStackEmpty(Stack S) { 67 | return S.top == -1; 68 | } 69 | 70 | void PreOrder(BiTree T) { 71 | if(T) { 72 | cout << T -> data << " "; 73 | PreOrder(T -> lchild); 74 | PreOrder(T -> rchild); 75 | } 76 | } 77 | 78 | // 参考非递归的先序遍历思路,设置指针i表示当前正在输出第i个元素,当i=k时将其返回 79 | char PreOrderKth(BiTree T, int k) { 80 | int i = 0; 81 | Stack s; 82 | BiNode * p = T; 83 | while(p || !IsStackEmpty(s)) { 84 | if(p) { 85 | i ++; 86 | if(i == k) 87 | return p -> data; 88 | Push(s, p); 89 | p = p -> lchild; 90 | } else { 91 | Pop(s, p); 92 | p = p -> rchild; 93 | } 94 | } 95 | } 96 | 97 | int main() { 98 | BiTree T; 99 | Build(T); 100 | int k = 3; // 假设要求先序遍历中的第k个节点 101 | cout << PreOrderKth(T,k) << endl; 102 | 103 | return 0; 104 | } 105 | 106 | -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_11_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/2. 3 | // 对于树中每个元素值为x的节点,删去以其为根的子树,并且释放空间 4 | // 有个地方有疑问,不知道是否需要删除那个值为x的根节点,我考虑的是不删 5 | 6 | #include 7 | using namespace std; 8 | 9 | // 二叉树使用的是例图中的结构 10 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 11 | typedef struct BiNode { 12 | char data; // 数据域 13 | struct BiNode * lchild, * rchild; 14 | } BiNode, * BiTree; 15 | 16 | // 二叉树的创建 17 | char a[] = {'A','B','D','#', '#','E','#','#','C','B','H','#','#','I','#','#','G','#','#'}; 18 | int i = 0; 19 | void Build(BiTree & T) { 20 | char ch = a[i]; i++; 21 | if(ch == '#') // 如果是#,则说明这个节点是空的 22 | T = NULL; 23 | else { 24 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 25 | T -> data = ch; // 为其赋值 26 | T -> lchild = NULL; // 左右孩子都设置为空 27 | T -> rchild = NULL; 28 | Build(T -> lchild); // 递归创建左孩子 29 | Build(T -> rchild); // 递归创建右孩子 30 | } 31 | } 32 | 33 | void PreOrder(BiTree T) { 34 | if(T) { 35 | cout << T -> data << " "; 36 | PreOrder(T -> lchild); 37 | PreOrder(T -> rchild); 38 | } 39 | } 40 | 41 | # define MaxSize 100 42 | // 队列结构如下 ************************************************** 43 | typedef struct Queue { 44 | int rear, front, tag; 45 | BiNode * buffer[MaxSize]; // 存放节点指针 46 | } Queue; 47 | 48 | // 入队 49 | void Enqueue(Queue & que, BiNode * data) { // 将data加入队列 50 | //判断队列是否已满 51 | if(que.rear == que.front && que.tag == 1) { 52 | cout << "塞不下啦!" << endl; 53 | return; 54 | } 55 | 56 | que.buffer[que.rear] = data; 57 | que.rear = (que.rear + 1) % MaxSize; 58 | que.tag = 1; 59 | } 60 | 61 | int IsQueEmpty(Queue que) { 62 | return que.rear == que.front && que.tag == 0; 63 | } 64 | 65 | void Dequeue(Queue & que, BiNode * & data) { // 队列出队,将出队元素的值赋值给data 66 | // 判断队列是否为空 67 | if(que.rear == que.front && que.tag == 0) { 68 | cout << "真没有出的了哥" << endl; 69 | return; 70 | } 71 | 72 | data = que.buffer[que.front]; 73 | que.front = (que.front + 1) % MaxSize; 74 | que.tag = 0; 75 | } 76 | 77 | void InitQueue(Queue & que) { 78 | que.tag = que.front = que.rear = 0; 79 | } 80 | 81 | void DelChild(BiTree & p) { 82 | // 删除p指针指向的所有节点 83 | if(p) return; 84 | DelChild(p -> lchild); // 递归删除左子树 85 | DelChild(p -> rchild); // 递归删除右子树 86 | free(p); // 释放该节点 87 | } 88 | 89 | // 先用层序遍历的方式找到值为x的节点的指针,然后删除该节点的所有孩子 90 | void Traverse(BiTree & T, char x) { 91 | Queue que; 92 | InitQueue(que); 93 | Enqueue(que, T); 94 | BiNode * p; 95 | 96 | while(!IsQueEmpty(que)) { // 层次遍历 97 | Dequeue(que, p); 98 | 99 | if(p -> data == x) { // 找到了值为x的节点 100 | if (p -> lchild) 101 | DelChild(p -> lchild); 102 | if (p -> rchild) 103 | DelChild(p -> rchild); 104 | p -> lchild = NULL; 105 | p -> rchild = NULL; 106 | } 107 | 108 | if(p -> lchild) 109 | Enqueue(que, p -> lchild); 110 | if(p -> rchild) 111 | Enqueue(que, p -> rchild); 112 | } 113 | } 114 | 115 | int main() { 116 | BiTree T; 117 | Build(T); 118 | 119 | PreOrder(T); 120 | 121 | cout << endl; 122 | char x = 'B'; // 删除例图中值为B的节点的子树 123 | 124 | Traverse(T, x); 125 | 126 | PreOrder(T); 127 | return 0; 128 | } -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_12_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/6. 3 | // 查找值为x的节点,并且编写算法打印值为x的所有祖先节点 4 | // 也就是要输出,从根节点到x节点路径上的所有节点 5 | // 本算法使用的是递归版本,非递归版本王道课后书有所描述 6 | 7 | #include 8 | using namespace std; 9 | 10 | // 二叉树使用的是例图中的结构 11 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 12 | typedef struct BiNode { 13 | char data; // 数据域 14 | struct BiNode * lchild, * rchild; 15 | } BiNode, * BiTree; 16 | 17 | 18 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 19 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 20 | int i = 0; 21 | void Build(BiTree & T) { 22 | char ch = a[i]; i++; 23 | if(ch == '#') // 如果是#,则说明这个节点是空的 24 | T = NULL; 25 | else { 26 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 27 | T -> data = ch; // 为其赋值 28 | T -> lchild = NULL; // 左右孩子都设置为空 29 | T -> rchild = NULL; 30 | Build(T -> lchild); // 递归创建左孩子 31 | Build(T -> rchild); // 递归创建右孩子 32 | } 33 | } 34 | 35 | void PreOrder(BiTree T) { 36 | if(T) { 37 | cout << T -> data << " "; 38 | PreOrder(T -> lchild); 39 | PreOrder(T -> rchild); 40 | } 41 | } 42 | 43 | bool FindAns(BiTree T, char x) { // 查找值为x的所有祖先 44 | if(T -> data == x) { // 如果找到,那么就向上层返回为true 45 | return true; 46 | } 47 | 48 | if(T -> lchild) { // 若有左子树,就到左子树中找 49 | if(FindAns(T -> lchild, x)) { // 若左子树中存在,就输出,并返回true给上层 50 | cout << T -> data << " "; 51 | return true; 52 | } 53 | 54 | } 55 | 56 | if(T -> rchild) { // 若有右子树,就到右子树中找 57 | if(FindAns(T -> rchild, x)) { // 若右子树中存在,就输出,并返回true给上层 58 | cout << T -> data << " "; 59 | return true; 60 | } 61 | } 62 | 63 | 64 | } 65 | 66 | int main() { 67 | BiTree T; 68 | Build(T); 69 | char x = 'H'; 70 | 71 | FindAns(T, x); // 查找值为x的所有祖先节点 72 | 73 | return 0; 74 | } -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_13_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/6. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | struct BiNode * lchild, * rchild; 13 | int tag = 0; 14 | } BiNode, * BiTree; 15 | 16 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 17 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 18 | int i = 0; 19 | void Build(BiTree & T) { 20 | char ch = a[i]; i++; 21 | if(ch == '#') // 如果是#,则说明这个节点是空的 22 | T = NULL; 23 | else { 24 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 25 | T -> data = ch; // 为其赋值 26 | T -> lchild = NULL; // 左右孩子都设置为空 27 | T -> rchild = NULL; 28 | Build(T -> lchild); // 递归创建左孩子 29 | Build(T -> rchild); // 递归创建右孩子 30 | } 31 | } 32 | 33 | void LCA(BiTree T, BiNode * p, BiNode * q, BiNode * & r) { 34 | BiNode * Stack1[20], * Stack2[20]; 35 | // top1是遍历时的栈顶指针,top2是辅助栈栈顶指针 36 | int top1 = 0, top2 = 0; 37 | 38 | BiNode * tmp = T; 39 | 40 | while(tmp || top1 > 0) { 41 | // 将左子树全部入栈 42 | while(tmp) { 43 | Stack1[++ top1] = tmp; 44 | tmp = tmp -> lchild; 45 | } 46 | 47 | // 如果栈一不为空并且已经访问过 48 | while(top1 != 0 && Stack1[top1] -> tag == 1) { 49 | // 如果访问到p 50 | if(Stack1[top1] == p) { 51 | for(int i = 1; i <= top1; i++) { 52 | Stack2[i] = Stack1[i]; // 将栈一中的数据全部复制到辅助栈中 53 | } 54 | top2 = top1; 55 | } 56 | // 如果访问到q 57 | if(Stack1[top1] == q) 58 | // 从栈顶依此往下,找最近的公共祖先 59 | for(int i = top1; i > 0; i --) 60 | for(int j = top2; j > 0; j --) 61 | if(Stack1[i] == Stack2[j]) { 62 | r = Stack1[i]; 63 | return; 64 | } 65 | top1 --; // 退栈 66 | } 67 | 68 | if(top1 != 0) { // 栈不为空,左边访问完,去右边 69 | Stack1[top1] -> tag = 1; 70 | tmp = Stack1[top1] -> rchild; 71 | } 72 | } 73 | return; 74 | } 75 | 76 | int main() { 77 | BiTree T; 78 | Build(T); 79 | 80 | BiNode * p = T -> rchild -> lchild -> lchild; // p指针指向'H' 81 | BiNode * q = T -> rchild -> rchild; // q指针指向'G' 82 | BiNode * r = NULL; 83 | LCA(T, p, q, r); // 找H和G的最近公共祖先 84 | if(r) 85 | cout << r -> data << endl; 86 | else 87 | cout << "false" << endl; 88 | return 0; 89 | } -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_14_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/11. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | struct BiNode * lchild, * rchild; 13 | int tag = 0; 14 | } BiNode, * BiTree; 15 | 16 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 17 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 18 | int i = 0; 19 | void Build(BiTree & T) { 20 | char ch = a[i]; i++; 21 | if(ch == '#') // 如果是#,则说明这个节点是空的 22 | T = NULL; 23 | else { 24 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 25 | T -> data = ch; // 为其赋值 26 | T -> lchild = NULL; // 左右孩子都设置为空 27 | T -> rchild = NULL; 28 | Build(T -> lchild); // 递归创建左孩子 29 | Build(T -> rchild); // 递归创建右孩子 30 | } 31 | } 32 | 33 | int getMaxWidth(BiTree T) { 34 | BiNode * Queue[40]; 35 | int width = -1; 36 | int front = -1, rear = -1, last = 0; 37 | 38 | Queue[++rear] = T; 39 | 40 | while(front < rear) { 41 | BiNode * p = Queue[++ front]; 42 | if(p -> lchild) 43 | Queue[++ rear] = p -> lchild; 44 | if(p -> rchild) 45 | Queue[++ rear] = p -> rchild; 46 | 47 | if(front == last) { // 遍历一层结束 48 | width = max(width, rear - front); 49 | last = rear; 50 | } 51 | } 52 | 53 | return width; 54 | } 55 | 56 | int main() { 57 | BiTree T; 58 | Build(T); 59 | 60 | cout << getMaxWidth(T) << endl; 61 | 62 | return 0; 63 | } -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_15_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/11. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | void Pre2Post(char Pre[], int l1, int r1, char Post[], int l2, int r2) { 9 | if(l1 <= r1) { 10 | Post[r2] = Pre[l1]; 11 | int half = (r1 - l1) / 2; 12 | Pre2Post(Pre, l1 + 1, l1 + half, Post, l2, l2 + half - 1); 13 | Pre2Post(Pre, l1 + half + 1, r1, Post, l2 + half, r2 -1); 14 | } 15 | } 16 | 17 | int main() { 18 | char Post[8]; 19 | char Pre[8] = "ABDECFG"; 20 | Pre2Post(Pre, 0, 6, Post, 0, 6); 21 | for(int i = 0; i < 7; ++i) { 22 | cout << Post[i] << " "; 23 | } 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_16_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/11. 3 | // 4 | 5 | // 将二叉树的叶子结点用一个但链表串起来 6 | // 对二叉树进行先序遍历可以找到叶子节点的先后次序,pre指向上次访问的叶子结点,p作为访问指针 7 | 8 | #include 9 | using namespace std; 10 | 11 | // 二叉树使用的是例图中的结构 12 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 13 | typedef struct BiNode { 14 | char data; // 数据域 15 | struct BiNode * lchild, * rchild; 16 | } BiNode, * BiTree; 17 | 18 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 19 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 20 | int i = 0; 21 | void Build(BiTree & T) { 22 | char ch = a[i]; i++; 23 | if(ch == '#') // 如果是#,则说明这个节点是空的 24 | T = NULL; 25 | else { 26 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 27 | T -> data = ch; // 为其赋值 28 | T -> lchild = NULL; // 左右孩子都设置为空 29 | T -> rchild = NULL; 30 | Build(T -> lchild); // 递归创建左孩子 31 | Build(T -> rchild); // 递归创建右孩子 32 | } 33 | } 34 | 35 | // 栈结构如下 ************************************************** 36 | # define MaxSize 100 37 | typedef struct Stack{ 38 | BiNode * data[MaxSize]; // 栈中存放的是指向节点的指针 39 | int top = -1; // 栈顶指针 40 | }Stack; 41 | 42 | void Push(Stack & S, BiNode * a) { 43 | if(S.top == MaxSize - 1) { 44 | cout << "栈满" << endl; 45 | return; 46 | } else { 47 | S.data[ ++ S.top] = a; 48 | } 49 | } 50 | 51 | void Pop(Stack & S, BiNode * & a) { 52 | if(S.top == - 1) { 53 | cout << "栈空" << endl; 54 | return; 55 | } else { 56 | a = S.data[S.top -- ]; 57 | } 58 | } 59 | 60 | void GetTop(Stack & S, BiNode * & a) { 61 | if(S.top == - 1) { 62 | cout << "栈空" << endl; 63 | return; 64 | } else { 65 | a = S.data[S.top]; 66 | } 67 | } 68 | // 判断栈S是否为空,若为空,则返回true,否则为false 69 | int IsStackEmpty(Stack S) { 70 | return S.top == -1; 71 | } 72 | 73 | void Leaves2LinkedList(BiTree T, BiNode * & head) { 74 | Stack s; 75 | BiNode * pre = NULL, * p = T; 76 | 77 | while(p || !IsStackEmpty(s)) { 78 | if(p) { 79 | // 将当前访问到的节点压栈,一路向左 80 | Push(s, p); 81 | 82 | if(p -> lchild == NULL && p -> rchild == NULL) { // 说明遇到叶子 83 | if(pre == NULL) { // 如果是第一个叶子节点 84 | pre = p; // 将初始化pre 85 | head = p; 86 | } else { // 如果不是第一个叶子结点 87 | pre -> rchild = p; // 直接将pre的rchild指向p 88 | pre = p; 89 | } 90 | } 91 | 92 | p = p -> lchild; 93 | } else { 94 | Pop(s, p); // 取栈顶,向右 95 | p = p -> rchild; 96 | } 97 | } 98 | } 99 | 100 | int main() { 101 | BiTree T; 102 | Build(T); 103 | BiNode * head; 104 | Leaves2LinkedList(T, head); 105 | 106 | // 遍历head所指向的链表 107 | BiNode * p = head; 108 | while(p) { 109 | cout << p -> data << " "; 110 | p = p -> rchild; 111 | } 112 | return 0; 113 | } 114 | 115 | -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_17_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/12. 3 | // 4 | // 判断两个二叉树是否相似 5 | 6 | #include 7 | using namespace std; 8 | 9 | // 二叉树使用的是例图中的结构 10 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 11 | typedef struct BiNode { 12 | char data; // 数据域 13 | struct BiNode * lchild, * rchild; 14 | } BiNode, * BiTree; 15 | 16 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 17 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 18 | int i = 0; 19 | void Build(BiTree & T) { 20 | char ch = a[i]; i++; 21 | if(ch == '#') // 如果是#,则说明这个节点是空的 22 | T = NULL; 23 | else { 24 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 25 | T -> data = ch; // 为其赋值 26 | T -> lchild = NULL; // 左右孩子都设置为空 27 | T -> rchild = NULL; 28 | Build(T -> lchild); // 递归创建左孩子 29 | Build(T -> rchild); // 递归创建右孩子 30 | } 31 | } 32 | 33 | bool IsSimilar(BiTree T1, BiTree T2) { 34 | if(T1 == NULL && T2 == NULL) { 35 | return true; 36 | } else if(T1 == NULL || T2 == NULL) { 37 | return false; 38 | } else { 39 | return IsSimilar(T1 -> lchild, T2 -> lchild) && IsSimilar(T1 -> rchild, T2 -> rchild); 40 | } 41 | } 42 | 43 | int main() { 44 | BiTree T1, T2; 45 | Build(T1); 46 | i = 0; 47 | Build(T2); 48 | 49 | if(IsSimilar(T1, T2)) { 50 | cout << "相似" << endl; 51 | } else { 52 | cout << "不相似" << endl; 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_3_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/29. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | int tag; // 标志域 13 | struct BiNode * lchild, * rchild; 14 | } BiNode, * BiTree; 15 | 16 | // 改成非递归需要用到栈,栈中的数据类型是BiNode *: 17 | # define MaxSize 100 18 | typedef struct Stack{ 19 | BiNode * data[MaxSize]; // 栈中存放的是指向节点的指针 20 | int top = -1; // 栈顶指针 21 | }Stack; 22 | 23 | void Push(Stack & S, BiNode * a) { 24 | if(S.top == MaxSize - 1) { 25 | cout << "栈满" << endl; 26 | return; 27 | } else { 28 | S.data[ ++ S.top] = a; 29 | } 30 | } 31 | 32 | void Pop(Stack & S, BiNode * & a) { 33 | if(S.top == - 1) { 34 | cout << "栈空" << endl; 35 | return; 36 | } else { 37 | a = S.data[S.top -- ]; 38 | } 39 | } 40 | 41 | void GetTop(Stack & S, BiNode * & a) { 42 | if(S.top == - 1) { 43 | cout << "栈空" << endl; 44 | return; 45 | } else { 46 | a = S.data[S.top]; 47 | } 48 | } 49 | // 判断栈S是否为空,若为空,则返回true,否则为false 50 | int IsEmpty(Stack S) { 51 | return S.top == -1; 52 | } 53 | 54 | 55 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 56 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 57 | int i = 0; 58 | void Build(BiTree & T) { 59 | char ch = a[i]; i++; 60 | if(ch == '#') // 如果是#,则说明这个节点是空的 61 | T = NULL; 62 | else { 63 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 64 | T -> data = ch; // 为其赋值 65 | T -> tag = 0; // 标志域,表示还没有被访问过 66 | T -> lchild = NULL; // 左右孩子都设置为空 67 | T -> rchild = NULL; 68 | Build(T -> lchild); // 递归创建左孩子 69 | Build(T -> rchild); // 递归创建右孩子 70 | } 71 | } 72 | 73 | // 递归版后序遍历 74 | void TraverseBack(BiTree T) { 75 | if(T) { 76 | TraverseBack(T -> lchild); 77 | TraverseBack(T -> rchild); 78 | cout << T -> data << " "; 79 | } 80 | } 81 | 82 | // 非递归版本后序遍历 83 | void TraverseBackNonRec(BiTree T) { 84 | Stack S; 85 | BiNode * p = T; 86 | 87 | while(p || !IsEmpty(S)) { 88 | if(p) { // 步骤一:沿着根的左孩子,依次入栈,直到左孩子为空 89 | Push(S, p); 90 | p = p -> lchild; 91 | } else { // 读栈顶元素,若其右孩子不空并且未被访问过,右子树执行步骤1(下一个循环) 92 | GetTop(S, p); 93 | if(p -> rchild && p -> rchild -> tag == 0) { 94 | p = p -> rchild; 95 | } else { 96 | Pop(S, p); // 将节点弹出,并且访问,最后需要将p设置为空,以便于从栈中查看节点 97 | cout << p -> data << " "; 98 | p -> tag = 1; 99 | p = NULL; 100 | } 101 | } 102 | } 103 | } 104 | 105 | int main() { 106 | BiTree T; 107 | Build(T); 108 | TraverseBack(T); // 递归版 109 | TraverseBackNonRec(T); //非递归版 110 | 111 | return 0; 112 | } -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/30. 3 | // 4 | 5 | // 自上而下,从右到左的遍历顺序,就是将自上而下,自左到右的遍历方式(也就是所谓的层序遍历)逆序一下 6 | #include 7 | using namespace std; 8 | 9 | // 二叉树使用的是例图中的结构 10 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 11 | typedef struct BiNode { 12 | char data; // 数据域 13 | struct BiNode * lchild, * rchild; 14 | } BiNode, * BiTree; 15 | 16 | 17 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 18 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 19 | int i = 0; 20 | void Build(BiTree & T) { 21 | char ch = a[i]; i++; 22 | if(ch == '#') // 如果是#,则说明这个节点是空的 23 | T = NULL; 24 | else { 25 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 26 | T -> data = ch; // 为其赋值 27 | T -> lchild = NULL; // 左右孩子都设置为空 28 | T -> rchild = NULL; 29 | Build(T -> lchild); // 递归创建左孩子 30 | Build(T -> rchild); // 递归创建右孩子 31 | } 32 | } 33 | 34 | // 栈结构如下 ************************************************** 35 | # define MaxSize 100 36 | typedef struct Stack{ 37 | BiNode * data[MaxSize]; // 栈中存放的是指向节点的指针 38 | int top = -1; // 栈顶指针 39 | }Stack; 40 | 41 | void Push(Stack & S, BiNode * a) { 42 | if(S.top == MaxSize - 1) { 43 | cout << "栈满" << endl; 44 | return; 45 | } else { 46 | S.data[ ++ S.top] = a; 47 | } 48 | } 49 | 50 | void Pop(Stack & S, BiNode * & a) { 51 | if(S.top == - 1) { 52 | cout << "栈空" << endl; 53 | return; 54 | } else { 55 | a = S.data[S.top -- ]; 56 | } 57 | } 58 | 59 | void GetTop(Stack & S, BiNode * & a) { 60 | if(S.top == - 1) { 61 | cout << "栈空" << endl; 62 | return; 63 | } else { 64 | a = S.data[S.top]; 65 | } 66 | } 67 | // 判断栈S是否为空,若为空,则返回true,否则为false 68 | int IsStackEmpty(Stack S) { 69 | return S.top == -1; 70 | } 71 | 72 | 73 | // 层序遍历还需要使用队列 74 | // 队列结构如下 ************************************************** 75 | typedef struct Queue { 76 | int rear, front, tag; 77 | BiNode * buffer[MaxSize]; // 存放节点指针 78 | } Queue; 79 | 80 | // 入队 81 | void Enqueue(Queue & que, BiNode * data) { // 将data加入队列 82 | //判断队列是否已满 83 | if(que.rear == que.front && que.tag == 1) { 84 | cout << "塞不下啦!" << endl; 85 | return; 86 | } 87 | 88 | que.buffer[que.rear] = data; 89 | que.rear = (que.rear + 1) % MaxSize; 90 | que.tag = 1; 91 | } 92 | 93 | int IsQueEmpty(Queue que) { 94 | return que.rear == que.front && que.tag == 0; 95 | } 96 | 97 | void Dequeue(Queue & que, BiNode * & data) { // 队列出队,将出队元素的值赋值给data 98 | // 判断队列是否为空 99 | if(que.rear == que.front && que.tag == 0) { 100 | cout << "真没有出的了哥" << endl; 101 | return; 102 | } 103 | 104 | data = que.buffer[que.front]; 105 | que.front = (que.front + 1) % MaxSize; 106 | que.tag = 0; 107 | } 108 | 109 | void InitQueue(Queue & que) { 110 | que.tag = que.front = que.rear = 0; 111 | } 112 | 113 | void PrePrint(BiTree T) { // 先序遍历 114 | if(T) { 115 | cout << T -> data << " "; 116 | PrePrint(T -> lchild); 117 | PrePrint(T -> rchild); 118 | } 119 | 120 | } 121 | 122 | void TraverseByReverseLevel(BiTree T) { // 反层序遍历 123 | Stack s; 124 | Queue que; 125 | InitQueue(que); 126 | 127 | Enqueue(que, T); 128 | 129 | while(!IsQueEmpty(que)) { // 层序遍历的模板,可以拓展深度优先搜索哦 130 | BiNode * p; 131 | Dequeue(que, p); // 出队 132 | 133 | Push(s, p); // 先不急输出,压栈,以便实现反层序遍历,如果直接输出就是普通的层序遍历 134 | 135 | if(p -> lchild) 136 | Enqueue(que, p -> lchild); 137 | if(p -> rchild) 138 | Enqueue(que, p -> rchild); 139 | } 140 | 141 | while(!IsStackEmpty(s)) { // 将栈里面的元素全部拿出来输出 142 | BiNode * p; 143 | Pop(s, p); 144 | cout << p -> data << " "; 145 | } 146 | } 147 | 148 | int main() { 149 | BiTree T; 150 | Build(T); // 构建二叉树 151 | TraverseByReverseLevel(T); 152 | return 0; 153 | } 154 | -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/6/30. 3 | // 4 | // 算法思路,采用另一套层序遍历的模板,来记录一共有多少层 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | struct BiNode * lchild, * rchild; 13 | } BiNode, * BiTree; 14 | 15 | 16 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 17 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 18 | int i = 0; 19 | void Build(BiTree & T) { 20 | char ch = a[i]; i++; 21 | if(ch == '#') // 如果是#,则说明这个节点是空的 22 | T = NULL; 23 | else { 24 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 25 | T -> data = ch; // 为其赋值 26 | T -> lchild = NULL; // 左右孩子都设置为空 27 | T -> rchild = NULL; 28 | Build(T -> lchild); // 递归创建左孩子 29 | Build(T -> rchild); // 递归创建右孩子 30 | } 31 | } 32 | 33 | int maxv(int a, int b) { 34 | return a > b ? a : b; 35 | } 36 | 37 | // 递归求树高 38 | int GetHeight(BiTree T) { 39 | if(T == NULL) 40 | return 0; 41 | return maxv(GetHeight(T -> lchild), GetHeight(T -> rchild)) + 1; 42 | } 43 | 44 | # define MaxSize 100 45 | 46 | // 非递归求树高 47 | int GetHeightNonRec(BiTree T) { 48 | int front = -1, rear = -1; // 队头和队尾指针 49 | int last = 0, level = 0; // last是当前层的最右边节点,level就是层号 50 | 51 | BiNode * Que[MaxSize]; 52 | Que[++ rear] = T; // 根节点入队 53 | BiNode * p; 54 | 55 | while(front < rear) { 56 | p = Que[++ front]; //出队 57 | if(p -> lchild) 58 | Que[++ rear] = p -> lchild; 59 | if(p -> rchild) 60 | Que[++ rear] = p -> rchild; 61 | 62 | if(front == last) { // 重点,当front到达了last后,说明这一层已经结束了 63 | level ++; // 手动模拟下更容易理解 64 | last = rear; 65 | } 66 | } 67 | 68 | return level; 69 | } 70 | 71 | int main() { 72 | BiTree T; 73 | Build(T); 74 | // 计算二叉树的高度 75 | cout << GetHeight(T) << endl; // 递归版 76 | cout << GetHeightNonRec(T) << endl; // 非递归版 77 | return 0; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_6_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/1. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | struct BiNode * lchild, * rchild; 13 | } BiNode, * BiTree; 14 | 15 | 16 | char A[9] = {'A', 'B' ,'D', 'E', 'C', 'F', 'H', 'I', 'G'}; 17 | char B[9] = {'D', 'B', 'E', 'A', 'H', 'F', 'I', 'C', 'G'}; 18 | 19 | BiTree CreateBiTree(int s1, int e1, int s2, int e2) {//s1和e1表示先序序列的起点和终点,s2和e2表示中序序列的起点和终点 20 | BiTree T = (BiTree) malloc(sizeof(BiNode)); 21 | T -> data = A[s1]; //创建根节点 22 | 23 | int i; 24 | for(i = s2; B[i] != A[s1]; ++i); // 空语句循环,目的是为了找到下一个中序遍历的分割线 25 | 26 | int llen = i - s2; // 得到左子树的长度 27 | int rlen = e2 - i; // 得到右子树的长度 28 | 29 | if(llen) { 30 | // 根据中间节点将中序和先序序列划分开 31 | T -> lchild = CreateBiTree(s1 + 1, s1 + llen, s2, s2 + llen - 1); 32 | } else { 33 | T -> lchild = NULL; 34 | } 35 | 36 | if(rlen) { 37 | T -> rchild = CreateBiTree(s1 + llen + 1, e1 , e2 - rlen + 1, e2); 38 | } else { 39 | T -> rchild = NULL; 40 | } 41 | return T; 42 | } 43 | 44 | // 测试创建效果 45 | void PreOrder(BiTree T) { 46 | if (T) { 47 | cout << T -> data << " "; 48 | PreOrder(T -> lchild); 49 | PreOrder(T -> rchild); 50 | } 51 | } 52 | 53 | int main() { 54 | BiTree T; 55 | 56 | T = CreateBiTree(0, 8, 0, 8); 57 | 58 | PreOrder(T); 59 | return 0; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_7_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/1. 3 | // 判断一棵树是否为完全二叉树 4 | 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | struct BiNode * lchild, * rchild; 13 | } BiNode, * BiTree; 14 | 15 | #define MaxSize 100 16 | 17 | // 队列结构如下 ************************************************** 18 | typedef struct Queue { 19 | int rear, front, tag; 20 | BiNode * buffer[MaxSize]; // 存放节点指针 21 | } Queue; 22 | 23 | // 入队 24 | void Enqueue(Queue & que, BiNode * data) { // 将data加入队列 25 | //判断队列是否已满 26 | if(que.rear == que.front && que.tag == 1) { 27 | cout << "塞不下啦!" << endl; 28 | return; 29 | } 30 | 31 | que.buffer[que.rear] = data; 32 | que.rear = (que.rear + 1) % MaxSize; 33 | que.tag = 1; 34 | } 35 | 36 | int IsQueEmpty(Queue que) { 37 | return que.rear == que.front && que.tag == 0; 38 | } 39 | 40 | void Dequeue(Queue & que, BiNode * & data) { // 队列出队,将出队元素的值赋值给data 41 | // 判断队列是否为空 42 | if(que.rear == que.front && que.tag == 0) { 43 | cout << "真没有出的了哥" << endl; 44 | return; 45 | } 46 | 47 | data = que.buffer[que.front]; 48 | que.front = (que.front + 1) % MaxSize; 49 | que.tag = 0; 50 | } 51 | 52 | void InitQueue(Queue & que) { 53 | que.tag = que.front = que.rear = 0; 54 | } 55 | 56 | 57 | // 使用二叉树的先序序列来构造一颗二叉树,其中#表示指针域为空 58 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 59 | int i = 0; 60 | void Build(BiTree & T) { 61 | char ch = a[i]; i++; 62 | if(ch == '#') // 如果是#,则说明这个节点是空的 63 | T = NULL; 64 | else { 65 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 66 | T -> data = ch; // 为其赋值 67 | T -> lchild = NULL; // 左右孩子都设置为空 68 | T -> rchild = NULL; 69 | Build(T -> lchild); // 递归创建左孩子 70 | Build(T -> rchild); // 递归创建右孩子 71 | } 72 | } 73 | 74 | void PreOrder(BiTree T) { 75 | if(T) { 76 | cout << T -> data << " "; 77 | PreOrder(T -> lchild); 78 | PreOrder(T -> rchild); 79 | } 80 | } 81 | // 判断是否为完全二叉树:按照从上到下从左到右的顺序遍历,找到第一个没有孩子的节点 82 | // 如果该节点后面的节点存在孩子节点,则说明不是完全二叉树,否则是完全二叉树 83 | bool check(BiTree T) { 84 | Queue que; 85 | InitQueue(que); 86 | 87 | Enqueue(que, T); 88 | 89 | int flag = 0; //flag若为零,则说明第一个没有孩子的节点还没找 90 | 91 | 92 | while(!IsQueEmpty(que)) { 93 | BiNode * p = NULL; 94 | Dequeue(que, p); 95 | 96 | 97 | if(p -> lchild == NULL && flag == 0) { // 第一个 98 | flag = 1; 99 | } else if (p -> lchild != NULL && flag == 1) { // 如果又出现孩子了 100 | return false; 101 | } 102 | 103 | 104 | if(p -> lchild) { 105 | Enqueue(que, p -> lchild); 106 | } 107 | if(p -> rchild) { 108 | Enqueue(que, p -> rchild); 109 | } 110 | 111 | } 112 | return true; 113 | } 114 | 115 | int main() { 116 | BiTree T; 117 | Build(T); 118 | 119 | PreOrder(T); cout << endl; 120 | 121 | if(check(T)) { 122 | cout << "是完全二叉树" << endl; 123 | } else { 124 | cout << "不是完全二叉树" << endl; 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_8_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/2. 3 | // 计算双分枝节点的个数 4 | 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | struct BiNode * lchild, * rchild; 13 | } BiNode, * BiTree; 14 | 15 | // 二叉树的创建 16 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 17 | int i = 0; 18 | void Build(BiTree & T) { 19 | char ch = a[i]; i++; 20 | if(ch == '#') // 如果是#,则说明这个节点是空的 21 | T = NULL; 22 | else { 23 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 24 | T -> data = ch; // 为其赋值 25 | T -> lchild = NULL; // 左右孩子都设置为空 26 | T -> rchild = NULL; 27 | Build(T -> lchild); // 递归创建左孩子 28 | Build(T -> rchild); // 递归创建右孩子 29 | } 30 | } 31 | 32 | void PreOrder(BiTree T) { 33 | if(T) { 34 | cout << T -> data << " "; 35 | PreOrder(T -> lchild); 36 | PreOrder(T -> rchild); 37 | } 38 | } 39 | 40 | int Calculate(BiTree T) { 41 | if(T == NULL) 42 | return 0; 43 | // 只要有一个为空,就说明没有双分枝 44 | if(T -> lchild == NULL || T -> rchild == NULL) 45 | return Calculate(T -> lchild) + Calculate(T -> rchild); 46 | // 若左孩子和右孩子都有,那么递归计算 47 | if(T -> lchild && T -> rchild) 48 | return Calculate(T -> lchild) + Calculate(T -> rchild) + 1; 49 | } 50 | 51 | int main() { 52 | BiTree T; 53 | Build(T); 54 | cout << Calculate(T) << endl; 55 | } 56 | -------------------------------------------------------------------------------- /chapter_5/5.3.3/5.3.3_9_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/2. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | // 二叉树使用的是例图中的结构 9 | // 二叉树的前序序列为:ABD##E##CFH##I##G## 10 | typedef struct BiNode { 11 | char data; // 数据域 12 | struct BiNode * lchild, * rchild; 13 | } BiNode, * BiTree; 14 | 15 | // 二叉树的创建 16 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 17 | int i = 0; 18 | void Build(BiTree & T) { 19 | char ch = a[i]; i++; 20 | if(ch == '#') // 如果是#,则说明这个节点是空的 21 | T = NULL; 22 | else { 23 | T = (BiTree) malloc(sizeof(BiNode)); // 申请一个节点空间 24 | T -> data = ch; // 为其赋值 25 | T -> lchild = NULL; // 左右孩子都设置为空 26 | T -> rchild = NULL; 27 | Build(T -> lchild); // 递归创建左孩子 28 | Build(T -> rchild); // 递归创建右孩子 29 | } 30 | } 31 | 32 | void PreOrder(BiTree T) { 33 | if(T) { 34 | cout << T -> data << " "; 35 | PreOrder(T -> lchild); 36 | PreOrder(T -> rchild); 37 | } 38 | } 39 | 40 | void MidOrder(BiTree T) { 41 | if(T) { 42 | MidOrder(T -> lchild); 43 | cout << T -> data << " "; 44 | MidOrder(T -> rchild); 45 | } 46 | } 47 | 48 | // 交换左右子树 49 | void SwapLchildRchild(BiTree T) { 50 | if(!T) return; 51 | 52 | BiTree tmp = T -> lchild; 53 | T -> lchild = T -> rchild; 54 | T -> rchild = tmp; 55 | 56 | SwapLchildRchild(T -> lchild); 57 | SwapLchildRchild(T -> rchild); 58 | } 59 | 60 | int main() { 61 | BiTree T; 62 | Build(T); 63 | cout << "交换前的先序:"; 64 | PreOrder(T); 65 | cout << "交换前的中序:"; 66 | MidOrder(T); 67 | cout << endl; 68 | 69 | SwapLchildRchild(T); 70 | 71 | cout << "交换后的先序:"; 72 | PreOrder(T); 73 | cout << "交换后的中序:"; 74 | MidOrder(T); 75 | 76 | } -------------------------------------------------------------------------------- /chapter_5/5.3.3/例图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_5/5.3.3/例图.png -------------------------------------------------------------------------------- /chapter_5/5.3.3/第11题的例图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_5/5.3.3/第11题的例图.png -------------------------------------------------------------------------------- /chapter_5/5.3.3/第十五题例图.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_5/5.3.3/第十五题例图.jpeg -------------------------------------------------------------------------------- /chapter_5/5.4.4/5.4.4_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/12. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct CSNode { 9 | char data; 10 | struct CSNode * firstchild, * nextsibling; 11 | } CSNode, * CSTree; 12 | 13 | char a[] = {'A','B','D','#', '#','E','#','#','C','F','H','#','#','I','#','#','G','#','#'}; 14 | int i = 0; 15 | void build(CSTree & T) { 16 | char ch = a[i ++]; 17 | if(ch == '#') { 18 | T = NULL; 19 | } else { 20 | T = (CSNode *) malloc(sizeof(CSNode)); 21 | T -> data = ch; 22 | T -> firstchild = NULL; 23 | T -> nextsibling = NULL; 24 | build(T -> firstchild); 25 | build(T -> nextsibling); 26 | } 27 | } 28 | 29 | int getLeaves(CSTree T) { 30 | if(T == NULL) { // 如果结点为空,则没有叶子结点 31 | return 0; 32 | } else if(T -> firstchild == NULL) { // 如果没有孩子,说明是叶子 33 | return getLeaves(T -> nextsibling) + 1; 34 | } else { // 分支结点,去左右两边找 35 | return getLeaves(T -> firstchild) + getLeaves(T -> nextsibling); 36 | } 37 | } 38 | 39 | int main() { 40 | CSTree T; 41 | build(T); 42 | cout << getLeaves(T) << endl; 43 | return 0; 44 | } -------------------------------------------------------------------------------- /chapter_5/5.4.4/5.4.4_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/12. 3 | // 求孩子兄弟表示的树的高度 4 | 5 | 6 | #include 7 | using namespace std; 8 | 9 | typedef struct CSNode { 10 | char data; 11 | struct CSNode * firstchild, * nextsibling; 12 | } CSNode, * CSTree; 13 | 14 | char a[] = {'A','B','D','#', '#','E','#','#', '#'}; 15 | int i = 0; 16 | void build(CSTree & T) { 17 | char ch = a[i ++]; 18 | if(ch == '#') { 19 | T = NULL; 20 | } else { 21 | T = (CSNode *) malloc(sizeof(CSNode)); 22 | T -> data = ch; 23 | T -> firstchild = NULL; 24 | T -> nextsibling = NULL; 25 | build(T -> firstchild); 26 | build(T -> nextsibling); 27 | } 28 | } 29 | 30 | int getHeight(CSTree T) { 31 | if(T == NULL) // 空节点对于高度没有贡献 32 | return 0; 33 | else { // 不是空节点,有孩子或者兄弟, 在子女高度+1 与 右兄弟中选出最高的 34 | return max(getHeight(T -> firstchild) + 1, getHeight(T -> nextsibling)); 35 | } 36 | } 37 | 38 | int main() { 39 | CSTree T; 40 | build(T); 41 | cout << getHeight(T) << endl; 42 | return 0; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /chapter_5/5.4.4/树及其对应的二叉树的例图.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_5/5.4.4/树及其对应的二叉树的例图.jpeg -------------------------------------------------------------------------------- /chapter_5/5.4.4/森林及其对应的二叉树例图.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_5/5.4.4/森林及其对应的二叉树例图.jpeg -------------------------------------------------------------------------------- /chapter_6/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_6/.DS_Store -------------------------------------------------------------------------------- /chapter_6/6.2.6/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_6/6.2.6/.DS_Store -------------------------------------------------------------------------------- /chapter_6/6.2.6/6.2.6_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/16. 3 | // 4 | 5 | /* 6 | 7 | 输入样例: 8 | 5 7 9 | a b c d e 10 | a b 11 | a e 12 | b c 13 | b d 14 | b e 15 | c d 16 | d e 17 | 18 | * */ 19 | 20 | 21 | #include 22 | using namespace std; 23 | 24 | #define MaxVertexNum 100 25 | 26 | //*****************************************// 邻接表的结构 27 | // 边表结点 28 | typedef struct ArcNode { 29 | int adjvex; //当前结点的编号 30 | ArcNode * next; //指向下一个结点的指针 31 | } ArcNode; 32 | 33 | //顶点表结点 34 | typedef struct VNode { 35 | char data; // 用于存放结点编号所对应的数据 36 | ArcNode * first; // 指向与该边相链接的第一个边表结点 37 | } VNode, AdjList[MaxVertexNum]; // 这里的AdjList表示定义了一个数组,数组中的每个元素的类型是VNode型,以后可以直接使用AdjList a; 表示创建一个名为a的数组 38 | 39 | // 图结构 Adjacency List -- 邻接表 40 | typedef struct ALGraph { 41 | AdjList vertices; // 图包含链接表 42 | int vertexnum, arcnum; //结点的个数以及弧的数量 43 | }; 44 | 45 | //*****************************************// 邻接矩阵的结构 46 | typedef struct MatrixGraph { 47 | int Matrix[MaxVertexNum][MaxVertexNum]; 48 | int vertexnum; 49 | } MGraph; 50 | 51 | // 根据结点的数据来查找对应的编号 52 | int Locate(ALGraph & G, char x) { 53 | for(int i = 0; i < G.vertexnum; ++i) { 54 | if(G.vertices[i].data == x) { 55 | return i; 56 | } 57 | } 58 | return -1; // 若找不到就返回-1 59 | } 60 | 61 | // 创建图 62 | void CreateGraph(ALGraph & G) { 63 | cout << "输入结点数和边数,并且用空格来隔开:"; 64 | cin >> G.vertexnum >> G.arcnum; 65 | 66 | // 顶点表信息保存: 67 | for(int i = 1; i <= G.vertexnum; ++i) { 68 | cout << "输入第" << i << "个顶点的信息:"; 69 | cin >> G.vertices[i - 1].data; 70 | G.vertices[i - 1].first = NULL; 71 | } 72 | 73 | // 边表信息保存: 74 | for(int i = 1; i <= G.arcnum; ++i) { 75 | char e1, e2; // 两个结点可以确定一条边 76 | cout << "输入第" << i << "条边的顶点:"; 77 | cin >> e1 >> e2; //输入边 78 | 79 | // 根据输入的结点值找到其所对应的下标 80 | int vi = Locate(G, e1); 81 | int vj = Locate(G, e2); 82 | 83 | // 开始插入, 先将vj插入到vi的后面 84 | ArcNode * e = new ArcNode; // 申请一个边表结点空间 85 | e -> adjvex = vj; 86 | e -> next = G.vertices[vi].first; 87 | G.vertices[vi].first = e; 88 | 89 | // 再将vi插入到vj的后面 90 | e = new ArcNode; 91 | e -> adjvex = vi; 92 | e -> next = G.vertices[vj].first; 93 | G.vertices[vj].first = e; 94 | } 95 | } 96 | 97 | // 深度优先搜索: 98 | 99 | bool visited[MaxVertexNum]; 100 | 101 | void DFS(ALGraph G, int i) { // 从结点i开始进行深度优先遍历 102 | visited[i] = true; 103 | ArcNode * p; 104 | cout << G.vertices[i].data << " "; 105 | p = G.vertices[i].first; 106 | 107 | while(p) { 108 | if(!visited[p -> adjvex]) { 109 | DFS(G, p -> adjvex); 110 | } 111 | p = p -> next; 112 | } 113 | } 114 | 115 | void DFSTraverse(ALGraph G) { 116 | for(int i = 0; i < G.vertexnum; ++i) { 117 | if(!visited[i]) 118 | DFS(G, i); 119 | } 120 | } 121 | 122 | 123 | void Adjency2Matrix(ALGraph & G, MGraph & MG) { 124 | ArcNode * p; 125 | for(int i = 0; i < G.vertexnum; ++i) { 126 | p = G.vertices[i].first; 127 | while(p) { 128 | MG.Matrix[i][p -> adjvex] = 1; 129 | p = p -> next; 130 | } 131 | 132 | } 133 | } 134 | 135 | int main() { 136 | ALGraph G; 137 | CreateGraph(G); 138 | MGraph MG; 139 | MG.vertexnum = G.vertexnum; 140 | Adjency2Matrix(G, MG); 141 | 142 | for(int i = 0; i < MG.vertexnum; ++i) { 143 | for(int j = 0; j < MG.vertexnum; ++j) { 144 | cout << MG.Matrix[i][j] << " "; 145 | } 146 | cout << endl; 147 | } 148 | 149 | return 0; 150 | } 151 | -------------------------------------------------------------------------------- /chapter_6/6.2.6/Example_AList_ALGraph.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/16. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | #define MaxVertexNum 100 9 | 10 | // 边表结点 11 | typedef struct ArcNode { 12 | int adjvex; //当前结点的编号 13 | ArcNode * next; //指向下一个结点的指针 14 | } ArcNode; 15 | 16 | //顶点表结点 17 | typedef struct VNode { 18 | char data; // 用于存放结点编号所对应的数据 19 | ArcNode * first; // 指向与该边相链接的第一个边表结点 20 | } VNode, AdjList[MaxVertexNum]; // 这里的AdjList表示定义了一个数组,数组中的每个元素的类型是VNode型,以后可以直接使用AdjList a; 表示创建一个名为a的数组 21 | 22 | // 图结构 23 | typedef struct ALGraph { 24 | AdjList vertices; // 图包含链接表 25 | int vertexnum, arcnum; //结点的个数以及弧的数量 26 | }; 27 | 28 | // 根据结点的数据来查找对应的编号 29 | int Locate(ALGraph & G, char x) { 30 | for(int i = 1; i <= G.vertexnum; ++i) { 31 | if(G.vertices[i].data == x) { 32 | return i; 33 | } 34 | } 35 | return -1; // 若找不到就返回-1 36 | } 37 | 38 | // 创建图 39 | void CreateGraph(ALGraph & G) { 40 | cout << "输入结点数和边数,并且用空格来隔开:"; 41 | cin >> G.vertexnum >> G.arcnum; 42 | 43 | // 顶点表信息保存: 44 | for(int i = 1; i <= G.vertexnum; ++i) { 45 | cout << "输入第" << i << "个顶点的信息:"; 46 | cin >> G.vertices[i - 1].data; 47 | G.vertices[i - 1].first = NULL; 48 | } 49 | 50 | // 边表信息保存: 51 | for(int i = 1; i <= G.arcnum; ++i) { 52 | char e1, e2; // 两个结点可以确定一条边 53 | cout << "输入第" << i << "条边的顶点:"; 54 | cin >> e1 >> e2; //输入边 55 | 56 | // 根据输入的结点值找到其所对应的下标 57 | int vi = Locate(G, e1); 58 | int vj = Locate(G, e2); 59 | 60 | // 开始插入, 先将vj插入到vi的后面 61 | ArcNode * e = new ArcNode; // 申请一个边表结点空间 62 | e -> adjvex = vj; 63 | e -> next = G.vertices[vi].first; 64 | G.vertices[vi].first = e; 65 | 66 | // 再将vi插入到vj的后面 67 | e = new ArcNode; 68 | e -> adjvex = vi; 69 | e -> next = G.vertices[vj].first; 70 | G.vertices[vj].first = e; 71 | } 72 | } 73 | 74 | // 深度优先搜索: 75 | 76 | bool visited[MaxVertexNum]; 77 | 78 | void DFS(ALGraph G, int i) { // 从结点i开始进行深度优先遍历 79 | visited[i] = true; 80 | ArcNode * p; 81 | cout << G.vertices[i].data << " "; 82 | p = G.vertices[i].first; 83 | 84 | while(p) { 85 | if(!visited[p -> adjvex]) { 86 | DFS(G, p -> adjvex); 87 | } 88 | p = p -> next; 89 | } 90 | } 91 | 92 | void DFSTraverse(ALGraph G) { 93 | for(int i = 0; i < G.vertexnum; ++i) { 94 | if(!visited[i]) 95 | DFS(G, i); 96 | } 97 | } 98 | 99 | int main() { 100 | ALGraph G; 101 | CreateGraph(G); 102 | DFSTraverse(G); 103 | 104 | return 0; 105 | } 106 | 107 | 108 | -------------------------------------------------------------------------------- /chapter_6/6.2.6/Example_Matrix_Graph.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/15. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | #define MaxVertexNum 100 9 | typedef struct { 10 | char Vex[MaxVertexNum] = {'a', 'b', 'c', 'd', 'e'}; //顶点表 11 | int Edge[MaxVertexNum][MaxVertexNum] = {{0, 1, 0, 0, 1}, {1, 0, 1, 1, 1}, {0, 1, 0, 1, 0}, {0, 1, 1, 0, 1}, {1, 1, 0, 1, 0}}; 12 | int vexnum, arcnum; //分别是顶点数和边数 13 | }MGraph; 14 | 15 | 16 | int map[10][10] = {{0, 1, 0, 0, 1}, {1, 0, 1, 1, 1}, {0, 1, 0, 1, 0}, {0, 1, 1, 0, 1}, {1, 1, 0, 1, 0}}; 17 | 18 | int main() { 19 | MGraph graph; 20 | graph.vexnum = 5; 21 | graph.arcnum = 7; 22 | 23 | // 打印图结点: 24 | for(int i = 0; i < graph.vexnum; i ++) { 25 | for (int j = 0; j < graph.vexnum; j ++ ) { 26 | cout << graph.Edge[i][j] << " "; 27 | } 28 | cout << endl; 29 | } 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /chapter_6/6.2.6/样例图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_6/6.2.6/样例图.png -------------------------------------------------------------------------------- /chapter_6/6.3.4/6.3.4_2_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/16. 3 | // 4 | 5 | // 对图G进行DFS,并且记录访问的边的数量,若 6 | // 1. 没有未访问完的顶点 7 | // 2. e = n - 1 8 | 9 | 10 | /* 11 | 图的输入样例如下 12 | 5 7 13 | a b c d e 14 | a b 15 | a e 16 | b c 17 | b d 18 | b e 19 | c d 20 | d e 21 | 树的输入样例如下 22 | 5 4 23 | a b c d e 24 | a b 25 | a c 26 | a d 27 | b e 28 | */ 29 | 30 | 31 | #include 32 | using namespace std; 33 | 34 | #define MaxVertexNum 100 35 | 36 | //*****************************************// 邻接表的结构 37 | // 边表结点 38 | typedef struct ArcNode { 39 | int adjvex; //当前结点的编号 40 | ArcNode * next; //指向下一个结点的指针 41 | } ArcNode; 42 | 43 | //顶点表结点 44 | typedef struct VNode { 45 | char data; // 用于存放结点编号所对应的数据 46 | ArcNode * first; // 指向与该边相链接的第一个边表结点 47 | } VNode, AdjList[MaxVertexNum]; // 这里的AdjList表示定义了一个数组,数组中的每个元素的类型是VNode型,以后可以直接使用AdjList a; 表示创建一个名为a的数组 48 | 49 | // 图结构 Adjacency List -- 邻接表 50 | typedef struct ALGraph { 51 | AdjList vertices; // 图包含链接表 52 | int vertexnum, arcnum; //结点的个数以及弧的数量 53 | }; 54 | 55 | 56 | // 根据结点值找到结点的编号 57 | int Locate(ALGraph G, char x) { 58 | for(int i = 1; i <= G.vertexnum; ++i) { 59 | if(G.vertices[i].data == x) 60 | return i; 61 | } 62 | return -1; 63 | } 64 | 65 | // 创建图 66 | void CreateGraph(ALGraph & G) { 67 | cout << "输入结点数和边数,并且用空格来隔开:"; 68 | cin >> G.vertexnum >> G.arcnum; 69 | 70 | // 顶点表信息保存: 71 | for(int i = 1; i <= G.vertexnum; ++i) { 72 | cout << "输入第" << i << "个顶点的信息:"; 73 | cin >> G.vertices[i - 1].data; 74 | G.vertices[i - 1].first = NULL; 75 | } 76 | 77 | // 边表信息保存: 78 | for(int i = 1; i <= G.arcnum; ++i) { 79 | char e1, e2; // 两个结点可以确定一条边 80 | cout << "输入第" << i << "条边的顶点:"; 81 | cin >> e1 >> e2; //输入边 82 | 83 | // 根据输入的结点值找到其所对应的下标 84 | int vi = Locate(G, e1); 85 | int vj = Locate(G, e2); 86 | 87 | // 开始插入, 先将vj插入到vi的后面 88 | ArcNode * e = new ArcNode; // 申请一个边表结点空间 89 | e -> adjvex = vj; 90 | e -> next = G.vertices[vi].first; 91 | G.vertices[vi].first = e; 92 | 93 | // 再将vi插入到vj的后面 94 | e = new ArcNode; 95 | e -> adjvex = vi; 96 | e -> next = G.vertices[vj].first; 97 | G.vertices[vj].first = e; 98 | } 99 | } 100 | 101 | bool visited[MaxVertexNum]; 102 | int edge = 0; // 记录访问过的边的数量 103 | 104 | void DFS(ALGraph G, int x) { // 从顶点x开始进行dfs 105 | visited[x] = true; 106 | ArcNode * p = G.vertices[x].first; 107 | 108 | cout << G.vertices[x].data << " "; 109 | 110 | while(p) { 111 | edge ++; 112 | if(!visited[p -> adjvex]) { 113 | DFS(G, p -> adjvex); 114 | } 115 | p = p -> next; 116 | } 117 | } 118 | 119 | bool GraphIsTree(ALGraph G) { 120 | DFS(G, 0); // 从零号顶点开始dfs 121 | for(int i = 0; i < G.vertexnum; ++i) { 122 | if(visited[i] == false) { 123 | return false; 124 | } 125 | } 126 | cout << edge << endl; 127 | if(edge != 2 * (G.vertexnum - 1) ) { 128 | return false; 129 | } 130 | return true; 131 | } 132 | 133 | 134 | int main() { 135 | ALGraph G; 136 | CreateGraph(G); 137 | if(GraphIsTree(G)) { 138 | cout << "树" << endl; 139 | } else { 140 | cout << "图" << endl; 141 | } 142 | 143 | return 0; 144 | } -------------------------------------------------------------------------------- /chapter_6/6.3.4/6.3.4_3_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/19. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | #define MaxVertexNum 100 9 | 10 | // 边表结点 11 | typedef struct ArcNode{ 12 | int adjvex; 13 | ArcNode * next; 14 | } ArcNode; 15 | 16 | typedef struct VNode { 17 | char data; 18 | ArcNode * first; 19 | } VNode, AdjList[MaxVertexNum]; 20 | 21 | typedef struct ALGraph { 22 | AdjList vertices; 23 | int arcnum, vertexnum; 24 | } ALGraph; 25 | 26 | int Locate(ALGraph G, char data) { 27 | for (int i = 1; i <= G.vertexnum; ++i) { 28 | if(G.vertices[i].data == data) 29 | return i; 30 | } 31 | } 32 | 33 | void CreateGraph(ALGraph & G) { 34 | cin >> G.vertexnum >> G.arcnum; 35 | for(int i = 1; i <= G.vertexnum; ++i) { 36 | cin >> G.vertices[i].data; 37 | G.vertices[i].first = NULL; 38 | } 39 | 40 | for(int i = 0; i < G.arcnum; ++i) { 41 | char e1, e2; 42 | cin >> e1 >> e2; 43 | 44 | int vi = Locate(G, e1); 45 | int vj = Locate(G, e2); 46 | 47 | ArcNode * p = new ArcNode; 48 | p -> adjvex = vj; 49 | p -> next = G.vertices[vi].first; 50 | G.vertices[vi].first = p; 51 | 52 | p = new ArcNode; 53 | p -> adjvex = vi; 54 | p -> next = G.vertices[vj].first; 55 | G.vertices[vj].first = p; 56 | } 57 | } 58 | 59 | 60 | 61 | //非递归版本的DFS需要用到栈这个数据结构: 62 | typedef struct Stack{ 63 | int top = -1; 64 | ArcNode * data[MaxVertexNum]; 65 | }; 66 | 67 | void Push(Stack & S, ArcNode * a) { 68 | if(S.top == MaxVertexNum - 1) { 69 | cout << "栈满" << endl; 70 | return; 71 | } else { 72 | S.data[ ++ S.top] = a; 73 | } 74 | } 75 | 76 | void Pop(Stack & S, ArcNode * & a) { 77 | if(S.top == - 1) { 78 | cout << "栈空" << endl; 79 | return; 80 | } else { 81 | a = S.data[S.top -- ]; 82 | } 83 | } 84 | 85 | bool visited[MaxVertexNum]; 86 | 87 | void DFS(ALGraph G, int cur) { // 访问和BFS差不多,只是将栈换成了队列 88 | cout << G.vertices[cur].data << " "; // 访问当前的这个结点 89 | visited[cur] = true; 90 | 91 | Stack stack; 92 | ArcNode * p = G.vertices[cur].first; 93 | Push(stack, p); 94 | 95 | while(stack.top != -1) { // 如果栈不是空的,说明还没访问完 96 | Pop(stack, p); 97 | 98 | if(!visited[p -> adjvex]) { // 如果这个结点没有被访问过,首先访问,然后将相连的结点加入到栈中以备访问 99 | visited[p -> adjvex] = true; 100 | cout << G.vertices[p -> adjvex].data << " "; 101 | 102 | while(p -> next) { 103 | Push(stack, p -> next); 104 | p = p -> next; 105 | } 106 | } 107 | 108 | 109 | } 110 | } 111 | 112 | void DFSTraverse(ALGraph G) { 113 | for (int i = 0; i < G.vertexnum; ++i) { 114 | if (visited[i] == false) 115 | DFS(G, i); 116 | } 117 | } 118 | 119 | 120 | int main() { 121 | ALGraph G; 122 | CreateGraph(G); 123 | DFSTraverse(G); 124 | return 0; 125 | } -------------------------------------------------------------------------------- /chapter_6/6.3.4/6.3.4_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/23. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | #define MaxVertexNum 100 8 | 9 | // 边表结点 10 | typedef struct ArcNode{ 11 | int adjvex; 12 | ArcNode * next; 13 | } ArcNode; 14 | 15 | typedef struct VNode { 16 | char data; 17 | ArcNode * first; 18 | } VNode, AdjList[MaxVertexNum]; 19 | 20 | typedef struct ALGraph { 21 | AdjList vertices; 22 | int arcnum, vertexnum; 23 | } ALGraph; 24 | 25 | int Locate(ALGraph G, char data) { 26 | for (int i = 1; i <= G.vertexnum; ++i) { 27 | if(G.vertices[i].data == data) 28 | return i; 29 | } 30 | } 31 | 32 | void CreateGraph(ALGraph & G) { 33 | cin >> G.vertexnum >> G.arcnum; 34 | for(int i = 1; i <= G.vertexnum; ++i) { 35 | cin >> G.vertices[i].data; 36 | G.vertices[i].first = NULL; 37 | } 38 | 39 | for(int i = 0; i < G.arcnum; ++i) { 40 | char e1, e2; 41 | cin >> e1 >> e2; 42 | 43 | int vi = Locate(G, e1); 44 | int vj = Locate(G, e2); 45 | 46 | ArcNode * p = new ArcNode; 47 | p -> adjvex = vj; 48 | p -> next = G.vertices[vi].first; 49 | G.vertices[vi].first = p; 50 | 51 | p = new ArcNode; 52 | p -> adjvex = vi; 53 | p -> next = G.vertices[vj].first; 54 | G.vertices[vj].first = p; 55 | } 56 | } 57 | 58 | # define Maxsize 100 59 | 60 | typedef struct Queue { 61 | int rear, front, tag; 62 | int buffer[Maxsize]; 63 | } Queue; 64 | 65 | // 入队 66 | void Enqueue(Queue & que, int data) { // 将data加入队列 67 | //判断队列是否已满 68 | if(que.rear == que.front && que.tag == 1) { 69 | cout << "塞不下啦!" << endl; 70 | return; 71 | } 72 | 73 | que.buffer[que.rear] = data; 74 | que.rear = (que.rear + 1) % Maxsize; 75 | que.tag = 1; 76 | } 77 | 78 | void Dequeue(Queue & que, int & data) { // 队列出队,将出队元素的值赋值给data 79 | // 判断队列是否为空 80 | if(que.rear == que.front && que.tag == 0) { 81 | cout << "真没有出的了哥" << endl; 82 | return; 83 | } 84 | 85 | data = que.buffer[que.front]; 86 | que.front = (que.front + 1) % Maxsize; 87 | que.tag = 0; 88 | } 89 | 90 | int IsQueEmpty(Queue que) { 91 | return que.rear == que.front && que.tag == 0; 92 | } 93 | 94 | bool visited[MaxVertexNum]; 95 | 96 | void DFS(ALGraph G, int i) { 97 | visited[i] = true; 98 | ArcNode * p = G.vertices[i].first; 99 | while(p) { 100 | if(!visited[p -> adjvex]) { 101 | DFS(G, p -> adjvex); 102 | } 103 | p = p -> next; 104 | } 105 | } 106 | 107 | void BFS(ALGraph G, int i) { 108 | // 队列及其初始化工作 109 | Queue que; 110 | que.front = que.rear = que.tag = 0; 111 | 112 | // 标记第i个结点为访问过,并将其编号加入队列 113 | visited[i] = true; 114 | Enqueue(que, i); 115 | 116 | while(!IsQueEmpty(que)) { 117 | int x; 118 | Dequeue(que, x); //取队列头部元素,赋值给x 119 | ArcNode * p = G.vertices[x].first; // 找到相邻元素 120 | 121 | while(p) { 122 | if(!visited[p -> adjvex]) { // 若该结点未访问过 123 | Enqueue(que, p -> adjvex); // 加入队列,标记访问 124 | visited[p -> adjvex] = true; 125 | } 126 | 127 | p = p -> next; 128 | } 129 | } 130 | } 131 | 132 | 133 | bool IsExistPath(ALGraph G, int i, int j) { 134 | // DFS(G, i); //以i为起点进行DFS 135 | BFS(G, i); //以i为起点进行BFS 136 | return visited[j]; //如果j没有访问过,那么就返回false,否则说明有路径,返回true 137 | } 138 | 139 | int main() { 140 | ALGraph G; 141 | cout << "请输入相关信息:" << endl; 142 | CreateGraph(G); 143 | 144 | if(IsExistPath(G, 1, 2)) { 145 | cout << "有路径" << endl; 146 | } else { 147 | cout << "没有路径" << endl; 148 | } 149 | return 0; 150 | } 151 | 152 | /* 153 | 图的相关信息如下: 154 | 5 7 155 | a b c d e 156 | a b 157 | a e 158 | b c 159 | b d 160 | b e 161 | c d 162 | d e 163 | * */ 164 | 165 | 166 | -------------------------------------------------------------------------------- /chapter_6/6.3.4/6.3.4_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/23. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | #define MaxVertexNum 100 8 | 9 | // 边表结点 10 | typedef struct ArcNode{ 11 | int adjvex; 12 | ArcNode * next; 13 | } ArcNode; 14 | 15 | typedef struct VNode { 16 | char data; 17 | ArcNode * first; 18 | } VNode, AdjList[MaxVertexNum]; 19 | 20 | typedef struct ALGraph { 21 | AdjList vertices; 22 | int arcnum, vertexnum; 23 | } ALGraph; 24 | 25 | int Locate(ALGraph G, char data) { 26 | for (int i = 1; i <= G.vertexnum; ++i) { 27 | if(G.vertices[i].data == data) 28 | return i; 29 | } 30 | } 31 | 32 | void CreateGraph(ALGraph & G) { 33 | cin >> G.vertexnum >> G.arcnum; 34 | for(int i = 1; i <= G.vertexnum; ++i) { 35 | cin >> G.vertices[i].data; 36 | G.vertices[i].first = NULL; 37 | } 38 | 39 | for(int i = 0; i < G.arcnum; ++i) { 40 | char e1, e2; 41 | cin >> e1 >> e2; 42 | 43 | int vi = Locate(G, e1); 44 | int vj = Locate(G, e2); 45 | 46 | ArcNode * p = new ArcNode; 47 | p -> adjvex = vj; 48 | p -> next = G.vertices[vi].first; 49 | G.vertices[vi].first = p; 50 | 51 | p = new ArcNode; 52 | p -> adjvex = vi; 53 | p -> next = G.vertices[vj].first; 54 | G.vertices[vj].first = p; 55 | } 56 | } 57 | 58 | // 深度优先搜索 59 | 60 | bool visited[MaxVertexNum]; 61 | int dist[MaxVertexNum]; 62 | 63 | void Path_By_DFS(ALGraph G, int start, int end, int d) { 64 | visited[start] = true; // 标记为访问过 65 | dist[d] = start; // 记录路径 66 | 67 | if(start == end) { // 如果目前访问到了最后的结点,那么将保存在dist数组中的元素都输出即可连成一条路径 68 | for(int i = 0; i <= d; ++i) { 69 | cout << G.vertices[dist[i]].data << " "; 70 | } 71 | cout << endl; 72 | } 73 | 74 | ArcNode * p = G.vertices[start].first; // 访问邻边 75 | while(p) { 76 | if(!visited[p -> adjvex]) { // 如果没有访问过 77 | Path_By_DFS(G, p -> adjvex, end, d + 1); // 访问 78 | } 79 | p = p -> next; 80 | } 81 | visited[start] = false; //恢复现场,因为可能会有其他路径会经过这个结点 82 | } 83 | 84 | /* 85 | *以下是尝试非递归的代码,有bug 86 | */ 87 | 88 | //void Path_By_DFS(ALGraph G, int start, int end) { 89 | // visited[start] = true; 90 | // int stack[100]; 91 | // int top = -1; 92 | // stack[++top] = start; 93 | // int d = 0; 94 | // while(top != -1) { // 栈不空 95 | // int x; 96 | // x = stack[top--]; 97 | // dist[d++] = x; 98 | // 99 | // ArcNode * p = G.vertices[x].first; 100 | // while(p) { 101 | // if(!visited[p -> adjvex]) { 102 | // if (p -> adjvex == end) { //如果到了j,那么将栈中的元素全部输出就是路径 103 | // dist[d++] = end; 104 | // for(int i = 0; i < d; ++i) 105 | // cout << G.vertices[dist[i]].data << " "; 106 | // cout << endl; 107 | // d--; 108 | // } else { 109 | // stack[++top] = p -> adjvex; 110 | // visited[p -> adjvex] = true; 111 | // } 112 | // } 113 | // p = p -> next; 114 | // } 115 | // } 116 | //} 117 | 118 | int main() { 119 | ALGraph G; 120 | cout << "输入图的相关信息:" << endl; 121 | CreateGraph(G); 122 | int start = Locate(G, 'a'), end = Locate(G, 'd'); 123 | Path_By_DFS(G, start, end, 0); // 从a到d的所有路径 124 | return 0; 125 | } 126 | 127 | /* 128 | 5 7 129 | a b c d e 130 | a b 131 | a e 132 | b c 133 | b d 134 | b e 135 | c d 136 | d e 137 | */ -------------------------------------------------------------------------------- /chapter_6/6.3.4/样例图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_6/6.3.4/样例图.png -------------------------------------------------------------------------------- /chapter_7/7.2.4/7.2.4_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/24. 3 | // 折半查找递归版 4 | #include 5 | using namespace std; 6 | 7 | // 假设最开始数组长度为10,元素如下 8 | int a[11] = {0, 1, 5, 9, 11, 15, 17, 19, 20, 21, 25}; 9 | 10 | // 返回所在位置,如果没有则返回-1 11 | int BinarySearch(int a[], int key, int low, int high) { 12 | int mid = (low + high) / 2; 13 | if(low <= high) { 14 | if(a[mid] == key) 15 | return mid; 16 | else if(a[mid] > key) { // 左半边寻找 17 | return BinarySearch(a, key, low, mid - 1); 18 | } else{ // 右半边寻找 19 | return BinarySearch(a, key, mid + 1, high); 20 | } 21 | } else { 22 | return -1; 23 | } 24 | } 25 | 26 | int main() { 27 | cout << BinarySearch(a, 10, 1, 11); // 在a中查找11, low为1, high为表长 28 | return 0; 29 | } -------------------------------------------------------------------------------- /chapter_7/7.2.4/7.2.4_6_LinkedList_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/24. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | int data; 10 | struct Node * next; 11 | } Node, * LinkedList; 12 | 13 | int a[11] = {0, 1, 5, 9, 11, 15, 17, 19, 20, 21, 25}; 14 | 15 | 16 | void CreateList(LinkedList & L) { 17 | // 首先创建一个头结点 18 | L = (LinkedList) malloc(sizeof(Node)); 19 | L -> next = NULL; 20 | LinkedList r = L; 21 | 22 | // 依次创建剩余结点,并采用尾插法 23 | for(int i = 0; i < 11; ++i) { 24 | LinkedList s = (LinkedList) malloc (sizeof(Node)); 25 | s -> data = a[i]; 26 | 27 | r -> next = s; 28 | r = s; 29 | } 30 | 31 | r -> next = NULL; 32 | } 33 | 34 | 35 | int SwitchSearch(LinkedList & L, int key) { 36 | int i = 0; 37 | LinkedList p = L -> next, pre = L; 38 | 39 | while(p) { 40 | if (p -> data == key) { // 如果找到 41 | if(i != 0) { // 不是第一个元素,和其前驱交换 42 | int tmp = p -> data; 43 | p -> data = pre -> data; 44 | pre -> data = tmp; 45 | return i - 1; 46 | } 47 | return i; 48 | } 49 | 50 | // 若没有找到 51 | p = p -> next; 52 | pre = pre -> next; 53 | i = i + 1; 54 | } 55 | // 遍历整表,未找到 56 | return -1; 57 | } 58 | 59 | int main() { 60 | LinkedList L; 61 | CreateList(L); 62 | int key = 9; 63 | cout << "在数组下标为" << SwitchSearch(L, key) << "的位置"; 64 | return 0; 65 | } -------------------------------------------------------------------------------- /chapter_7/7.2.4/7.2.4_6_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/24. 3 | // 4 | 5 | // 找到一个结点的时候,将这个结点与其前驱结点交换 6 | 7 | #include 8 | using namespace std; 9 | 10 | int a[11] = {0, 1, 5, 9, 11, 15, 17, 19, 20, 21, 25}; 11 | 12 | int SwitchSearch(int a[], int key) { 13 | for(int i = 0; i < 11; ++i) { 14 | if(a[i] == key) { 15 | if(i != 0) { // 只要不是第一个元素,就将这个元素和前面的结点交换 16 | int t = a[i]; 17 | a[i] = a[i - 1]; 18 | a[i - 1] = t; 19 | return i - 1; 20 | } 21 | return i; 22 | 23 | } 24 | } 25 | } 26 | 27 | int main() { 28 | int key = 9; 29 | cout << "数组下标在:" << SwitchSearch(a, key) << endl; 30 | 31 | for(int i = 0; i < 11; ++i) { 32 | cout << a[i] << " "; 33 | } 34 | cout << endl; 35 | 36 | return 0; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /chapter_7/7.3.4/7.3.4_10_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/25. 3 | // 设计算法,从大到小输出二叉排序树中所有值不小于k的关键字 4 | 5 | #include 6 | using namespace std; 7 | typedef struct BiNode { 8 | int data; 9 | struct BiNode * lchild, * rchild; 10 | }BiNode, * BiTree; 11 | 12 | // 是二叉排序树的例子 13 | int a[15] = {10, 5, 3, -1, -1, 8, -1, -1, 15, 13, -1, -1, 20, -1, -1}; 14 | int i = 0; 15 | // 创建一棵树 16 | void Build(BiTree & T) { 17 | int data = a[i ++]; // 改这个地方的a或者b切换样例 18 | if(data == -1) { 19 | T = NULL; 20 | } else { 21 | T = (BiTree) malloc(sizeof(BiNode)); 22 | T -> data = data; 23 | T -> lchild = T -> rchild = NULL; 24 | Build(T -> lchild); 25 | Build(T -> rchild); 26 | } 27 | }; 28 | 29 | void PreOrder(BiTree T) { 30 | if(T) { 31 | cout << T -> data << " "; 32 | PreOrder(T -> lchild); 33 | PreOrder(T -> rchild); 34 | } 35 | } 36 | 37 | // 由于二叉排序树的中序遍历是有序的,因此,可以利用中序遍历来输出,而题目要求从大到小,因此可以使用改进的中序遍历,先打印右子树,再打印左子树 38 | void FindBiggerThanK(BiTree T, int k) { 39 | if(T) { 40 | FindBiggerThanK(T -> rchild, k); 41 | if(T -> data >= k) 42 | cout << T -> data << " "; 43 | FindBiggerThanK(T -> lchild, k); 44 | } 45 | } 46 | 47 | int main() { 48 | BiTree T; 49 | Build(T); 50 | int k = 10; 51 | FindBiggerThanK(T, k); 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /chapter_7/7.3.4/7.3.4_6_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/24. 3 | // 编写算法判断所给定的树是否是二叉排序树 4 | 5 | #include 6 | using namespace std; 7 | 8 | #define MaxSize 100 9 | 10 | typedef struct BiNode { 11 | int data; 12 | struct BiNode * lchild, * rchild; 13 | }BiNode, * BiTree; 14 | 15 | // 是二叉排序树的例子 16 | int a[15] = {10, 5, 3, -1, -1, 8, -1, -1, 15, 13, -1, -1, 20, -1, -1}; 17 | // 不是二叉排序树的例子 18 | int b[15] = {10, 5, 6, -1, -1, 8, -1, -1, 15, 13, -1, -1, 20, -1, -1}; 19 | 20 | int i = 0; 21 | 22 | // 创建一棵树 23 | void Build(BiTree & T) { 24 | int data = a[i ++]; // 改这个地方的a或者b切换样例 25 | if(data == -1) { 26 | T = NULL; 27 | } else { 28 | T = (BiTree) malloc(sizeof(BiNode)); 29 | T -> data = data; 30 | T -> lchild = T -> rchild = NULL; 31 | Build(T -> lchild); 32 | Build(T -> rchild); 33 | } 34 | }; 35 | 36 | void PreOrder(BiTree T) { 37 | if(T) { 38 | cout << T -> data << " "; 39 | PreOrder(T -> lchild); 40 | PreOrder(T -> rchild); 41 | } 42 | } 43 | 44 | bool IsSortTree(BiTree T) { 45 | if(T -> lchild && T -> rchild) { // 若左右孩子都存在,首先同一层次相比较,然后递归判断左子树右子树 46 | return T -> lchild -> data <= T -> data && T -> data <= T -> rchild -> data && IsSortTree(T -> lchild) && 47 | IsSortTree(T -> rchild); 48 | } 49 | 50 | if(T -> lchild && T -> rchild == NULL) { // 若只存在左子树,首先同一层次相比较,然后递归判断左子树 51 | return T -> lchild -> data <= T -> data && IsSortTree(T -> lchild); 52 | } 53 | 54 | if(T -> lchild == NULL && T -> rchild) { // 若只存在右子树,首先同一层次相比较,然后递归判断右子树 55 | return T -> rchild -> data >= T -> data && IsSortTree(T -> rchild); 56 | } 57 | 58 | // 边界条件,根据我们前面的判断,T不可能是空树,如果T是空的则不可能进来,但是可能会存在左右子树均为空的情况,这个时候说明到了叶子结点,那么返回true 59 | if(T -> lchild == NULL && T -> rchild == NULL) 60 | return true; 61 | } 62 | 63 | int main() { 64 | BiTree T; 65 | Build(T); 66 | if(IsSortTree(T)) { 67 | cout << "是二叉排序树" << endl; 68 | } else { 69 | cout << "不是二叉排序树" << endl; 70 | } 71 | return 0; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /chapter_7/7.3.4/7.3.4_6_例图.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mach4101/wangdao_exercise/137f707e8cac824a61b801644426b9d1a84840ca/chapter_7/7.3.4/7.3.4_6_例图.jpeg -------------------------------------------------------------------------------- /chapter_7/7.3.4/7.3.4_7_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/24. 3 | // 指定结点在二叉排序树中的层次:每找一次,层次加一 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct BiNode { 9 | int data; 10 | struct BiNode * lchild, * rchild; 11 | }BiNode, * BiTree; 12 | 13 | // 是二叉排序树的例子 14 | int a[15] = {10, 5, 3, -1, -1, 8, -1, -1, 15, 13, -1, -1, 20, -1, -1}; 15 | int i = 0; 16 | // 创建一棵树 17 | void Build(BiTree & T) { 18 | int data = a[i ++]; // 改这个地方的a或者b切换样例 19 | if(data == -1) { 20 | T = NULL; 21 | } else { 22 | T = (BiTree) malloc(sizeof(BiNode)); 23 | T -> data = data; 24 | T -> lchild = T -> rchild = NULL; 25 | Build(T -> lchild); 26 | Build(T -> rchild); 27 | } 28 | }; 29 | 30 | void PreOrder(BiTree T) { 31 | if(T) { 32 | cout << T -> data << " "; 33 | PreOrder(T -> lchild); 34 | PreOrder(T -> rchild); 35 | } 36 | } 37 | 38 | int levelnum = 1; 39 | 40 | void Level(BiTree T, int key) { 41 | if(key < T -> data) { 42 | // 左子树中找 43 | if(T -> lchild) { // 如果左孩子存在,去左子树中找 44 | levelnum ++; 45 | Level(T -> lchild, key); 46 | } 47 | else { // 如果左孩子不存在,那么说明没有找到 48 | levelnum = -1; 49 | } 50 | } else if (key > T -> data) { 51 | if(T -> rchild){ 52 | levelnum ++; 53 | Level(T -> rchild, key); 54 | } else { 55 | levelnum = -1; 56 | } 57 | } else { // 如果找到,就返回 58 | return; 59 | } 60 | 61 | 62 | } 63 | 64 | int main() { 65 | BiTree T; 66 | Build(T); 67 | Level(T, 5); // 在T中查找5这个关键字 68 | cout << levelnum << endl; // 输出层数 69 | return 0; 70 | } 71 | 72 | 73 | -------------------------------------------------------------------------------- /chapter_7/7.3.4/7.3.4_8_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // Created by mach4101 on 2022/7/24. 2 | // 判断一课二叉树是否是高度平衡的二叉树 3 | #include 4 | using namespace std; 5 | 6 | typedef struct BiNode { 7 | int data; 8 | struct BiNode * lchild, * rchild; 9 | }BiNode, * BiTree; 10 | 11 | // 是二叉排序树的例子 12 | int a[15] = {10, 5, 3, -1, -1, 8, -1, -1, 15, 13, -1, -1, 20, -1, -1}; 13 | // 不是二叉排序树的例子 14 | int b[15] = {10, 5, 6, -1, -1, 8, -1, -1, 15, 13, -1, -1, 20, -1, -1}; 15 | 16 | int i = 0; 17 | // 创建一棵树 18 | void Build(BiTree & T) { 19 | int data = b[i ++]; // 改这个地方的a或者b切换样例 20 | if(data == -1) { 21 | T = NULL; 22 | } else { 23 | T = (BiTree) malloc(sizeof(BiNode)); 24 | T -> data = data; 25 | T -> lchild = T -> rchild = NULL; 26 | Build(T -> lchild); 27 | Build(T -> rchild); 28 | } 29 | }; 30 | 31 | void PreOrder(BiTree T) { 32 | if(T) { 33 | cout << T -> data << " "; 34 | PreOrder(T -> lchild); 35 | PreOrder(T -> rchild); 36 | } 37 | } 38 | 39 | int Height(BiTree T) { 40 | if(T == NULL) 41 | return 0; 42 | return max(Height(T -> lchild), Height(T -> rchild)) + 1; 43 | } 44 | 45 | // 算法思路:(王道答案) 46 | /* 1. 若T为空,高度为0,balance=1 47 | * 2. 若T仅有根结点,高度为1,balance=1 48 | * 3. 对左右子树递归运算,返回左右子树的平衡标志以及高度,T的高度是子树的高度加1,如果高度相差大于1,那么balance=0 49 | * 如果高度相差小于等于一,且左右子树的balance都为1的时,balance = 1,否则balance = 0 50 | * */ 51 | void IsBST(BiTree T, int & balance, int & height) { 52 | int left_balance, right_balance, left_height, right_height; 53 | if(T == NULL) { // T为空 54 | balance = 1; 55 | height = 0; 56 | } 57 | else if(T -> lchild == NULL && T -> rchild == NULL) { // T不为空,但是左右子树都是空的 58 | balance = 1; 59 | height = 1; 60 | } else { //其他情况 61 | IsBST(T -> lchild, left_balance, left_height); 62 | IsBST(T -> rchild, right_balance, right_height); 63 | 64 | height = (left_height > right_height) ? left_height + 1 : right_height + 1; // 子树的最大高度加一就是当前结点的最大高度 65 | 66 | if(abs(left_height - right_height) > 2) { 67 | balance = 0; 68 | } else { 69 | balance = left_balance && right_balance; 70 | } 71 | } 72 | 73 | } 74 | 75 | int main() { 76 | BiTree T; 77 | Build(T); 78 | 79 | int balance = 0, height = 0; 80 | IsBST(T, balance, height); 81 | if(balance) { 82 | cout << "是平衡树" << endl; 83 | } else { 84 | cout << "不是平衡树" << endl; 85 | } 86 | return 0; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /chapter_7/7.3.4/7.3.4_9_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/25. 3 | // 求出给定二叉排序树中最小 和 最大的关键字 4 | 5 | #include 6 | using namespace std; 7 | typedef struct BiNode { 8 | int data; 9 | struct BiNode * lchild, * rchild; 10 | }BiNode, * BiTree; 11 | 12 | // 是二叉排序树的例子 13 | int a[15] = {10, 5, 3, -1, -1, 8, -1, -1, 15, 13, -1, -1, 20, -1, -1}; 14 | int i = 0; 15 | // 创建一棵树 16 | void Build(BiTree & T) { 17 | int data = a[i ++]; // 改这个地方的a或者b切换样例 18 | if(data == -1) { 19 | T = NULL; 20 | } else { 21 | T = (BiTree) malloc(sizeof(BiNode)); 22 | T -> data = data; 23 | T -> lchild = T -> rchild = NULL; 24 | Build(T -> lchild); 25 | Build(T -> rchild); 26 | } 27 | }; 28 | 29 | void PreOrder(BiTree T) { 30 | if(T) { 31 | cout << T -> data << " "; 32 | PreOrder(T -> lchild); 33 | PreOrder(T -> rchild); 34 | } 35 | } 36 | 37 | // 二叉排序树的最小值一定在最左边,最大值一定在最右边 38 | void FindMinInSortTree(BiTree T, int & minv) { 39 | if(T == NULL) 40 | return; 41 | else { 42 | minv = T -> data; 43 | FindMinInSortTree(T -> lchild, minv); 44 | } 45 | } 46 | 47 | void FindMaxInSortTree(BiTree T, int & maxv) { 48 | if(T == NULL) 49 | return; 50 | else { 51 | maxv = T -> data; 52 | FindMaxInSortTree(T -> rchild, maxv); 53 | } 54 | } 55 | 56 | int main() { 57 | BiTree T; 58 | int minv = 0; 59 | int maxv = 0; 60 | Build(T); 61 | FindMinInSortTree(T, minv); 62 | FindMaxInSortTree(T, maxv); 63 | cout << "最小值:" << minv << " " << "最大值:" << maxv << endl; 64 | return 0; 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /chapter_8/8.3.3/8.3.3_2_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/25. 3 | // 双向冒泡排序算法 4 | 5 | #include 6 | using namespace std; 7 | 8 | void DeSort(int a[], int length) { 9 | int low = 0, high = length; 10 | 11 | while(low < high) { 12 | int flag = 1; 13 | for(int i = low; i < high - 1; i++) { // 从前往后,把大的放最后 14 | if(a[i] > a[i + 1]) { 15 | flag = 0; // 如果有交换,那么说明序列还不是有序状态 16 | swap(a[i], a[i + 1]); 17 | } 18 | } 19 | 20 | high --; // 最大值已经就位,设置high往前挪动 21 | 22 | if(flag == 1) break; // 如果flag = 1说明,在上一次排序的过程中并没有涉及到交换 => 已经有序 23 | 24 | for(int i = high; i > low; i--) { // 从后往前,把小的放最前 25 | if(a[i - 1] > a[i]) { 26 | swap(a[i], a[i - 1]); 27 | } 28 | } 29 | low ++; // 最小值已经就位,设置low往后挪动 30 | 31 | 32 | } 33 | } 34 | 35 | int main() { 36 | int a[11] = {2,5,21,54,64,12,65,34,12,37,21}; 37 | cout << "原序列:"; 38 | for(int i = 0; i < 11; ++i) 39 | cout << a[i] << " "; 40 | cout << endl; 41 | 42 | DeSort(a,11); 43 | 44 | cout << "排序后:"; 45 | for(int i = 0; i < 11; ++i) 46 | cout << a[i] << " "; 47 | cout << endl; 48 | 49 | return 0; 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /chapter_8/8.3.3/8.3.3_3_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/25. 3 | // 将奇数结点移动到偶数结点的前面 4 | 5 | #include 6 | using namespace std; 7 | 8 | // 采用双指针的思想,flag初始指向列表中的第一个元素,i从前往后扫描,当扫描到奇数元素时,和flag进行交换,然后flag++,直到数组遍历完 9 | void MoveOdds(int a[], int length) { 10 | int flag = 0; // 11 | for(int i = 0; i < length; ++i) { 12 | if(a[i] % 2 == 1) { 13 | swap(a[i], a[flag]); 14 | flag ++; 15 | } 16 | } 17 | } 18 | 19 | int main() { 20 | int a[11] = {2,5,21,54,64,12,65,34,12,37,21}; 21 | cout << "原数组为:"; 22 | for(int i = 0; i < 11; ++i) { 23 | cout << a[i] << " "; 24 | } 25 | cout << endl; 26 | 27 | MoveOdds(a, 11); 28 | 29 | cout << "移动后的数组为:"; 30 | for(int i = 0 ; i < 11; ++i) { 31 | cout << a[i] << " "; 32 | } 33 | cout << endl; 34 | 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /chapter_8/8.3.3/8.3.3_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/25. 3 | // 改编快排,枢纽结点从列表中随机选取 4 | 5 | #include 6 | using namespace std; 7 | 8 | int Partition(int a[], int low, int high) { 9 | int pivot = a[rand() % (high - low + 1) + low]; // 随机从数组中选择一个元素作为枢纽 10 | while(low < high) { 11 | while(low < high && a[high] >= pivot) --high; // 从右往左,找到第一个比枢纽小的 12 | a[low] = a[high]; 13 | 14 | while(low < high && a[low] <= pivot) ++ low; // 从左往右,找到第一个比枢纽大的 15 | a[high] = a[low]; 16 | } 17 | 18 | a[low] = pivot; // 枢纽还原 19 | return low; // 返回位置 20 | 21 | } 22 | 23 | void QuickSort(int a[], int low, int high) { 24 | if(low < high) { 25 | int pivotpos = Partition(a, low, high); 26 | QuickSort(a, low, pivotpos - 1); 27 | QuickSort(a, pivotpos + 1, high); 28 | } 29 | } 30 | 31 | int main() { 32 | int a[11] = {2,5,21,54,64,12,65,34,12,37,21}; 33 | cout << "原数组为:"; 34 | for(int i = 0; i < 11; ++i) { 35 | cout << a[i] << " "; 36 | } 37 | cout << endl; 38 | 39 | QuickSort(a, 0, 10); 40 | 41 | cout << "排序后的数组为:"; 42 | for(int i = 0 ; i < 11; ++i) { 43 | cout << a[i] << " "; 44 | } 45 | cout << endl; 46 | return 0; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /chapter_8/8.3.3/8.3.3_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/25. 3 | #include 4 | using namespace std; 5 | int Kth(int a[], int low, int high, int k) { 6 | if (low == high) return a[low]; 7 | int mid = a[low]; 8 | 9 | int ldx = low - 1, rdx = high + 1; //执行的是do while 10 | while(ldx < rdx) { // 快排交换元素模板 11 | do ldx ++; while (a[ldx] < mid); 12 | do rdx --; while(a[rdx] > mid); 13 | 14 | if(ldx < rdx) swap(a[ldx], a[rdx]); 15 | } 16 | 17 | int leftLength = rdx - low + 1; // 区间左边的长度 18 | if(k <= leftLength) return Kth(a, low, rdx, k); // 如果第k小数在左半区间,那么在左半区间中找第k小的元素 19 | return Kth(a, rdx + 1, high, k - leftLength); // 如果第k小的数在右半区间,那么在右半区间中找第 k - leftLength小的元素 20 | } 21 | 22 | int main() { 23 | int a[11] = {2,5,21,54,64,12,65,34,12,37,21}; 24 | cout << "原数组为:"; 25 | for(int i = 0; i < 11; ++i) 26 | cout << a[i] << " "; 27 | cout << endl; 28 | cout << Kth(a, 0, 10, 3); // 找到第3小的数 29 | return 0; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /chapter_8/8.3.3/8.3.3_6_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/26. 3 | // 荷兰国旗问题 => 本质是快排的一次划分 4 | 5 | #include 6 | using namespace std; 7 | 8 | void Partition(int Color[], int length) { 9 | int i = 0, j = 0, k = length - 1; // i前面是红色,k后面是蓝色,j是扫描的工作指针 10 | while(j <= k) { 11 | if(Color[j] == 0) { // 如果扫描到红色,和第一个元素交换 12 | swap(Color[i], Color[j]); 13 | i ++; 14 | j ++; 15 | } else if(Color[j] == 1) { // 如果是白色,什么也不做 16 | j ++; 17 | } else { // 如果是蓝色 18 | swap(Color[j], Color[k]); 19 | k --; 20 | // 这个地方不用j --,因为可能之前的Color[k]也是蓝色,如果j+1那么这个蓝色就会被跳过 21 | } 22 | } 23 | } 24 | 25 | int main() { 26 | //假设红为0,白为1,蓝为2 27 | int Color[10] = { 1,0,1,2,2,1,2,0,1,2 }; 28 | cout << "原数组为:"; 29 | for(int i = 0; i < 10; ++i) { 30 | cout << Color[i] << " "; 31 | } 32 | cout << endl; 33 | 34 | Partition(Color, 10); 35 | 36 | cout << "调整后的数组为:"; 37 | for(int i = 0; i < 10; ++i) { 38 | cout << Color[i] << " "; 39 | } 40 | cout << endl; 41 | return 0; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /chapter_8/8.4.3/8.4.3_4_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/26. 3 | // 在链表上进行选择排序 4 | 5 | #include 6 | using namespace std; 7 | 8 | typedef struct Node { 9 | int data; 10 | struct Node * next; 11 | } Node, * LinkedList; 12 | 13 | int a[11] = {0, 21, 11, 9, 3, 15, 17, 3, 25, 7, 21}; 14 | void CreateList(LinkedList & L) { 15 | // 首先创建一个头结点 16 | L = (LinkedList) malloc(sizeof(Node)); 17 | L -> next = NULL; 18 | LinkedList r = L; 19 | // 依次创建剩余结点,并采用尾插法 20 | for(int i = 0; i < 11; ++i) { 21 | LinkedList s = (LinkedList) malloc (sizeof(Node)); 22 | s -> data = a[i]; 23 | 24 | r -> next = s; 25 | r = s; 26 | } 27 | r -> next = NULL; 28 | } 29 | 30 | void Print(LinkedList L) { 31 | LinkedList p = L -> next; 32 | while(p) { 33 | cout << p -> data << " "; 34 | p = p -> next; 35 | } 36 | } 37 | 38 | //每一趟选择一个最大的元素,插入到链表的头部 39 | void SelectSortOnLinkedList(LinkedList & L) { 40 | LinkedList p = L -> next, max, cur, maxpre, curpre; // p指针前面的元素均有序,cur是工作指针,用于遍历序列找最大元素, curpre是cur指针的前驱,maxpre是max指针的前驱,max指向的是当前结点值最大的元素 41 | L = NULL; 42 | while(p) { 43 | cur = p; 44 | curpre = NULL; 45 | max = p; 46 | maxpre = NULL; 47 | 48 | while (cur) { 49 | if (cur -> data > max -> data) { // 如果当前找到了最小元素 50 | max = cur; 51 | maxpre = curpre; 52 | } 53 | curpre = cur; // 指针后移 54 | cur = cur -> next; 55 | } 56 | 57 | if (max == p) { //如果最大的结点是第一个结点 58 | p = p -> next; 59 | } else { 60 | maxpre -> next = max -> next; // 链表连上,把最大元素的结点单独摘出来 61 | } 62 | max -> next = L; 63 | L = max; 64 | } 65 | } 66 | 67 | 68 | 69 | int main() { 70 | LinkedList L; 71 | CreateList(L); 72 | 73 | cout << "原链表为:"; 74 | Print(L); 75 | cout << endl; 76 | 77 | SelectSortOnLinkedList(L -> next); 78 | cout << "排序后的链表为:"; 79 | Print(L); 80 | cout << endl; 81 | return 0; 82 | } -------------------------------------------------------------------------------- /chapter_8/8.4.3/8.4.3_5_mach4101.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by mach4101 on 2022/7/26. 3 | // 4 | 5 | #include 6 | using namespace std; 7 | 8 | bool IsHeap(int A[],int len) { 9 | if (len % 2 == 0) { 10 | if (A[len / 2] > A[len]) { 11 | return false; 12 | for (int i = len / 2 - 1; i >= 1; i--) { 13 | if (A[i] > A[2 * i] || A[i] > A[2 * i + 1]) 14 | return false; 15 | } 16 | } 17 | else { 18 | for (int i = len / 2; i >= 1; i--) { 19 | if (A[i] > A[2 * i] || A[i] > A[2 * i + 1]) 20 | return false; 21 | } 22 | } 23 | return true; 24 | } 25 | } 26 | 27 | int main() 28 | { 29 | int A[] = { -1,2,4,5,21,45,21,44,22,87,2,4,8 }; 30 | int B[] = { -1,2,4,3 }; 31 | if (IsHeap(A, 12)) 32 | cout << "是小根堆" << endl; 33 | else 34 | cout << "不是小根堆" << endl; 35 | return 0; 36 | } --------------------------------------------------------------------------------