二叉树的建立(非递归建立与定义建立)与基本操作(广度和深度遍历,求叶子树高)实现

      二叉树的建立可以用二叉树性质第六条建立,也可以按照完全二叉树的定义来建立。

      遍历主要分为广度优先遍历和深度优先遍历,深度优先遍历又分为递归前序遍历、递归后序遍历、递归中序遍历,和非递归前序遍历、非递归后序遍历、非递归中序遍历。

      广度优先遍历主要用队列的思想实现,而深度优先遍历如上述所说用递归和非递归思想实现。


现在说说建立和遍历的实现思想。

       二叉树建立的基本思想是:依次输入节点信息,若输入的节点不是虚节点,则建立一个新节点。若新节点是第一个节点,则令其为根节点;否则将新节点作为孩子节点链接到它的双亲节点上。如此反复进行,直到输入结束标志#为止。为使新节点能够与双亲节点正确相连,以及考虑到这种方法中先建立的节点,其孩子节点也一定要先建立的特点,可以设置一个指针型的数组构成的队列来保存已输入的节点的地址,并使队尾(rear)指向当前输入的节点;对头(front)指向这个节点的双亲节点。由于根节点的地址放在队列的第一个单元里,因此当rear为偶数是,rear所指向的节点应作为左孩子与其双亲节点链接;否则rear所指向的节点应作为右孩子预期双亲节点链接。若双亲节点或孩子节点为虚节点,则无需链接。当双亲节点与两个孩子节点链接完毕,才进行出队操作,使对头指针指向下一个待链接的双亲节点。

       递归遍历的思想:符合人的思维逻辑,无需多说,只不过要搞清楚算法执行的内部步骤也是不容易的,有兴趣的诸君可以自行尝试。

       非递归遍历的思想:(中序遍历为例)使用一个堆栈stack[N]来保存每次调用的参数,这个堆栈的栈顶指针为top,另设一个活动指针p来指向当前访问的节点。当p所指向的节点非空,将该节点的地址进栈,然后将p指向该节点的左孩子节点;当p所指向的节点为空时,从栈顶退出栈顶元素,并访问该节点,然后将p指向该节点的右孩子节点;如此反复,直到p为空并且栈顶指针头top=-1为止。

      下面给出实现的代码和运行结果,还是秉持一贯的作风建议一句:将运行结果和代码对照起来学习,效果更明显。其中递归遍历全部实现了,而非递归遍历只实现了中序遍历,其他两种遍历留给诸君进行练习,学了之后总要检验下学会了没有吧?哈哈

/*********************\
Author:Harrykate
Date:2014/9/14
Time:17:08
Name:binarytree
\*********************/
#include "iostream"
#include "malloc.h"
using namespace std;

#define Maxsize 1024

typedef char datatype;
typedef struct node
{
	datatype data;
	struct node*lchild,*rchild;
}bitree;


bitree*CreatTree()//非递归的方式建立完全二叉树
{
	cout<<"连续输入字符建立完全二叉树,并以‘#’结束"<<endl;
	char ch;
	bitree*Q[Maxsize];
	int front,rear;
	bitree*root,*s;
	root=NULL;
	front=1,rear=0;
	while ((ch=getchar())!='#')
	{
		s=NULL;
		s=(bitree*)malloc(sizeof(bitree));
		s->data=ch;
		s->lchild=NULL;
		s->rchild=NULL;
		rear++;
		Q[rear]=s;

		if (rear==1)
			root=s;
		else
		{
			if(s&&Q[front])
			{
				if(rear%2==0)
					Q[front]->lchild=s;
				else
					Q[front]->rchild=s;
			}
			if(rear%2==1)
				front++;
		}
	}
	return root;
}

bitree *CreatTree2(int i,int n)//定义的方式建立完全二叉树
	                           //不够通用,仅提供一种参考
{
	bitree *root;
	root=(bitree*)malloc(sizeof(bitree));
	root->data=i;
	if(2*i<=n)              //若2*i<=n,那么tree的左孩子为tree[2*i];
		root->lchild=CreatTree2(2*i,n);
	else
		root->lchild=NULL;
	if(2*i+1<=n)//若2*i+1<=n,那么tree的右孩子为tree[2*i+1];
		root ->rchild=CreatTree2(2*i+1,n);
	else
		root->rchild=NULL;
	return root;
}


void PreOrder(bitree*p)//前序递归遍历
{
	if (p!=NULL)
	{
		cout<<"->"<<p->data;
		PreOrder(p->lchild);
		PreOrder(p->rchild);
	}
}


void InOrder(bitree*p)//中序递归遍历
{
	if (p!=NULL)
	{
		InOrder(p->lchild);
		cout<<"->"<<p->data;
		InOrder(p->rchild);
	}
}

void NinOrder(bitree*p)//非递归的中序遍历,其他两种非递归遍历诸君自己实现
{
	bitree*stack[Maxsize];
	bitree*s=p;
	int top=-1;
	while (top!=-1||s!=NULL)
	{
		while (s!=NULL)
		{
			if (top==Maxsize-1)
			{
				cout<<"OVERFLOW";
				return;
			}
			else
			{
				top++;
				stack[top]=s;
				s=s->lchild;
			}
		}
		s=stack[top];
		top--;
		cout<<s->data;
		s=s->rchild;
	}
}

void PostOrder(bitree*p)//后序递归遍历
{
	if (p!=NULL)
	{
		PostOrder(p->lchild);
		PostOrder(p->rchild);
		cout<<"->"<<p->data;
	}
}


void Layer(bitree*p)//用队列实现广度优先遍历
{
	bitree*Q[Maxsize];
	bitree*s;
	int rear=1,front=0;
	Q[rear]=p;
	while (front<rear)
	{
		front++;
		s=Q[front];
		cout<<"->"<<s->data;
		if (s->lchild!=NULL)
		{
			rear++;
			Q[rear]=s->lchild;
		}
		if (s->rchild!=NULL)
		{
			rear++;
			Q[rear]=s->rchild;
		}
	}
}


int CountLeaf(bitree*p)//计算叶子节点数目
{
	if(!p)
		return 0;
	else if(!p->lchild&&!p->rchild)
		return 1;
	else
		return CountLeaf(p->lchild)+CountLeaf(p->rchild);
}

int Height(bitree*p)//计算数的高度
{
	int lc,rc;
	if(p==NULL)
		return 0;
	lc=Height(p->lchild)+1;
	rc=Height(p->rchild)+1;
	return lc>rc?lc:rc;
}

int main()
{
	bitree*p;
	int leaf,height;

	p=CreatTree();

	cout<<"深度优先遍历如下所示"<<endl<<endl;;

	cout<<"    前序遍历为";
	PreOrder(p);
	cout<<endl<<endl;

	cout<<"    中序遍历为";
	InOrder(p);
	cout<<endl<<endl;

	cout<<"    后序遍历为";
	PostOrder(p);
	cout<<endl<<endl;

	cout<<"广度优先遍历为";
	Layer(p);
	cout<<endl<<endl;

	leaf=CountLeaf(p);
	cout<<"叶子数目为:"<<leaf<<endl<<endl;
	height=Height(p);
	cout<<"数的高度为:"<<height<<endl<<endl;

	return 0;
}
运行结果如下:



终于写完了,代码有点多,工作量比较大。不过诸君能通过这篇博文学会二叉树的基本操作,那也是甚感欣慰的。

鼓掌!!




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章