二叉树的遍历

二叉树的非递归遍历需要用到栈,所以就自己写栈,这也是一个比较纠结的地方。C语言里面只有值传递。声明指针时知给指针分配了空间,所以对于指针指向的对象,需要我们自己malloc。我在用户函数里声明了Stack*变量,在初始化时,当然需要分配Stack的空间,切记!!!又因为值传递的影响,所以选择传递一个二维指针,就因为之前没有分配一个Stack空间,而直接操作里面的base指针,显然要错误!

 1 #include "stack.h"
2 #include<stdio.h>
3 #include<stdlib.h>
4 #include<malloc.h>
5 #include <assert.h>
6
7 int InitStack(Stack **S)
8 {
9 *S = (Stack*)malloc(sizeof(Stack));
10 if(!*S)
11 {
12 printf("Stack malloc error\n");
13 exit(-1);
14 }
15 (*S)->base = (int *)malloc(STACK_INIT_SIZE * sizeof(int));
16 if(!(*S)->base)
17 {
18 printf("Stack base malloc error\n");
19 exit(-1);
20 }
21 (*S)->top = (*S)->base;
22 (*S)->stacksize = STACK_INIT_SIZE;
23 return 1;
24 }
25
26 int Push(Stack *S, int e)
27 {
28 if(S->top - S->base >= S->stacksize)
29 {
30 S->base = (int *)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(int));
31 if(!S->base)
32 {
33 printf("Push malloc error\n");
34 exit(1);
35 }
36 S->top = S->base + STACKINCREMENT;
37 S->stacksize += STACKINCREMENT;
38 }
39 *S->top++ = e;
40 return 1;
41 }
42
43 int Pop(Stack *S, int *pe)
44 {
45 if(S->top == S->base)
46 return 0;
47 *pe = * --S->top;
48 return 1;
49 }
50
51 int StackEmpty(Stack *s)
52 {
53 if(s->top == s->base)
54 return 1;
55 return 0;
56 }
57
58 int Top(Stack *s, int *e)
59 {
60 if(StackEmpty(s))
61 return 0;
62
63 *e = *(s->top-1);
64 return 1;
65 }
66
67 int DestoryStack(Stack *S)
68 {
69 assert(S != NULL);
70 free(S->base);
71 S->base = NULL;
72 S->top = NULL;
73 free(S);
74 S = NULL;
75 return 1;
76 }

