总结数据结构中树的重要基础知识:

1、二叉树

 1.1 二叉树的表示形式

  1.1.1 数组形式

   根据二叉树的性质安排树中节点在数组中的位置,从根节点开始,对树中节点顺序编号,如1,2,3,...对一个具有n个节点的二叉树,采用数组表示时,具有下列两条性质:

    (前提条件:根节点的数组下标为1)

    性质a:对于节点i,如果2i<=n,则其左孩子节点在数组中位置为2i;如果2i>n,则该节点无左孩子。

    性质b:对于节点i,如果2i+1<=n,则其右孩子节点在数组中位置为2i+1;如果2i+1>n,则该节点无右孩子。

    C语言定义:

1 #define MAXSIZE 100
2 int treeArray[MAXSIZE];   //假设节点数据为int型

  1.1.2 链表形式

   二叉树具有多种链表形式,根据链表节点中指针域的不同,分为X叉链表,以下是树的链表节点的几种类型:

    Type1:普通的二叉链表,节点包括数据域、指向左子树和右子树的指针,如下所示:

1 struct treeNode{
2    int data;
3    struct treeNode * lchild;
4    struct treeNode * rchild;
5 };

    Type2:  三叉链表,除了Type1中各子结构外,还有指向父节点的指针,如下所示:

