<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">看了一篇博客,感觉不错,在这里感谢一下原作者,自己顺手复习一下二叉树的遍历。</span>
http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html
http://www.seanyxie.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E4%B8%89%E7%A7%8D%E9%81%8D%E5%8E%86%E6%96%B9%E6%B3%95%EF%BC%88%E9%80%92%E5%BD%92%E5%92%8C%E9%9D%9E%E9%80%92%E5%BD%92%EF%BC%89/
http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html
二叉树的一些概念如下:
每个结点最多有两棵子树,左子树和右子树,次序不可以颠倒。
性质:
1、非空二叉树的第n层上至多有2^(n-1)个元素。
2、深度为h的二叉树至多有2^h-1个结点。
满二叉树:所有终端都在同一层次,且非终端结点的度数为2。
在满二叉树中若其深度为h,则其所包含的结点数必为2^h-1。
完全二叉树:除了最大的层次即成为一颗满二叉树且层次最大那层所有的结点均向左靠齐,即集中在左面的位置上,不能有空位置。
对于完全二叉树,设一个结点为i则其父节点为i/2,2i为左子节点,2i+1为右子节点。
其中二叉树的遍历是重点,包含先序遍历,中序遍历,后续遍历。
递归遍历比较简单,算法思想如下;
先序遍历:
递归进行先序遍历是先访问根节点,然后访问其左子树,最后访问其右子树。
代码如下:
void Tree::PreOrderVisit(Tree *T)
{
if (T)
{
cout << T->data << ' ';
PreOrderVisit(T->Left);
PreOrderVisit(T->Right);
}
}
根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左子树和右子树。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左子树不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:
对于任一结点P:
1)访问结点P,并将结点P入栈;
2)判断结点P的左子树是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右子树置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。
代码如下:
void Tree::NoPreRecursiveVist(Tree *T)
{
stack<Tree *>S; //用来保存的节点的栈
Tree *p;
p = T;
while (!S.empty() || p)
{
if (p) //p非空
{
S.push(p);
cout << p->data << ' ';
p = p->Left;
}
else
{
p = S.top();
S.pop();
p = p->Right;
}
}
}
中序遍历:
中序遍历的递归算法是先访问左子树,然后访问根节点,最后访问右子树。
代码如下:
//中序遍历树
void Tree::InOrderVisit(Tree *T)
{
if (T)
{
InOrderVisit(T->Left);
cout << T->data << ' ';
InOrderVisit(T->Right);
}
}
根据中序遍历的顺序,对于任一结点,优先访问其左子树,而左子树节点又可以看做一根结点,然后继续访问其左子树结点,直到遇到左子树结点为空的结点才进行访问,然后按相同的规则访问其右子树。因此其处理过程如下:
对于任一结点P,
1)若其左子树不为空,则将P入栈并将P的左子树置为当前的P,然后对当前结点P再进行相同的处理;
2)若其左子树为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右子树;
3)直到P为NULL并且栈为空则遍历结束
代码如下:
void Tree::NoInRecursiveVist(Tree *T)
{
stack<Tree *>S; //用来保存的节点的栈
Tree *p;
p = T;
while (!S.empty() || p)
{
if (p) //p非空
{
S.push(p);
p = p->Left;
}
else
{
p = S.top();
S.pop();
cout << p->data << ' ';
p = p->Right;
}
}
}
后序遍历:
后序遍历的递归算法是先访问左子树,然后访问右子树,最后访问根节点。
代码如下:
void Tree::LastOrderVisit(Tree *T)
{
if (T)
{
LastOrderVisit(T->Left);
LastOrderVisit(T->Right);
cout << T->data << ' ';
}
}
后序遍历的非递归算法是最复杂的,
代码如下:
void Tree::NoLastRecursiveVist(Tree *T)
{
stack<Tree *>S;
Tree *p;
Tree *pre = NULL;
p = T;
while (!S.empty() || p)
{
while (p)
{
S.push(p);
p = p->Left;
}
p = S.top();
if (p->Right == NULL || p->Right == pre)
{
cout << p->data << ' ';
pre = p;
p = NULL;
S.pop();
}
else
p = p->Right;
}
}
完整代码如下:
#pragma once
#ifndef _TREE_H
#define _TREE_H
#include<iostream>
#include<queue>
#include<stack>
class Tree
{
public:
Tree *Left;
Tree * Right;
char data;
Tree();
void CreateTree(Tree* &node);
void PreOrderVisit(Tree * T);
void InOrderVisit(Tree * T);
void LastOrderVisit(Tree * T);
void LevelOrderVisit(Tree * T);
void NoPreRecursiveVist(Tree *T);
void NoInRecursiveVist(Tree *T);
void NoLastRecursiveVist(Tree *T);
};
#endif
#include"tree.h"
#include<iostream>
using namespace std;
Tree::Tree()
{
}
//构造树
void Tree::CreateTree(Tree* &node)
{
char temp;
cout << "输入改节点的数据" << endl;
cin >> temp;
if (temp == 'c')
{
node = NULL;
}
else
{
node = new Tree;
node->data = temp;
CreateTree(node->Left);
CreateTree(node->Right);
}
}
//先序遍历树
void Tree::PreOrderVisit(Tree *T)
{
if (T)
{
cout << T->data << ' ';
PreOrderVisit(T->Left);
PreOrderVisit(T->Right);
}
}
//中序遍历树
void Tree::InOrderVisit(Tree *T)
{
if (T)
{
InOrderVisit(T->Left);
cout << T->data << ' ';
InOrderVisit(T->Right);
}
}
//后序遍历树
void Tree::LastOrderVisit(Tree *T)
{
if (T)
{
LastOrderVisit(T->Left);
LastOrderVisit(T->Right);
cout << T->data << ' ';
}
}
//层序遍历
void Tree::LevelOrderVisit(Tree *T)
{
queue<Tree *>Q;
if (!T)
return;
Q.push(T);
Tree *temp = NULL;
while (!Q.empty())
{
temp = Q.front();
cout << temp->data << ' ';
Q.pop();
if (temp->Left)
Q.push(temp->Left);
if (temp->Right)
Q.push(temp->Right);
}
}
//非递归的遍历树的三种方法
void Tree::NoInRecursiveVist(Tree *T)
{
stack<Tree *>S; //用来保存的节点的栈
Tree *p;
p = T;
while (!S.empty() || p)
{
if (p) //p非空
{
S.push(p);
p = p->Left;
}
else
{
p = S.top();
S.pop();
cout << p->data << ' ';
p = p->Right;
}
}
}
void Tree::NoPreRecursiveVist(Tree *T)
{
stack<Tree *>S; //用来保存的节点的栈
Tree *p;
p = T;
while (!S.empty() || p)
{
if (p) //p非空
{
S.push(p);
cout << p->data << ' ';
p = p->Left;
}
else
{
p = S.top();
S.pop();
p = p->Right;
}
}
}
void Tree::NoLastRecursiveVist(Tree *T)
{
stack<Tree *>S;
Tree *p;
Tree *pre = NULL;
p = T;
while (!S.empty() || p)
{
while (p)
{
S.push(p);
p = p->Left;
}
p = S.top();
if (p->Right == NULL || p->Right == pre)
{
cout << p->data << ' ';
pre = p;
p = NULL;
S.pop();
}
else
p = p->Right;
}
}
#include"tree.h"
#include<iostream>
using namespace std;
void main()
{
Tree *T = NULL;
T->CreateTree(T);
cout << "先序遍历" << endl;
T->PreOrderVisit(T);
cout << endl;
cout << "中序遍历" << endl;
T->InOrderVisit(T);
cout << endl;
cout << "后序遍历" << endl;
T->LastOrderVisit(T);
cout << endl;
cout << "层序遍历" << endl;
T->LevelOrderVisit(T);
cout << endl;
cout << "非递归先序遍历二叉树" << endl;
T->NoPreRecursiveVist(T);
cout << endl;
cout << "非递归中序遍历二叉树" << endl;
T->NoInRecursiveVist(T);
cout << endl;
cout << "非递归后序遍历二叉树" << endl;
T->NoLastRecursiveVist(T);
cout << endl;
system("pause");
}