我的tree.c文件,对二叉树后序遍历的非递归算法还是有疑问。

  1 #include <stdio.h>
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <time.h>
5 #include "stack.h"
6
7 #define BASE 10
8 #define COUNT 10
9
10 typedef struct Node {
11 int data;
12 struct Node *lchild, *rchild;
13 }Node, *pNode;
14
15 static void
16 BT_Visit(pNode root)
17 {
18 if(root != NULL)
19 printf("%d\t", root->data);
20 }
21
22 pNode BT_GetNode(pNode root, int e)
23 {
24 if(root == NULL)
25 return NULL;
26
27 if(root->data == e)
28 return root;
29 if(root->data > e) {
30 return BT_GetNode(root->lchild, e);
31 } else {
32 return BT_GetNode(root->rchild, e);
33 }
34 }
35
36 static pNode BT_MakeNode(int e)
37 {
38 pNode pnode = (pNode)malloc(sizeof(Node));
39 assert(pnode != NULL);
40
41 pnode->data = e;
42 pnode->lchild = NULL;
43 pnode->rchild = NULL;
44 return pnode;
45 }
46
47 pNode BT_Insert(pNode *T, int e)
48 {
49 pNode pnode;
50 assert(T != NULL);
51
52 pnode = *T;
53
54 //二叉树为空
55 if(pnode == NULL) {
56 return *T = BT_MakeNode(e);
57 }
58
59 //已经存在,不能插入
60 if(pnode->data == e)
61 return NULL;
62 else if(pnode->data > e)
63 return BT_Insert(&pnode->lchild, e);
64 else
65 return BT_Insert(&pnode->rchild, e);
66 }
67
68 void
69 BT_PreOrder(pNode root)
70 {
71 if(root != NULL)
72 {
73 BT_Visit(root);
74 BT_PreOrder(root->lchild);
75 BT_PreOrder(root->rchild);
76 }
77 }
78
79 BT_InOrder(pNode root)
80 {
81 if(root != NULL)
82 {
83 BT_InOrder(root->lchild);
84 BT_Visit(root);
85 BT_InOrder(root->rchild);
86 }
87 }
88
89 void
90 BT_PostOrder(pNode root)
91 {
92 if(root != NULL)
93 {
94 BT_PostOrder(root->lchild);
95 BT_PostOrder(root->rchild);
96 BT_Visit(root);
97 }
98 }
99
100 //先打印当前节点,再依次访问左右子树。用栈是方便回溯,记录当前节点,用来以后访问右子树。
101 void
102 BT_PreOrderNoRec(pNode root)
103 {
104 pNode pnode = root;
105 int data;
106 assert(pnode != NULL);
107
108 Stack *s;
109 InitStack(&s);
110
111 while(pnode != NULL || !StackEmpty(s))
112 {
113 if(pnode != NULL) {
114 BT_Visit(pnode);
115 Push(s, pnode->data);
116 pnode = pnode->lchild;
117 } else {
118 Pop(s, &data);
119 pnode = BT_GetNode(root, data);
120 pnode = pnode->rchild;
121 }
122 }
123 DestoryStack(s);
124 }
125
126 //先访问左子树,所以先将节点压栈,且并不打印data
127 void
128 BT_InOrderNoRec(pNode root)
129 {
130 pNode pnode = root;
131 int data;
132 Stack *s;
133 InitStack(&s);
134
135 while(pnode != NULL || !StackEmpty(s))
136 {
137 if(pnode != NULL) {
138 Push(s, pnode->data);
139 pnode = pnode->lchild;
140 } else {
141 Pop(s, &data);
142 pnode = BT_GetNode(root, data);
143 BT_Visit(pnode);
144 pnode = pnode->rchild;
145 }
146 }
147 DestoryStack(s);
148 }
149
150 //要先判断当前节点是否存在右子树,如果存在,先打印右子树,所以,要设置一个tag,如果右子树已经在上次访问过了,
151 //那么就不用继续访问,可以直接打印当前节点。
152 void
153 BT_PostOrderNoRec(pNode root)
154 {
155 pNode pnode = root;
156 pNode pre = NULL;
157 int data;
158 Stack* s;
159 InitStack(&s);
160
161 while(pnode != NULL || !StackEmpty(s))
162 {
163 if(pnode != NULL) {
164 Push(s, pnode->data);
165 pnode = pnode->lchild;
166 } else {
167 Top(s, &data);
168 pnode = BT_GetNode(root, data);
169 if(pnode->rchild != NULL && pre != pnode->rchild)
170 pnode = pnode->rchild;
171 else {
172 BT_Visit(pnode);
173 Pop(s, &data);
174 pre = pnode;
175 pnode = NULL;
176 }
177 }
178 }
179 DestoryStack(s);
180 }
181
182 int
183 main(void)
184 {
185 int i;
186 pNode root = NULL;
187 BT_Insert(&root, 100);
188 BT_Insert(&root, 10);
189 BT_Insert(&root, 11);
190 BT_Insert(&root, 9);
191 BT_Insert(&root, 2);
192
193 printf("BT_PreOrderNoRec:\n");
194 BT_PreOrderNoRec(root);
195 printf("\n");
196
197 printf("BT_InOrderNoRec:\n");
198 BT_InOrderNoRec(root);
199 printf("\n");
200
201 printf("BT_PostOrderNoRec:\n");
202 BT_PostOrderNoRec(root);
203 printf("\n");
204 return 0;
205 }




posted @ 2011-12-31 21:23  leealways87  阅读(206)  评论(0编辑  收藏  举报