树和二叉树->其他(待完善)

关于树和二叉树的部分,还有如下三个知识点,待以后时间更充裕的时候再回头完善。

 

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("打印以树的双亲表示法表示的树:\n");
 38     printf("树的结点数: %d\n", S->n);
 39     printf("树的根的位置: %d\n", S->r);
 40     int i = 0;
 41     for(i=0; i<=S->n; i++)
 42     {
 43         printf("index %d: (data %c, parent %d)\n", i, S->node[i].data, S->node[i].parent);
 44     }
 45     printf("\n");
 46 }
 47 
 48 //初始化操作, 构造一个由n个子集(每个子集只含单个成员xi)构成的集合S。
 49 static int initialMFSet(PTree *S)
 50 {
 51     printf("构造一个由n个子集(每个子集只含单个成员xi)构成的集合S:\n");
 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("\n");
 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集合中不存在!\n", 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("创建等价类:\n");
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("\n");
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 树的计数

posted on 2018-08-13 18:07  LiveWithACat  阅读(161)  评论(0编辑  收藏  举报