二叉樹的建立(非遞歸建立與定義建立)與基本操作(廣度和深度遍歷,求葉子樹高)實現

      二叉樹的建立可以用二叉樹性質第六條建立,也可以按照完全二叉樹的定義來建立。

      遍歷主要分爲廣度優先遍歷和深度優先遍歷,深度優先遍歷又分爲遞歸前序遍歷、遞歸後序遍歷、遞歸中序遍歷,和非遞歸前序遍歷、非遞歸後序遍歷、非遞歸中序遍歷。

      廣度優先遍歷主要用隊列的思想實現,而深度優先遍歷如上述所說用遞歸和非遞歸思想實現。


現在說說建立和遍歷的實現思想。

       二叉樹建立的基本思想是:依次輸入節點信息,若輸入的節點不是虛節點,則建立一個新節點。若新節點是第一個節點,則令其爲根節點;否則將新節點作爲孩子節點鏈接到它的雙親節點上。如此反覆進行,直到輸入結束標誌#爲止。爲使新節點能夠與雙親節點正確相連,以及考慮到這種方法中先建立的節點,其孩子節點也一定要先建立的特點,可以設置一個指針型的數組構成的隊列來保存已輸入的節點的地址,並使隊尾(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;
}
運行結果如下:



終於寫完了,代碼有點多,工作量比較大。不過諸君能通過這篇博文學會二叉樹的基本操作,那也是甚感欣慰的。

鼓掌!!




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