資料結構(八)
阿新 • • 發佈:2019-01-26
二叉樹(二分表示法)
此處有前提
以下是二叉樹的基本操作,包括二叉樹的建立,先序、中序、後序(遞迴和非遞迴方法)、層序遍歷、求二叉樹的高度、寬度,結點數、判斷是否為二叉排序樹等。
#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.以前 接觸的資料結構主要都是線性表,學習到樹這塊的各種函式編寫時,雖然一開始都沒啥思路,但是參考他人的見解之後的豁然開朗帶來的喜悅很值得分享給大家。
學習到這個階段,有句話送給大家:不忘初衷,砥礪前行。