您的位置:首页 > 其它

二叉树的建立、三种(递归、非递归)遍历方法

2015-06-08 21:42 543 查看
二叉树定义:

1.有且仅有一个特定的称之为根root的结点

2.当n>1时,除根结点之外的其余结点分为两个互不相交的子集。他们称为二叉树的左子树和右子树。

二叉树的一种建立方法:

若对有n个结点的完全二叉树进行顺序编号(1<=i<=n),那么,对于编号为i(i>=1)的结点。

当i=1时,该结点为根,它无双亲结点;

当i>1时,该节点的双亲编号为[i/2];

若2i<=n,该结点为编号为2i的左孩子,否则没有左孩子

当2i+1<=n,该结点有编号为2i+1的右孩子,否则没有右孩子

利用上个性质,对任意二叉树,先按满二叉树对其所有结点进行编号。

注意:由于此树并非完全树,所以结点的编号并不连续。

遍历二叉树:

遍历二叉树是指以一定的次序访问二叉树中的每个结点,并且每个结点仅被访问一次,访问结点是指进行各种操作的简称。3种遍历次序:中根遍历二叉树、先根遍历二叉树、后根遍历二叉树。

递归算法:

先根遍历:如果根不为空,1.访问根结点2.按先根次序遍历左子树,3.按先根次序遍历右子树,否则返回。

中根遍历:如果根不为空,1.按中根次序遍历左子树,2.访问根结点,3.按中根次序遍历右子树,否则返回。

后根遍历:如果根不为空,1.按后根次序遍历左子树,2.按后根次序遍历右子树,3.访问根结点,否则返回。

中根遍历非递归算法:

需要人为设置一个栈来存放所经过的根结点的指针(栈我图简单,直接调用STL标准库的),第一次遇到根结点并不访问,而是如栈,然后中根遍历左子树。左子树遍历结束后,第二次遇到根结点,退栈并访问该结点。然后遍历右子树。

先根遍历非递归算法:同中根遍历非递归算法,只是把输出位置提前

后根遍历非递归算法:

后根遍历在搜索线第一次经过根结点时不访问进行如栈,在遍历左子树之后,搜索线第二次经过根结点时也不能访问,继续遍历右子树,直到搜索线第三次经过根结点时,退栈并且访问根结点。因此,另设一个辅助栈用来记录经过某个结点的次数。

废话少说,上代码......

BinaryTree.h

#ifndef BINARYTREE_H_
#define BINARYTREE_H_
typedef int T;
struct Node
{
T data;
Node *lch;
Node *rch;
};
class BinaryTree
{
protected:
Node *root;
public:
BinaryTree();
~BinaryTree();
void Create();
void preorder();
void Preorder()
{
Preorder(root);
}
void inorder();
void Inorder()
{
Inorder(root);
}
void postorder();
void Postorder()
{
Postorder(root);
}
private:
void Inorder(Node *p);
void Preorder(Node *p);
void Postorder(Node *p);
void Destroy(Node *p);
};

#endif
BinaryTree.cpp

#include "BinaryTree.h"
#include <iostream>
#include <stack>
using namespace std;
BinaryTree::BinaryTree()
{
root=NULL;
}
BinaryTree::~BinaryTree()
{
Destroy(root);
root=NULL;
}
void BinaryTree::Inorder(Node *p)
{
if(p!=NULL)
{
Inorder(p->lch);
cout<<p->data<<" ";
Inorder(p->rch);
}
}
//非递归法实现中根遍历
void BinaryTree::inorder()
{
Node *p=root;
Node *q;
stack<Node *> S;
do
{
while(p!=NULL)
{
S.push(p);
p=p->lch;
}
p=S.top();
S.pop();
cout<<p->data<<" ";
p=p->rch;
}while(!(S.empty() && p==NULL));
}
//先根遍历,用递归法
void BinaryTree::Preorder(Node *p)
{
if(p!=NULL)
{
cout<<p->data<<" ";
Preorder(p->lch);
Preorder(p->rch);
}
}
//先根遍历的非递归算法
void BinaryTree::preorder()
{
Node *p=root;
stack<Node *> S;
do
{
while(p!=NULL)
{
S.push(p);
cout<<p->data<<" ";
p=p->lch;
}
p=S.top();
p=p->rch;
S.pop();
}while(!(S.empty() && p==NULL));
}
//后根
void BinaryTree::Postorder(Node *p)
{
if(p!=NULL)
{
Postorder(p->lch);
Postorder(p->rch);
cout<<p->data<<" ";
}
}
//非递归法实现后根遍历
void BinaryTree::postorder()
{
stack<Node *>S;
stack<int> s;
Node *p=root;
int t=0;
do
{
while(p!=NULL)
{
s.push(1);
S.push(p);
p=p->lch;
}
t=s.top();
if(t==2)
{
p=S.top();
S.pop();
s.pop();
cout<<p->data<<" ";
p=NULL;
}
if(!s.empty())
{
t=s.top();
}
if(t==1)
{
p=S.top();
p=p->rch;
s.pop();
s.push(2);
}

}while(!(S.empty() && p==NULL));
}
void BinaryTree::Destroy(Node *p)
{
if(p!=NULL)
{
Destroy(p->lch);
Destroy(p->rch);
delete p;
}
}

void BinaryTree::Create()
{
Node *q, *s[20]; T x; int i,j;
cout<<"请按照二叉树的层序,自上而下自左至右的顺序组织数据"<<endl;
cout<<"每次输入结点的序号和数据,假设根结点值为11;"<<endl;
cout<<"那么输入应是:1 11,若两者都输入0,则输入结束。"<<endl;
root=NULL;
cout<<"i,x = "; cin>>i>>x;
while((i!=0)&&(x!=0))
{
q=new Node;
q->data=x;
q->lch=NULL;
q->rch=NULL;
s[i]=q;
if(i==1)
{
root=q;
}
else
{
j=i/2;
if(i%2==0)
{
s[j]->lch=s[i];
}
else
{
s[j]->rch=s[i];
}
}
cout<<"i,x = "; cin>>i>>x;
}
cout<<"二叉树建立完毕!"<<endl;
}
main.cpp

//直接调用STL库中的栈吧,不在
#include "BinaryTree.h"
#include <iostream>

using namespace std;

int main()
{
/*cout<<"hello,world"<<endl;*/
BinaryTree BT;
BT.Create();
cout<<"先根遍历二叉树:"<<endl;
BT.Preorder();
cout<<endl<<"先根非递归遍历二叉树:"<<endl;
BT.preorder();
cout<<endl<<"中根遍历二叉树:"<<endl;
BT.Inorder();
cout<<endl<<"中根非递归遍历二叉树:"<<endl;
BT.inorder();
cout<<endl<<"后根遍历二叉树:"<<endl;
BT.Postorder();
cout<<endl<<"后根非递归遍历二叉树:"<<endl;
BT.postorder();
cout<<endl;
system("pause");
return 0;
}
结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: