二叉树的非递归遍历(栈)
二叉树递归遍历很简单,如先序遍历:
1: void preOrder(Tree T)
2: {
3: if (T!=NULL)
4: {
5: cout<<T->element<<" ";
6: preOrder(T->left);
7: preOrder(T->right);
8: }
9: }
递归过程很简单,可以从二叉树的图结构看出,T一直左走,直到null,然后返回父节点,以其右子节点为根,重复步骤。
因此,需要有个方法,能够返回当前节点的父节点,即能够回溯。
有两种方法:方法见此博客
1.使用栈的记忆:
两个版本:模拟递归的实现效果;模拟后序遍历入栈。
2.增加一个指向父节点的指针。
其中,本文主要用栈结构实现非递归遍历。
其中,由于前序与中序遍历的情况,有节点序列的连续,因此,采用模拟递归的方法较容易;而后序遍历根节点有一定的跳跃性,需要先访问左,然后跳至右节点,最后才访问中间节点,使用模拟后序入栈的顺序遍历方法时,需要一个变量来标记中间节点的访问。
前序遍历与中序遍历的模拟递归实现:
1: #include <stack>
2: //前序遍历二叉搜索树:用栈模拟递归
3: void PreOrderTraversal(Tree T)
4: {
5: stack<Tree> s;
6: while (NULL!=T || !(s.size()==0))
7: {
8: if (T!=NULL)
9: {
10: cout<<T->element<<" ";//前序遍历,先处理根节点
11: s.push(T);//入栈
12: T=T->left;//一直向左搜索,若非空则入栈
13: }
14: else
15: {
16: T = s.top();//回溯到父节点
17: s.pop();
18: T = T->right;//以父节点的右子节点为新的根节点,重复上述一直向左搜索操作
19: }
20: }
21: cout<<endl;
22: }
23:
24: void InOrderTraversal(Tree T)
25: {
26: stack<Tree> s;
27: while(T!=NULL || !s.empty())
28: {
29: if (T!=NULL)
30: {
31: s.push(T);
32: T=T->left;
33: }
34: else
35: {
36: T = s.top();
37: s.pop();
38: cout<<T->element<<" ";
39: T=T->right;
40: }
41: }
42: cout<<endl;
43: }
后序遍历的非递归模拟后序入栈顺序实现:
1: //后序遍历二叉搜索树:非递归方法,使用栈(模拟后序)
2: void PostOrderTraversal(Tree T)
3: {
4: if (NULL==T)
5: {
6: cout<<"NULL trees"<<endl;
7: }
8: stack<Tree> s;
9: T->bPushed = false;//bPushed:表示左右子节点是否已经入栈。
10: //初始化为false,表示还未处理左右子节点
11: s.push(T);
12:
13: while (!s.empty())
14: {
15: T = s.top();
16: s.pop();
17: if (T->bPushed==true)
18: {//bPushed:为true,表示左右子节点均已入栈。此时,访问该节点。
19: //bPushed的使用可避免左右子节点重复入栈:false,表示左右子节点需入栈;true的话,直接跳过
20: cout<<T->element<<" ";
21: }
22: else
23: {//bPushed:为false。此时,需设置bPushed为true,然后处理左右子节点。
24: T->bPushed = true;//设置该节点标志符为true,然后处理左右子节点。
25: s.push(T);
26:
27: if (T->right!=NULL )
28: {
29: T->right->bPushed = false;//初始化当前节点的右节点(若存在)为false
30: s.push(T->right);
31: }
32:
33: if (T->left!=NULL )
34: {
35: T->left->bPushed = false;//初始化当前节点的左节点(若存在)为false
36: s.push(T->left);
37: }
38:
39: }
40: }
41: cout<<endl;
42: }
完整程序:
1: typedef struct TreeNode * Tree;
2: typedef int ElemType;
3: struct TreeNode
4: {
5: ElemType element;
6: Tree left;
7: Tree right;
8: bool bPushed;
9: };
10: #include <iostream>
11: using namespace std;
12:
13:
14: //创建一个空树
15: Tree MakeEmpty(Tree T)
16: {
17: if (NULL!=T)
18: {
19: MakeEmpty(T->left);
20: MakeEmpty(T->right);
21: free(T);
22: }
23: return NULL;
24: }
25:
26: Tree Insert(ElemType X,Tree& T)
27: {
28: if (NULL==T)
29: {
30: T = (Tree)malloc(sizeof(TreeNode));
31: if (NULL==T)
32: {
33: cout<<"out of space!"<<endl;
34: }
35: else
36: {
37: T->element = X;
38: T->left=NULL;
39: T->right=NULL;
40: }
41: return T;
42: }
43: else
44: {
45: if (X<T->element)
46: {
47: T->left = Insert(X,T->left);
48: }
49: else
50: T->right = Insert(X,T->right);
51: }
52: return T;
53: }
54:
55: #include <stack>
56: //前序遍历二叉搜索树:用栈模拟递归
57: void PreOrderTraversal(Tree T)
58: {
59: stack<Tree> s;
60: while (NULL!=T || !(s.size()==0))
61: {
62: if (T!=NULL)
63: {
64: cout<<T->element<<" ";//前序遍历,先处理根节点
65: s.push(T);//入栈
66: T=T->left;//一直向左搜索,若非空则入栈
67: }
68: else
69: {
70: T = s.top();//回溯到父节点
71: s.pop();
72: T = T->right;//以父节点的右子节点为新的根节点,重复上述一直向左搜索操作
73: }
74: }
75: cout<<endl;
76: }
77:
78: void InOrderTraversal(Tree T)
79: {
80: stack<Tree> s;
81: while(T!=NULL || !s.empty())
82: {
83: if (T!=NULL)
84: {
85: s.push(T);
86: T=T->left;
87: }
88: else
89: {
90: T = s.top();
91: s.pop();
92: cout<<T->element<<" ";
93: T=T->right;
94: }
95: }
96: cout<<endl;
97: }
98:
99: //后序遍历二叉搜索树:非递归方法,使用栈(模拟后序)
100: void PostOrderTraversal(Tree T)
101: {
102: if (NULL==T)
103: {
104: cout<<"NULL trees"<<endl;
105: }
106: stack<Tree> s;
107: T->bPushed = false;//bPushed:表示左右子节点是否已经入栈。
108: //初始化为false,表示还未处理左右子节点
109: s.push(T);
110:
111: while (!s.empty())
112: {
113: T = s.top();
114: s.pop();
115: if (T->bPushed==true)
116: {//bPushed:为true,表示左右子节点均已入栈。此时,访问该节点。
117: //bPushed的使用可避免左右子节点重复入栈:false,表示左右子节点需入栈;true的话,直接跳过
118: cout<<T->element<<" ";
119: }
120: else
121: {//bPushed:为false。此时,需设置bPushed为true,然后处理左右子节点。
122: T->bPushed = true;//设置该节点标志符为true,然后处理左右子节点。
123: s.push(T);
124:
125: if (T->right!=NULL )
126: {
127: T->right->bPushed = false;//初始化当前节点的右节点(若存在)为false
128: s.push(T->right);
129: }
130:
131: if (T->left!=NULL )
132: {
133: T->left->bPushed = false;//初始化当前节点的左节点(若存在)为false
134: s.push(T->left);
135: }
136:
137: }
138: }
139: cout<<endl;
140: }
141:
142: void preOrder(Tree T)
143: {
144: if (T!=NULL)
145: {
146: cout<<T->element<<" ";
147: preOrder(T->left);
148: preOrder(T->right);
149: }
150: }
151:
152: void inOrder(Tree T)
153: {
154: if (T!=NULL)
155: {
156: inOrder(T->left);
157: cout<<T->element<<" ";
158: inOrder(T->right);
159: }
160: }
161:
162: void postOrder(Tree T)
163: {
164: if (T!=NULL)
165: {
166: postOrder(T->left);
167: postOrder(T->right);
168: cout<<T->element<<" ";
169: }
170: }
171: int main()
172: {
173:
174: Tree T = NULL;
175: Insert(10,T);
176: Insert(20,T);
177: Insert(8,T);
178: Insert(15,T);
179: Insert(1,T);
180: Insert(9,T);
181: Insert(28,T);
182: preOrder(T);cout<<endl;
183: inOrder(T);cout<<endl;
184: postOrder(T);cout<<endl;
185: PreOrderTraversal(T);
186: InOrderTraversal(T);
187: PostOrderTraversal(T);
188: system("pause");
189: return 0;
190: }