二叉树主要有三种遍历方式:前序遍历、中序遍历和后序遍历,每种方式都有递归和非递归两种方法。递归的方法简单明了,但是会比较耗时,非递归的方法效率相对较高,但是算法也比较晦涩。本文就这三种遍历方式做简单的介绍。
数据结构:
struct BTree{ int data; BTree *lchild; BTree *rchild; };
一、 前序遍历
1. 递归的算法:
前序遍历每次先访问根结点,然后访问左子树,接着是右子树。用递归的方法很容易写出递归的算法:
void preTraverse(BTree *t) { cout<<t->data<<" "; if(t->lchild) preTraverse(t->lchild); if(t->rchild) preTraverse(t->rchild); }
2. 非递归算法:
由于函数的递归调用归根到底使用的是栈保存相关的变量,我们可以按照递归调用的过程,借助于栈将递归的算法改成非递归的算法。
void preOrder(BTree *t) { stack<BTree *> stk; stk.push(t); while(!stk.empty()) { BTree *q = stk.top(); stk.pop(); cout<<q->data<<" "; if(q->rchild) stk.push(q->rchild); if(q->lchild) stk.push(q->lchild); } cout<<endl; }这里我们采用一个栈保存访问过的节点,先访问根节点,然后将右子树根节点入栈,接着是左子树根节点。之所以先右后左,因为栈是后进先出的数据结构,我们要先访问左子树后访问右子树,所以要先将右子树根节点入栈再将左子树根节点入栈。
二、 中序遍历
1. 递归算法:
中序遍历先访问左子树,然后访问根节点,接着访问右子树。递归的算法如下:
void inTraverse(BTree *t) { if(t->lchild) inTraverse(t->lchild); cout<<t->data<<" "; if(t->rchild) inTraverse(t->rchild); }
中序遍历的时候,先访问左子树,再访问根节点,接着是右子树,那么我们需要用栈保存未访问的节点。当节点的左子树已经被访问之后,就将节点出栈,进行访问,然后将右子树根节点入栈。
void inOrder(BTree *t) { stack<BTree *> stk; BTree *p = t; while(!stk.empty() || p) { while(p) { stk.push(p); p = p->lchild; } p = stk.top(); cout<<p->data<<" "; stk.pop(); p = p->rchild; } cout<<endl; }
三、 后序遍历
1. 递归算法:
后序遍历的时候先访问左子树,然后是右子树,最后才访问根节点。递归算法如下:
void postTraverse(BTree *t) { if(t->lchild) postTraverse(t->lchild); if(t->rchild) postTraverse(t->rchild); cout<<t->data<<" "; }
后序遍历的非递归算法较复杂,因为后续遍历需要确认左右子树都访问之后才访问根节点,因此,不仅需要栈保存节点,而且需要有状态指示其左子树和右子树都已经被访问过了,这个时候才可以访问根节点。
void postOrder(BTree *t) { stack<BTree *> stk; vector<int> tag; int k = -1; BTree *p = t; while(!stk.empty() || p) { while(p) { stk.push(p); tag.push_back(1); ++k; p = p->lchild; } while(!stk.empty() && tag.back() == 2){ p = stk.top(); cout<<p->data<<" "; stk.pop(); tag.pop_back(); --k; } if(stk.empty()) break; p = stk.top(); tag[k] = 2; p = p->rchild; } cout<<endl; }
四、 层序遍历
二叉树的层序遍历有点类似于图的广度优先搜索算法,先访问根节点,接着将临近的每个节点都入队列,按照入队列/出队列的顺序访问每个元素。
//层序遍历---非递归---借助于队列 void levelOrder(BTree *t) { queue<BTree *> Q; Q.push(t); while(!Q.empty()) { BTree *q = Q.front(); Q.pop(); cout<<q->data<<" "; if(q->lchild) Q.push(q->lchild); if(q->rchild) Q.push(q->rchild); } cout<<endl; }
#include <iostream> #include <fstream> #include <string> #include <vector> #include <map> #include <algorithm> #include <stack> #include <queue> using namespace std; struct BTree{ int data; BTree *lchild; BTree *rchild; BTree(){ this->data = 0; this->lchild = NULL; this->rchild = NULL; } BTree(int d){ this->data = d; this->lchild = NULL; this->rchild = NULL; } }; BTree* buildNode(int a[], int k); void PrintTree(BTree *p); void preTraverse(BTree *t); void inTraverse(BTree *t); void postTraverse(BTree *t); void levelOrder(BTree *t); void preOrder(BTree *t); void inOrder(BTree *t); void postOrder(BTree *t); int main(int argc, char* argv[]) { int n; while(cin>>n) { int *a = new int[n+1]; a[0] = n; for(int k = 1; k <= n; ++k) cin>>a[k]; BTree *t = buildNode(a, 1); PrintTree(t); cout<<"**************levelOrder--non-recursive********"<<endl; levelOrder(t); cout<<"*************************************************"<<endl; cout<<"--------------preTraverse--recursive-------------"<<endl; preTraverse(t); cout<<endl<<"-------------------------------------------------"<<endl; cout<<"**************preOrder--non-recursive********"<<endl; preOrder(t); cout<<"*************************************************"<<endl; cout<<"--------------inTraverse--recursive-------------"<<endl; inTraverse(t); cout<<endl<<"-------------------------------------------------"<<endl; cout<<"**************inOrder--non-recursive********"<<endl; inOrder(t); cout<<"*************************************************"<<endl; cout<<"--------------postTraverse--recursive-------------"<<endl; postTraverse(t); cout<<endl<<"-------------------------------------------------"<<endl; cout<<"**************postOrder--non-recursive********"<<endl; postOrder(t); cout<<"*************************************************"<<endl; } return 0; } //后续遍历---非递归 void postOrder(BTree *t) { stack<BTree *> stk; vector<int> tag; int k = -1; BTree *p = t; while(!stk.empty() || p) { while(p) { stk.push(p); tag.push_back(1); ++k; p = p->lchild; } while(!stk.empty() && tag.back() == 2){ p = stk.top(); cout<<p->data<<" "; stk.pop(); tag.pop_back(); --k; } if(stk.empty()) break; p = stk.top(); tag[k] = 2; p = p->rchild; } cout<<endl; } //中序遍历---非递归 void inOrder(BTree *t) { stack<BTree *> stk; BTree *p = t; while(!stk.empty() || p) { while(p) { stk.push(p); p = p->lchild; } p = stk.top(); cout<<p->data<<" "; stk.pop(); p = p->rchild; } cout<<endl; } //先序遍历---非递归----借助于栈 void preOrder(BTree *t) { stack<BTree *> stk; stk.push(t); while(!stk.empty()) { BTree *q = stk.top(); stk.pop(); cout<<q->data<<" "; if(q->rchild) stk.push(q->rchild); if(q->lchild) stk.push(q->lchild); } cout<<endl; } //层序遍历---非递归---借助于队列 void levelOrder(BTree *t) { queue<BTree *> Q; Q.push(t); while(!Q.empty()) { BTree *q = Q.front(); Q.pop(); cout<<q->data<<" "; if(q->lchild) Q.push(q->lchild); if(q->rchild) Q.push(q->rchild); } cout<<endl; } //后序遍历 void postTraverse(BTree *t) { if(t->lchild) postTraverse(t->lchild); if(t->rchild) postTraverse(t->rchild); cout<<t->data<<" "; } //中序遍历 void inTraverse(BTree *t) { if(t->lchild) inTraverse(t->lchild); cout<<t->data<<" "; if(t->rchild) inTraverse(t->rchild); } //pre-order void preTraverse(BTree *t) { cout<<t->data<<" "; if(t->lchild) preTraverse(t->lchild); if(t->rchild) preTraverse(t->rchild); } BTree* buildNode(int a[], int k){//构建第k个Node if(k > a[0] || a[k] == -1) return NULL; BTree *p = new BTree(a[k]); p->lchild = buildNode(a, 2*k); p->rchild = buildNode(a, 2*k+1); return p; } void PrintTree(BTree *p) { int k = 1, cnt = 0; queue<BTree *> que; que.push(p); while(!que.empty()) { BTree *q = que.front(); que.pop(); if(q->lchild != NULL) que.push(q->lchild); if(q->rchild != NULL) que.push(q->rchild); cout<<q->data<<" "; ++cnt; if(cnt == k){ cout<<endl; k = 2*k; cnt = 0; } } if(cnt != 0) cout<<endl; }
原文地址:http://blog.csdn.net/uilotus/article/details/38332701