樹的先序遍歷、中序遍歷、後序遍歷、層次遍歷的非遞迴演算法
阿新 • • 發佈:2019-01-10
Written by Robert_Wang in Southwest University of Science And Technology.
這裡提出用非遞迴遍歷的原因是:用遞迴遍歷雖然方便,但是不能遞迴太深,否則會 stack overflow
先序遍歷這裡有兩種遍歷方法
void PreOrder1(Btree*b) { stack<node*>s; Btree *p; //if (b) s.push(b); if (b) { while (b || !s.empty()) { while (b) { cout << b->data << " "; s.push(b); b = b->lchild; } if (!s.empty()) { p = s.top(); s.pop(); if (p->rchild) s.push(p->rchild); } } } }
void PreOrder2(Btree*b)
{
stack<Btree*>s;
Btree *p;
if (b)
{
s.push(b);
while (!s.empty())
{
p = s.top();
s.pop();
cout << p->data << " ";
if (p->rchild) s.push(p->rchild);
if (p->lchild) s.push(p->lchild);
}
}
}
中序遍歷只需要在上面的程式碼的基礎上稍作改動
//中序遍歷的非遞迴遍歷 void InOrder(Btree*b) { Btree*p; stack<Btree*>s; if (b) { while (b || !s.empty()) { while (b) { s.push(b); b = b->lchild; } if (!s.empty()) { p = s.top(); s.pop(); cout << p->data << " "; if (p->rchild) s.push(p->rchild); } } } }
後續遍歷就要先走到最左端,再看右兒子是否為空或者已經被訪問過
如果沒有訪問過,轉向右子樹,迴圈退一層,繼續走到最左端,
如果訪問過或者為空,則訪問該根結點元素,退棧一次
//後序遍歷的非遞迴演算法 void PostOrder(Btree*b) { Btree*p,*r; stack<Btree*>s; p = b; bool flag; do { while (p) { s.push(p); p = p->lchild; } r = NULL; flag = true;//flag == true 表示正在處理棧頂結點 while (!s.empty() && flag) { p = s.top(); if (p->rchild == r)//如果右子樹為空或者已經被訪問過 { cout << p->data << " "; s.pop(); r = p; } else { p = p->rchild; flag = false; } } } while (!s.empty()); }
層次遍歷就是一個BFS演算法
void LevelOrder(Btree*b)
{
queue<Btree*>q;
Btree*p;
if (b)
{
q.push(b);
while (!q.empty())
{
p = q.back();
q.pop();
cout << p->data << " ";
if (p->lchild) q.push(p->lchild);
if (p->rchild) q.push(p->rchild);
}
}
}
和在一起就是
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
typedef struct node
{
int data;
struct node *lchild;
struct node *rchild;
}Btree;
//非遞迴演算法
void PreOrder1(Btree*b)
{
stack<node*>s;
Btree *p;
//if (b) s.push(b);
if (b)
{
while (b || !s.empty())
{
while (b)
{
cout << b->data << " ";
s.push(b);
b = b->lchild;
}
if (!s.empty())
{
p = s.top();
s.pop();
if (p->rchild) s.push(p->rchild);
}
}
}
}
void PreOrder2(Btree*b)
{
stack<Btree*>s;
Btree *p;
if (b)
{
s.push(b);
while (!s.empty())
{
p = s.top();
s.pop();
cout << p->data << " ";
if (p->rchild) s.push(p->rchild);
if (p->lchild) s.push(p->lchild);
}
}
}
//中序遍歷的非遞迴遍歷
void InOrder(Btree*b)
{
Btree*p;
stack<Btree*>s;
if (b)
{
while (b || !s.empty())
{
while (b)
{
s.push(b);
b = b->lchild;
}
if (!s.empty())
{
p = s.top();
s.pop();
cout << p->data << " ";
if (p->rchild) s.push(p->rchild);
}
}
}
}
//後序遍歷的非遞迴演算法
void PostOrder(Btree*b)
void PostOrder(Btree*b)
{
Btree*p,*r;
stack<Btree*>s;
p = b;
bool flag;
do
{
while (p)
{
s.push(p);
p = p->lchild;
}
r = NULL;
flag = true;//flag == true 表示正在處理棧頂結點
while (!s.empty() && flag)
{
p = s.top();
if (p->rchild == r)//如果右子樹為空或者已經被訪問過
{
cout << p->data << " ";
s.pop();
r = p;
}
else
{
p = p->rchild;
flag = false;
}
}
} while (!s.empty());
}
//層次遍歷
void LevelOrder(Btree*b)
{
queue<Btree*>q;
Btree*p;
if (b)
{
q.push(b);
while (!q.empty())
{
p = q.back();
q.pop();
cout << p->data << " ";
if (p->lchild) q.push(p->lchild);
if (p->rchild) q.push(p->rchild);
}
}
}
void CreateTree(Btree*&b)
{
b = new Btree;
b->lchild = b->rchild = NULL;
int x;
cin >> x;
if (x != 0)
{
b->data = x;
CreateTree(b->lchild);
CreateTree(b->rchild);
}
else b = NULL;
}
int main()
{
Btree*b;
CreateTree(b);
cout << "先序遍歷演算法1如下:" << endl;
PreOrder1(b);
cout << "先序遍歷演算法2如下:" << endl;
PreOrder2(b);
cout << "中序遍歷演算法如下:" << endl;
InOrder(b);
cout << "後序遍歷的演算法如下:" << endl;
PostOrder(b);
cout << "層次遍歷的演算法如下:" << endl;
LevelOrder(b);
return 0;
}