1  struct treeNode{
2    int data;
3    struct treeNode * lchild;
4    struct treeNode * rchild;
5    struct treeNode * parent;
6 };

     Type3:线索链表,用于解决链表节点中指针浪费的问题,待补充:

 1.2 建立一棵二叉树(采用先序递归建立)

   输入为0表示该节点的左子节点或右子节点为空,可能的输入形式为:4 5 0 0 0 ,构造了一棵两个节点的树,其中data为5的节点为data为4的节点的左子节点,程序如下:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<assert.h>
 4 
 5 //定义树节点
 6 typedef struct treeNode{
 7    int data;
 8    struct treeNode * lchild;
 9    struct treeNode *rchild;
10 } *treeNodeP;
11 
12 #define MALLOC(p) if(!(p = (treeNodeP)malloc(sizeof(struct treeNode)))) assert(p!=NULL);
13 
14 bool createBiTree(treeNodeP *root);
15 void traverseBiTree(treeNodeP root);
16 
17 //main函数
18 int main()
19 {
20     treeNodeP root;
21     createBiTree(&root);     //注意:传递的是指针的指针
22     if(!root)
23     {
24         printf("root is null\n");
25         exit(1);
26     }
27     printf("The root's lchild is: %d\n",root->lchild->data);
28     int temp;
29     temp = getchar();
30     return 0;
31 }
32 //按先序次序建立二叉树
33 bool createBiTree(treeNodeP *p)
34 {
35     int d;
36     scanf("%d",&d);
37     if(d == 0)
38         *p = NULL;   
39     else
40     {
41         MALLOC(*p);
42         (*p)->data = d;
43         createBiTree(&((*p)->lchild));
44         createBiTree(&((*p)->rchild));
45     }
46     return true;
47 }

 1.3 遍历二叉树

  1.3.1 递归遍历

   二叉树的递归遍历有三种类型:前序遍历、中序遍历、后序遍历,具体实现如下:

 1 //1. 递归先序遍历
 2 void rePreTraBiTree(treeNodeP root)
 3 {
 4     if(!root)
 5         return;
 6     else
 7     {
 8         printf("Tree: %d\n",root->data);
 9         rePreTraBiTree(root->lchild);
10         rePreTraBiTree(root->rchild);
11     }
12 }
13 //2. 递归中序遍历
14 void reInTraBiTree(treeNodeP root)
15 {
16     if(!root)
17         return;
18     else
19     {
20         reInTraBiTree(root->lchild);
21         printf("Tree: %d\n",root->data);
22         reInTraBiTree(root->rchild);
23     }
24 }
25 //3. 递归后序遍历
26 void rePosTraBiTree(treeNodeP root)
27 {
28     if(!root)
29         return;
30     else
31     {
32         rePosTraBiTree(root->lchild);
33         rePosTraBiTree(root->rchild);
34         printf("Tree: %d\n",root->data);
35     }
36 }

  1.3.2 非递归遍历

   二叉树的递归遍历函数调用次数较多,效率较低,每种递归遍历均有相应的非递归遍历算法,二叉树前序、中序和后序的非递归遍历实现如下:

 1 //4. 非递归先序遍历
 2 void nonrePreTraBiTree(treeNodeP root)
 3 {
 4     stackNodeP stack;
 5     //treeNodeP ttemp;
 6     stack = stackCreate();
 7     while(1)
 8     {
 9         for(;root;root = root->lchild)
10         {
11             printf("Tree: %d\n",root->data);
12             push_stack(root, &stack);
13         }
14         root = pop_stack(&stack);
15         if(root == NULL)
16             break;
17         root = root->rchild;
18     }
19 }
20 //5. 非递归中序遍历
21 void nonreInTraBiTree(treeNodeP root)
22 {
23     stackNodeP stack;
24     //treeNodeP ttemp;
25     stack = stackCreate();
26     while(1)
27     {
28         for(;root;root = root->lchild)
29             push_stack(root, &stack);
30         root = pop_stack(&stack);
31         if(root == NULL)
32             break;
33         printf("Tree: %d\n",root->data);
34         root = root->rchild;
35     }
36 }
37 //6. 非递归后序遍历
38 void nonrePosTraBiTree(treeNodeP root)
39 {
40     stackNodeP stack;
41     treeNodeP ttemp;
42     stack = stackCreate();
43     //第一棵左子树入栈到底
44     for(;root;root = root->lchild)
45     {
46         root->flag = 0;
47         push_stack(root,&stack);
48     }
49     while(1)
50     {
51         ttemp = pop_stack(&stack);
52         if(ttemp == NULL)
53             break;
54         while(ttemp->rchild != NULL && ttemp->flag == 0)
55         {
56             ttemp->flag =1;
57             push_stack(ttemp, &stack);  //重新入栈
58             ttemp = ttemp->rchild;
59             for(;ttemp;ttemp = ttemp->lchild)
60             {
61                 ttemp->flag =0;
62                 push_stack(ttemp, &stack);
63             }
64             ttemp = pop_stack(&stack);
65         }
66         printf("tree: %d\n",ttemp->data);
67     }
68 }

  1.4 完整程序

  1 /*
  2 *   Created By Chunxin Yang, NWPU.
  3 */
  4 
  5 #include<stdio.h>
  6 #include<stdlib.h>
  7 #include<assert.h>
  8 
  9 //定义树节点
 10 typedef struct treeNode{
 11    int data;
 12    struct treeNode * lchild;
 13    struct treeNode *rchild;
 14    int flag;    //标识后序遍历每个节点的右子树是否访问过
 15 } *treeNodeP;
 16 //定义栈节点
 17 typedef struct stackNode{
 18     treeNodeP tp;
 19     struct stackNode * next;
 20 } *stackNodeP;
 21 
 22 #define MALLOC(p) if(!(p = (treeNodeP)malloc(sizeof(struct treeNode)))) assert(p!=NULL);
 23 
 24 bool createBiTree(treeNodeP *root);
 25 void traverseBiTree(treeNodeP root);
 26 
 27 stackNodeP stackCreate();
 28 void push_stack(treeNodeP root, stackNodeP *top);
 29 treeNodeP pop_stack(stackNodeP *top);
 30 
 31 void rePreTraBiTree(treeNodeP root);  //递归先序
 32 void reInTraBiTree(treeNodeP root);   //递归中序
 33 void rePosTraBiTree(treeNodeP root);   //递归后序
 34 void nonrePreTraBiTree(treeNodeP root);  //非递归先序
 35 void nonreInTraBiTree(treeNodeP root);   //非递归中序
 36 void nonrePosTraBiTree(treeNodeP root);   //非递归后序
 37 
 38 //main函数
 39 int main()
 40 {
 41     treeNodeP root;
 42     createBiTree(&root);     //注意:传递的是指针的指针
 43     if(!root)
 44     {
 45         printf("root is null\n");
 46         exit(1);
 47     }
 48     //printf("The root's lchild is: %d\n",root->lchild->data);
 49     traverseBiTree(root);
 50     int temp;
 51     temp = getchar();
 52     getchar();
 53     getchar();
 54     return 0;
 55 }
 56 //按先序次序建立二叉树
 57 bool createBiTree(treeNodeP *p)
 58 {
 59     int d;
 60     scanf("%d",&d);
 61     if(d == 0)
 62         *p = NULL;   
 63     else
 64     {
 65         MALLOC(*p);
 66         (*p)->data = d;
 67         createBiTree(&((*p)->lchild));
 68         createBiTree(&((*p)->rchild));
 69     }
 70     return true;
 71 }
 72 //遍历二叉树
 73 void traverseBiTree(treeNodeP root)
 74 {
 75     //1. 递归先序遍历
 76     printf("1:先序遍历\n");
 77     rePreTraBiTree(root);
 78     //2. 递归中序遍历
 79     printf("2:中序遍历\n");
 80     reInTraBiTree(root);   
 81     //3. 递归后序遍历
 82     printf("3:后序遍历\n");
 83     rePosTraBiTree(root);  
 84     //4. 非递归先序遍历
 85     printf("4:非递归先序遍历\n");
 86     nonrePreTraBiTree(root);
 87     //5. 非递归中序遍历
 88     printf("5:非递归中序遍历\n");
 89     nonreInTraBiTree(root);
 90     //6. 非递归后序遍历
 91     printf("6:非递归后序遍历\n");
 92     nonrePosTraBiTree(root);
 93 }
 94 //1. 递归先序遍历
 95 void rePreTraBiTree(treeNodeP root)
 96 {
 97     if(!root)
 98         return;
 99     else
100     {
101         printf("Tree: %d\n",root->data);
102         rePreTraBiTree(root->lchild);
103         rePreTraBiTree(root->rchild);
104     }
105 }
106 //2. 递归中序遍历
107 void reInTraBiTree(treeNodeP root)
108 {
109     if(!root)
110         return;
111     else
112     {
113         reInTraBiTree(root->lchild);
114         printf("Tree: %d\n",root->data);
115         reInTraBiTree(root->rchild);
116     }
117 }
118 //3. 递归后序遍历
119 void rePosTraBiTree(treeNodeP root)
120 {
121     if(!root)
122         return;
123     else
124     {
125         rePosTraBiTree(root->lchild);
126         rePosTraBiTree(root->rchild);
127         printf("Tree: %d\n",root->data);
128     }
129 }
130 //4. 非递归先序遍历
131 void nonrePreTraBiTree(treeNodeP root)
132 {
133     stackNodeP stack;
134     //treeNodeP ttemp;
135     stack = stackCreate();
136     while(1)
137     {
138         for(;root;root = root->lchild)
139         {
140             printf("Tree: %d\n",root->data);
141             push_stack(root, &stack);
142         }
143         root = pop_stack(&stack);
144         if(root == NULL)
145             break;
146         root = root->rchild;
147     }
148 }
149 //5. 非递归中序遍历
150 void nonreInTraBiTree(treeNodeP root)
151 {
152     stackNodeP stack;
153     //treeNodeP ttemp;
154     stack = stackCreate();
155     while(1)
156     {
157         for(;root;root = root->lchild)
158             push_stack(root, &stack);
159         root = pop_stack(&stack);
160         if(root == NULL)
161             break;
162         printf("Tree: %d\n",root->data);
163         root = root->rchild;
164     }
165 }
166 //6. 非递归后序遍历
167 void nonrePosTraBiTree(treeNodeP root)
168 {
169     stackNodeP stack;
170     treeNodeP ttemp;
171     stack = stackCreate();
172     //第一棵左子树入栈到底
173     for(;root;root = root->lchild)
174     {
175         root->flag = 0;
176         push_stack(root,&stack);
177     }
178     while(1)
179     {
180         ttemp = pop_stack(&stack);
181         if(ttemp == NULL)
182             break;
183         while(ttemp->rchild != NULL && ttemp->flag == 0)
184         {
185             ttemp->flag =1;
186             push_stack(ttemp, &stack);  //重新入栈
187             ttemp = ttemp->rchild;
188             for(;ttemp;ttemp = ttemp->lchild)
189             {
190                 ttemp->flag =0;
191                 push_stack(ttemp, &stack);
192             }
193             ttemp = pop_stack(&stack);
194         }
195         printf("tree: %d\n",ttemp->data);
196     }
197 }
198 //建栈
199 stackNodeP stackCreate()
200 {
201     stackNodeP top = NULL;
202     return top;
203 }
204 //如栈
205 void push_stack(treeNodeP root, stackNodeP *top)
206 {
207     stackNodeP temp;
208     if(top == NULL)
209     {
210         if(!((*top) = (stackNodeP)malloc(sizeof(stackNode)))) assert((*top)!=NULL);
211         (*top)->tp = root;
212         (*top)->next = NULL;
213     }else{
214         if(!(temp = (stackNodeP)malloc(sizeof(stackNode)))) assert(temp!=NULL);
215         temp->tp = root;
216         temp->next = *top;
217         *top = temp;
218     }
219 }
220 //出栈
221 treeNodeP pop_stack(stackNodeP *top)
222 {
223     treeNodeP temp;
224     if((*top) == NULL)
225         return NULL;
226     temp = (*top)->tp;
227     (*top) = (*top)->next;
228     return temp;
229 }

 

 posted on 2013-04-24 16:13  小小cfo  阅读(288)  评论(0编辑  收藏  举报