二叉树的递归实现:
#include <iostream>
using namespace std;
#define LEN sizeof(struct Tree)
struct Tree
{
int key;
struct Tree*lchild;
struct Tree*rchild;
};
//二叉树的创建
void create(struct Tree **p)
{
*p=new struct Tree [LEN];
cout<<"请输入二叉树key值:(按0结束当前分支输入)"<<endl;
cin>>(*p)->key;
static i=0;
if ((*p)->key!=0)
{
create((&(*p)->lchild));
create((&(*p)->rchild));
}
}
//先序遍历递归过程。。。。(位置1)
void PreOderTraverse(struct Tree *p)
{//递归实现先序遍历
if (p->key)
{
cout<<p->key<<" ";
PreOderTraverse(p->lchild);
PreOderTraverse(p->rchild);
}
}
//中序遍历
void InOderTraverse(struct Tree *p)
{
if (p->key)
{
InOderTraverse(p->lchild);
cout<<p->key<<" ";
InOderTraverse(p->rchild);
}
}
//后序遍历
void BackOderTraverse(struct Tree *p)
{
if (p->key)
{
BackOderTraverse(p->lchild);
BackOderTraverse(p->rchild);
cout<<p->key<<" ";
}
}
void main()
{
struct Tree *p=NULL;
create(&p);
cout<<"先序遍历:"<<endl;
PreOderTraverse(p);
cout<<endl;
cout<<"中序遍历:"<<endl;
InOderTraverse(p);
cout<<endl;
cout<<"后序遍历:"<<endl;
BackOderTraverse(p);
cout<<endl;
}
二叉树的非递归实现:
这里我们主要谈一下先序遍历的非递归实现的三种方法。
1,可以直接用C++STL的栈实现:
头文件加上#include <stack>,将上面代码位置1的递归实现二叉树遍历过程替换以下代码即可实现。
//先序遍历非递归过程
void PreOderTraverse(struct Tree *root)
{ //用C++STL实现很容易。
if (root == NULL) return;
stack<struct Tree *>s;
s.push(root);
while (!s.empty()) {
struct Tree *p=s.top();
cout<<p->key<<" ";
s.pop();
if (p->rchild->key != 0)
{
s.push(p->rchild);
}
if (p->lchild->key != 0)
{
s.push(p->lchild);
}
}
cout << endl;
}
2.也可以用栈的数组实现,栈的实现,包括PUSH POP等栈操作全部自己实现。这个应该是符合《算法导论》10.4-3题目条件。
#include <iostream>
using namespace std;
#define LEN sizeof(struct Tree)
#define m 10//栈的最大容纳空间可以调整
struct Tree
{
int key;
struct Tree*lchild;
struct Tree*rchild;
};
struct Stack
{
int top;
int Array[m];
bool empty();
void push(struct Tree*);
int pop();
}s;
//判断栈是否为空
bool Stack::empty()
{
if (s.top==-1)
{
return true;
}
else
{
return false;
}
}
//入栈
void Stack::push(struct Tree*p)
{
if (s.top==m)
{
cerr<<"overflow!"<<endl;
}
else
{
s.top++;
s.Array[s.top]=reinterpret_cast<int>(p);//将树形结构体的地址转化为整数储存到栈里面。
}
}
//出栈
int Stack::pop()
{
if (empty())
{
cerr<<"underflow"<<endl;
return NULL;
}
else
{
s.top--;
return s.Array[s.top+1];
}
}
void create(struct Tree **p)
{
*p=new struct Tree [LEN];
cin>>(*p)->key;
static i=0;
if ((*p)->key!=0)
{
create((&(*p)->lchild));
create((&(*p)->rchild));
}
}
void PreOderTraverse(struct Tree *root)
{ //用栈的数组实现,POP PUSH等函数全部自己来写
if (root == NULL) return;
s.top=-1;
s.push(root);
struct Tree *p=root;
while (!s.empty()) {
p=reinterpret_cast<struct Tree *>(s.Array[s.top]);//将数组中的数据恢复为编译器所能识别的指针
cout<<p->key<<" ";
s.pop();
if (p->rchild->key != 0)
{
s.push(p->rchild);
}
if (p->lchild->key != 0)
{
s.push(p->lchild);
}
}
cout << endl;
}
void main()
{
struct Tree *p=NULL;
create(&p);
PreOderTraverse(p);
}
3.前2种都是用辅助栈的方法实现的,还有一种不用辅助栈,但需要父结点。
(1). 访问左孩子
(2). 访问右孩子
(3). 如果是从右孩子返回,表明整棵子树已访问完,需要沿树而上寻找父节点。直到是从左孩子返回,或者访问到根节点的父节点
#include <iostream>
#include <stack>
using namespace std;
#define LEN sizeof(struct Tree)
struct Tree
{
int key;
struct Tree*lchild;
struct Tree*rchild;
struct Tree*parent;
};
void create(struct Tree **p)
{
static struct Tree *p1=NULL;//p1保存当前结点的父亲结点
*p=new struct Tree [LEN];
cin>>(*p)->key;
(*p)->parent=p1;
p1=*p;
if ((*p)->key!=0)
{
create((&(*p)->lchild));
p1=*p;
create((&(*p)->rchild));
}
}
void InOderTraverse(struct Tree *p)
{
if(!p->key) return;
struct Tree *x=NULL;
while(1)
{
//访问左孩子
if(x != p->lchild)
{
while(p->lchild->key)
{
p=p->lchild;
}
}
cout<<p->key<<" ";
//访问右孩子
if(p->rchild->key)
{
p=p->rchild;
continue;
}
//回溯
do
{
x=p;
p=p->parent;
//访问到根节点的父节点(NULL)
if(!p) return;
}while(x==p->rchild);
}
}
void main()
{
struct Tree *p=NULL;
create(&p);
InOderTraverse(p);
}
这段代码遍历是借鉴网友的,但是创建的过程是自己写的,尤其是如何把父结点和这颗树相联系起来。