1. 程式人生 > >資料結構(八)

資料結構(八)

二叉樹(二分表示法)

此處有前提

以下是二叉樹的基本操作,包括二叉樹的建立,先序、中序、後序(遞迴和非遞迴方法)、層序遍歷、求二叉樹的高度、寬度,結點數、判斷是否為二叉排序樹等。

#define SIZE sizeof(BiTNode)
#define ElemType char
#include<iostream>
#include<stdlib.h>
#include<stack>
#include<queue>
using namespace std;
typedef struct BiTNode{
	ElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void InitBiTree(BiTree &T){
	if(!(T=(BiTree)malloc(SIZE))) exit(-2);
	T->lchild=NULL;
	T->rchild=NULL;
}
void DestroyBiTree(BiTree &T){
	if(T){
		if(T->lchild)	DestroyBiTree(T->lchild);
		if(T->rchild)	DestroyBiTree(T->rchild);
		free(T);//T左右兩孩子都為NULL之後釋放T 
		T=NULL;
	}
} 
void CreateBiTree(BiTree &T){
	ElemType temp;
	cin>>temp;
	if(temp=='#') T=NULL;//以#代表NULL 
	else{
		if(!(T=(BiTree)malloc(SIZE))) exit(-2);
		T->data=temp;
		CreateBiTree(T->lchild);
		CreateBiTree(T->rchild);
	}
}
void ClearBiTree(BiTree &T){
	if(T){//如果T為NULL不執行任何操作 
		if(T->lchild)	ClearBiTree(T->lchild);
		if(T->rchild)	ClearBiTree(T->rchild);
		T=NULL;
	}
}
bool BiTreeEmpty(BiTree T){
	return T==NULL;
}
int BiTreeDepth(BiTree T){//當前結點的深度是其孩子結點深度加一 
	if(!T) return 0;
	int LDepth=BiTreeDepth(T->lchild);
	int RDepth=BiTreeDepth(T->rchild);
	return (LDepth>RDepth?LDepth:RDepth)+1;
}
ElemType Root(BiTree T){
	if(!T) exit(-2);
	return T->data; 
}
ElemType Value(BiTree T,BiTNode* e){		
	if(!e) exit(-2);
	return e->data;
}
bool Assign(BiTree &T,BiTNode *e,ElemType value){
	if(!e) return false;
	e->data=value;
	return true;	
}
BiTNode* Parent(BiTree T,BiTNode *e){
	BiTNode* q;
	if(e==T||!T) 	return NULL;
	if((T->lchild && T->lchild==e) || (T->rchild && T->rchild==e))  return T;
    if(q = Parent(T->lchild, e)) return q;  
    else if(q = Parent(T->rchild, e)) return q;  
    else return NULL;  		
}
BiTNode* LeftChild(BiTree T,BiTNode *e){
	return T->lchild;
}
BiTNode* RightChild(BiTree T,BiTNode *e){
	return T->rchild;
}
BiTNode* LeftSibling(BiTree T,BiTNode *e){
	BiTNode* temp=Parent(T,e);
	if(temp)	return temp->lchild;
	return NULL;
}
BiTNode* RightSibling(BiTree T,BiTNode *e){
	BiTNode* temp=Parent(T,e);
	if(temp)	return temp->rchild;
	return NULL;
}
bool InsertChild(BiTree &T,BiTNode *p,int LR,BiTree c){//LR為0插作左子樹,LR為1插作右子樹 
	if(!T) return false;
	if(LR){
		c->rchild=p->rchild;
		p->rchild=c;
	}else{
		c->rchild=p->lchild;
		p->lchild=c;
	}
	return true;
}
bool DeleteChild(BiTree &T,BiTNode *p,int LR){
	if(!T) return false;
	if(LR)
		DestroyBiTree(p->rchild);
	else
		DestroyBiTree(p->lchild);
	return true;
}
void PreOrderTraverseRecursion(BiTree T){	//遞迴實現 
	if(T){
		cout<<T->data;
		PreOrderTraverseRecursion(T->lchild);
		PreOrderTraverseRecursion(T->rchild);
	}
}
void PreOrderTraverse(BiTree T){			//非遞迴實現 
	if(!T) exit(-2);
	std::stack<BiTree> s;
	while(T||!s.empty()){
		if(T){
			cout<<T->data;
			s.push(T);
			T=T->lchild;
		}else{
			T=s.top();
			s.pop();
			T=T->rchild;
		}
	}
}
void InOrderTraverseRecursion(BiTree T){
	if(T){
		InOrderTraverseRecursion(T->lchild);
		cout<<T->data;
		InOrderTraverseRecursion(T->rchild);
	}
}
void InOrderTraverse(BiTree T){
	if(!T) exit(-2);
	std::stack<BiTree> s;
	while(T||!s.empty()){
		if(T){		
			s.push(T);
			T=T->lchild;
		}else{
			T=s.top();
			cout<<T->data;
			s.pop();
			T=T->rchild;
		}
	}
}
void PostOrderTraverseRecursion(BiTree T){
	if(T){
		PostOrderTraverseRecursion(T->lchild);
		PostOrderTraverseRecursion(T->rchild);
		cout<<T->data;
	}
}
void PostOrderTraverse(BiTree T){//後序遍歷是參考網上的idea 
	if(!T) exit(-2);
	std::stack<BiTree> s;
	BiTNode *temp=NULL,*cur=T;
	while(cur){
		s.push(cur);
		cur=cur->lchild;
	}
	while(!s.empty()){
		cur=s.top();
		s.pop();
		if(!cur->rchild||cur->rchild==temp){
			cout<<cur->data;
			temp=cur;
		}else{
			s.push(cur);
			cur=cur->rchild;
			while(cur){
				s.push(cur);
				cur=cur->lchild;
			}
		}
	} 	
}
void LevelOrderTraverse(BiTree T){
	if(!T) exit(-2);
	std::queue<BiTree> q;
	q.push(T);
	while(!q.empty()){
		BiTNode *temp=q.front();
		q.pop();
		if(temp) cout<<temp->data;
		if(temp->lchild)
			q.push(temp->lchild); 
		if(temp->rchild)
		 	q.push(temp->rchild);
	}
}
bool DeleteByValue(BiTree &T,ElemType e){
	bool flag;
	if(!T) return false;
	BiTNode* temp;
	if(T->data==e){
		DestroyBiTree(T->lchild);
		DestroyBiTree(T->rchild);
		return true; 
	}else{
		if(flag=DeleteByValue(T->lchild,e)) return flag;
		else if(flag=DeleteByValue(T->rchild,e)) return flag;
		else return false;
	}
}
bool JudgeCompeletBiTree(BiTree T){//判斷完全二叉樹 
	std::queue<BiTree> q;
	BiTNode *temp;
	q.push(T);
	while(temp=q.front()){
		q.pop();
		q.push(temp->lchild);//不論孩子是否為NULL都放入 
		q.push(temp->rchild);
	}
	while(!q.empty()){ 
		temp=q.front();
		q.pop();
		if(temp)	//若佇列中的第一個空元素之後還有非空元素	
			return false;
	}
	return true;
}
bool JudgeBiSortedTree(BiTree T){	//中序遍歷二叉樹能得到一個有序序列 
	if(!T) exit(-2);
	std::stack<BiTree> s;
	int temp=-1; 
	while(T||!s.empty()){
		if(T){		
			s.push(T);
			T=T->lchild;
		}else{
			T=s.top();
			if(T->data<temp)
				return false;
			temp=T->data;
			s.pop();
			T=T->rchild;
		}
	}
	return true;
}
int main(){
	BiTree T;
	/*	   A 			
		 B
	   C   D		樹的圖示 
		 E   F
	   G
	*/
	InitBiTree(T);
	//A B C # # D E # G # # F # # #
	CreateBiTree(T);
	BiTNode	*temp,*c;
	temp=T->lchild->rchild->lchild;
	cout<<Value(T,temp);
	c=Parent(T,temp);
	DeleteChild(T,c,1);
	cout<<"\nE點的父親為:"<<c->data; 
	cout<<"\n樹的深度為:"<<BiTreeDepth(T);
	cout<<"\n根節點為:"<<Root(T);
	cout<<"\n先序遍歷的結果是:"; 
	PreOrderTraverse(T);
	cout<<endl<<JudgeCompeletBiTree(T);
	cout<<"\n刪除值為D的點後的結果是:";
	DeleteByValue(T,'D');
	PreOrderTraverse(T);
	cout<<"\n層次遍歷的結果是:";
	LevelOrderTraverse(T);
	cout<<"\n後序遍歷的結果是:";
	PostOrderTraverse(T);	
	cout<<"\n中序遍歷的結果是:"; 
	InOrderTraverseRecursion(T);
	DestroyBiTree(T);
	return 0;
}

對二叉樹的各類函式編寫讓我受益很大的主要幾點在於:

1.對遞迴的理解更深一層,雖然還是迷迷糊糊,但是這個感受很強烈。

2.對棧、佇列的運用,讓我意識到這兩類資料結構實用性真的高。

3.以前 接觸的資料結構主要都是線性表,學習到樹這塊的各種函式編寫時,雖然一開始都沒啥思路,但是參考他人的見解之後的豁然開朗帶來的喜悅很值得分享給大家。

學習到這個階段,有句話送給大家:不忘初衷,砥礪前行。