关于树和二叉树的部分,还有如下三个知识点,待以后时间更充裕的时候再回头完善。
1 树与等价问题
文字描述
关于等价关系和等价类的定义,在离散数学上的描述有点拗口, 其实在数据结构中,这部分相关的主要是如下三个函数:
示意图
算法分析:
代码实现
1 // 2 // Created by lady on 18-12-15. 3 // 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #define MAX_TREE_SIZE 20 10 11 typedef char TElemType; 12 13 /* 14 * 树的双亲表示法 15 * 16 * 以一组连续空间存储树的结点,同时在每个结点中附设一个指示器指示其双亲结点在链表中的位置。 17 */ 18 //结点结构 19 typedef struct PTNode{ 20 //结点的数据域 21 TElemType data; 22 //结点的双亲位置域 23 int parent; 24 }PTNode; 25 //树的结构 26 typedef struct{ 27 //树的结点 28 PTNode node[MAX_TREE_SIZE]; 29 //树的根的位置 30 int r; 31 //树的结点数 32 int n; 33 }PTree; 34 35 static void printMFSet(PTree *S) 36 { 37 printf("打印以树的双亲表示法表示的树: "); 38 printf("树的结点数: %d ", S->n); 39 printf("树的根的位置: %d ", S->r); 40 int i = 0; 41 for(i=0; i<=S->n; i++) 42 { 43 printf("index %d: (data %c, parent %d) ", i, S->node[i].data, S->node[i].parent); 44 } 45 printf(" "); 46 } 47 48 //初始化操作, 构造一个由n个子集(每个子集只含单个成员xi)构成的集合S。 49 static int initialMFSet(PTree *S) 50 { 51 printf("构造一个由n个子集(每个子集只含单个成员xi)构成的集合S: "); 52 printf("输入n的值:"); 53 char tmp[10] = {0}; 54 scanf("%d", &S->n); 55 int i = 0; 56 for(i=0; i<S->n; i++) 57 { 58 printf("输入第%d个子集的值:", i+1); 59 memset(tmp, 0, sizeof(tmp)); 60 scanf("%s", tmp); 61 S->node[i+1].data = tmp[0]; 62 S->node[i+1].parent = -1; 63 } 64 S->r = 0; 65 printf(" "); 66 return 0; 67 } 68 69 /* param1 S: S是已存在的集合 70 * param2 data: x是S中某个子集的成员 71 * result: 查找函数,确定S中x所属子集Si 72 */ 73 static int findMFSet(PTree *S, TElemType data) 74 { 75 int i = 0; 76 int j = 0; 77 int loc = -1; 78 for(i=1; i<=S->n; i++){ 79 if(S->node[i].data == data){ 80 loc = i; 81 break; 82 } 83 } 84 if(loc < 0){ 85 printf("数据data:%c在S集合中不存在! ", data); 86 return -1; 87 } 88 for(j=i; S->node[j].parent>0; j=S->node[j].parent); 89 return j; 90 } 91 92 //data_i和data_j所在的子集互不相交, 93 static int mergeMFSet(PTree *S, TElemType data_i, TElemType data_j) 94 { 95 int loc_i = -1, loc_j = -1; 96 if((loc_i=findMFSet(S, data_i)) < 0){ 97 return -1; 98 } 99 if((loc_j=findMFSet(S, data_j)) < 0){ 100 return -1; 101 } 102 103 if(S->node[loc_i].parent > S->node[loc_j].parent){ 104 //data_i所在子集的数目比data_j所在子集的数目少 105 S->node[loc_j].parent += S->node[loc_i].parent; 106 S->node[loc_i].parent = loc_j; 107 }else{ 108 S->node[loc_i].parent += S->node[loc_j].parent; 109 S->node[loc_j].parent = loc_i; 110 } 111 return 0; 112 } 113 114 //确定data所在子集,并交data所在index到根路径上所有结点都变成根的孩子结点。 115 static int fixMFSet(PTree *S, TElemType data) 116 { 117 int index = -1; 118 int parent = -1; 119 int t = 0; 120 int k = 0; 121 for(t=1; t<=S->n; t++){ 122 if(S->node[t].data == data){ 123 index = t; 124 break; 125 } 126 } 127 if(index < 0) 128 return ; 129 for(parent=index; S->node[parent].parent>0; parent=S->node[parent].parent); 130 for(k=index; k!=parent; k=t){ 131 t = S->node[k].parent; 132 S->node[k].parent = parent; 133 } 134 } 135 136 int main(int argc, char *argv[]) 137 { 138 PTree S; 139 initialMFSet(&S); 140 printMFSet(&S); 141 142 143 printf("创建等价类: "); 144 char tmp[10] = {0}; 145 TElemType dataI, dataJ; 146 while(1){ 147 memset(tmp, 0, sizeof(tmp)); 148 printf("输入一对数据,(0,0)表示结束:"); 149 scanf("%s", tmp); 150 sscanf(tmp, "%c,%c", &dataI, &dataJ); 151 if(mergeMFSet(&S, dataI, dataJ) < 0){ 152 break; 153 }else{ 154 printMFSet(&S); 155 } 156 } 157 printf(" "); 158 159 printf("现开始压缩路径, 输入要压缩的结点值: "); 160 memset(tmp, 0, sizeof(tmp)); 161 scanf("%s", tmp); 162 fixMFSet(&S, tmp[0]); 163 printMFSet(&S); 164 return 0; 165 }
代码运行
/home/lady/CLionProjects/untitled/cmake-build-debug/untitled 构造一个由n个子集(每个子集只含单个成员xi)构成的集合S: 输入n的值:9 输入第1个子集的值:1 输入第2个子集的值:2 输入第3个子集的值:3 输入第4个子集的值:4 输入第5个子集的值:5 输入第6个子集的值:6 输入第7个子集的值:7 输入第8个子集的值:8 输入第9个子集的值:9 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -1) index 2: (data 2, parent -1) index 3: (data 3, parent -1) index 4: (data 4, parent -1) index 5: (data 5, parent -1) index 6: (data 6, parent -1) index 7: (data 7, parent -1) index 8: (data 8, parent -1) index 9: (data 9, parent -1) 创建等价类: 输入一对数据,(0,0)表示结束:1,2 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -2) index 2: (data 2, parent 1) index 3: (data 3, parent -1) index 4: (data 4, parent -1) index 5: (data 5, parent -1) index 6: (data 6, parent -1) index 7: (data 7, parent -1) index 8: (data 8, parent -1) index 9: (data 9, parent -1) 输入一对数据,(0,0)表示结束:3,4 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -2) index 2: (data 2, parent 1) index 3: (data 3, parent -2) index 4: (data 4, parent 3) index 5: (data 5, parent -1) index 6: (data 6, parent -1) index 7: (data 7, parent -1) index 8: (data 8, parent -1) index 9: (data 9, parent -1) 输入一对数据,(0,0)表示结束:5,6 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -2) index 2: (data 2, parent 1) index 3: (data 3, parent -2) index 4: (data 4, parent 3) index 5: (data 5, parent -2) index 6: (data 6, parent 5) index 7: (data 7, parent -1) index 8: (data 8, parent -1) index 9: (data 9, parent -1) 输入一对数据,(0,0)表示结束:7,8 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -2) index 2: (data 2, parent 1) index 3: (data 3, parent -2) index 4: (data 4, parent 3) index 5: (data 5, parent -2) index 6: (data 6, parent 5) index 7: (data 7, parent -2) index 8: (data 8, parent 7) index 9: (data 9, parent -1) 输入一对数据,(0,0)表示结束:1,3 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -4) index 2: (data 2, parent 1) index 3: (data 3, parent 1) index 4: (data 4, parent 3) index 5: (data 5, parent -2) index 6: (data 6, parent 5) index 7: (data 7, parent -2) index 8: (data 8, parent 7) index 9: (data 9, parent -1) 输入一对数据,(0,0)表示结束:5,7 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -4) index 2: (data 2, parent 1) index 3: (data 3, parent 1) index 4: (data 4, parent 3) index 5: (data 5, parent -4) index 6: (data 6, parent 5) index 7: (data 7, parent 5) index 8: (data 8, parent 7) index 9: (data 9, parent -1) 输入一对数据,(0,0)表示结束:1,5 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -8) index 2: (data 2, parent 1) index 3: (data 3, parent 1) index 4: (data 4, parent 3) index 5: (data 5, parent 1) index 6: (data 6, parent 5) index 7: (data 7, parent 5) index 8: (data 8, parent 7) index 9: (data 9, parent -1) 输入一对数据,(0,0)表示结束:0,0 数据data:0在S集合中不存在! 现开始压缩路径, 输入要压缩的结点值: 8 打印以树的双亲表示法表示的树: 树的结点数: 9 树的根的位置: 0 index 0: (data , parent -1208980472) index 1: (data 1, parent -8) index 2: (data 2, parent 1) index 3: (data 3, parent 1) index 4: (data 4, parent 3) index 5: (data 5, parent 1) index 6: (data 6, parent 5) index 7: (data 7, parent 1) index 8: (data 8, parent 1) index 9: (data 9, parent -1) Process finished with exit code 0
2 回溯法与树的遍历
3 树的计数