考研數據結構---樹

                                           **樹**

樹的知識真的是很多!!!!
(一開始我以爲排序內容多呢,跪倒在樹面前,)
等九月份再二刷吧!!!!!
下圖整體結構框架

在這裏插入圖片描述
感覺比排序多的不是一點點!!!!!

王道中的算法
1.二叉樹的鏈式存儲結構

//二叉樹的鏈式存儲結構
typedef struct BiTNode{
	ElemType data;//數據域
	struct BiTNode *lchild,*rchild;//左,右孩子指針 
}; 

2.遍歷

//先序遍歷(記憶) 
void PreOrder(BiTree T)
{
	if(T!=NULL)
	{
		visit(T);//訪問根結點
		PreOrder(T->lchild);//訪問遍歷左子樹
		PreOrder(T->rchild);//訪問遍歷右孩子 
	}
}
//中序遍歷(記憶) 
void InOrder(BiTree T)
{
	if(T!=NULL)
	{
		PreOrder(T->lchild);//訪問遍歷左子樹
		visit(T);//訪問根結點
		PreOrder(T->rchild);//訪問遍歷右孩子 
	}
 } 
//後序遍歷(記憶) 
void PostOrder(BiTree T)
{
	if(T!=NULL)
	{
		PreOrder(T->lchild);//訪問遍歷左子樹
		PreOrder(T->rchild);//訪問遍歷右孩子 
		visit(T);//訪問根結點
	}
 } 
//中序遍歷的非遞歸算法
void InOrder2(BiTree T)
{
	//二叉樹中序遍歷的非遞歸算法,算法需要藉助一個棧
	InitStack(S);BiTree p=T;//初始化棧;p是遍歷指針
	while(p||!IsEmpty(S)){ //棧不空或p不空時循環 
		if(p){  //根指針進棧,遍歷左子樹 
			Push(S,p);//每遇到非空二叉樹先向左走
			p=p->lchild; 
		}
		else{ //根指針退棧,訪問根結點,遍歷右子樹 
			Pop(S,p);visit(p);
			p=p->rchild;
		}
		 
	} 
} 
//層次遍歷(記憶) 
void LevelOrder(BiTree T)
{
	InitQueue(Q);//初始化輔助隊列
	BiTree p;
	EnQueue(Q,T);//將根結點入隊
	while(!IsEmpty(Q)){//隊列不空循環
	    DeQueue(Q,p);//隊頭元素出隊
		visit(p);//訪問當前p所指向結點
		if(p->lchild!=NULL)
		   EnQueue(Q,p->lchild);//左子樹不空,則左子樹入隊列
		if(p->rchild!=NULL)
		   EnQueue(Q,p->rchild);//右子樹不空,則右子樹入隊列 
	} 
}

3.線索二叉樹

//線索二叉樹
//線索二叉樹的存儲結構
typedef struct ThreadNode{
	ElemType data;//數據元素
	struct ThreadNode *lchild,*rchild;//左,右孩子指針
	int ltag,rtag;//左右線索標誌 
}ThreadNode,*ThreadTree;
//中序遍歷對二叉樹線索化的遞歸算法
//指針pre指向中序遍歷時上一個剛剛訪問過的結點,用它來表示各結點訪問的前後關係 
void InThread(Thread &p,ThreadTree &pre)
{
	if(p!=NULL){
		InThread(p->lchild,pre);//遞歸,線索化左子樹
		if(p->lchild==NULL){
			//左子樹爲空,建立前驅線索
			p->lchild=pre;
			p->ltag=1; 
		}
		if(pre!=NULL &&pre->rchild==NULL){
		    pre->rchild=p;//建立前驅結點的後繼線索
			pre->rtag=1; 
		}
		pre=p;//標記當前結點成爲剛剛訪問過的結點
		InThread(p->rchild,pre);//遞歸,線索化右子樹 
	}
 } 
//中序遍歷建立中序線索二叉樹的主過程算法
void CreateInThread(ThreadTree T)
{
	ThreadTree pre=NULL;
	if(T!=NULL){
		//非空二叉樹,線索化
		InThread(T,pre);//線索化二叉樹
		pre->rchild=NULL;//處理遍歷的最後一個結點
		pre->rtag=1; 
	}
 } 
//線索二叉樹的遍歷
//求中序線索二叉樹中中序序列下的第一個結點
ThreadNode *Firstnode(ThreadNode *p)
{
	while(p->ltag==0) p=p->lchild;//最左下結點(不一定是葉結點)
	return p; 
 } 
//求中序線索二叉樹中結點p在中序序列下的後繼結點
ThreadNode *Nextnode(ThreadNode *p)
{
	if(p->rtag==0) return Firstnode(p->rchild);
	else return p->rchild;//rtag==1直接返回後繼線索 
 } 
//不含頭結點的中序線索二叉樹的中序遍歷算法
void Inorder(ThreadNode *T)
{
	for(ThreadNode *p=Firstnode(T);p!=NULL;p=Nextnode(p))
	visit(p); 
 } 

4.並查集

//並查集的結構定義
#define SIZE 100
int UFSets(SIZE);//集合元素數組(雙親指針數組)
//並查集的初始化操作(S即爲並查集)
void Initial(int S[])
{
	for(int i=0;i<size;i++)//每個自成單元素集合 
	  S[i]=-1;
 } 
//Find操作(函數在並查集S中查找並返回包含元素x的樹的根)
int Find(int S[],int x)
{
	while(S[x]>=0)//循環尋找x的根
	   x=S[x];
	   return x;//根的S[]小於0 
 } 
//Union操作(函數求兩個不相交子集合的並集)
void Union(int S[],int Root1,int Root2) 
{
	//要求Root1與Root2是不相同的,且表示子集合的名字
	S[Root2]=Root1;//將根Root2連接到另一根Root1下面 
}

5.二叉排序樹

//二叉排序樹
//二叉排序樹的查找
BSTNode *BST_Search(BiTree T,ElemType key,BSTNode *&p)
{
	//查找函數返回關鍵字值爲key的結點指針,若不存在,返回NULL
	p=NULL;//p指向被查找結點的雙親,用於插入和刪除操作中
	while(T!=NULL && key!=T->data){
		p=T;
		if(key<T->data) T=T->lchild;
		else T=T->rchild;
	} 
	return T;
 } 
//二叉排序樹的插入
int BST_Insert(BiTree &T,KeyType k)
{
	//在二叉排序樹T中插入一個關鍵字爲k的結點
	if(T==NULL)
	{
		//原樹爲空,新插入的記錄爲根結點
		T=(BiTree)malloc(sizeof(BSTNode));
		T->key=k;
		T->lchild=T->rchild=NULL;
		return 1;//返回1,表示成功 
	 } 
	 else if(k==T->key)//樹中存在相同關鍵字的結點
	    return 0;
	 else if(k<T->key)
	    return BST_Insert(T->lchild);//插入T的左子樹
	 else
	    return BST_Insert(T->rchild);//插入T的右子樹 
}
//二叉排序樹的構造
void Creat_BST(BiTree &T,KeyType str[],int n)
{
	//用關鍵字數組str[]建立一個二叉排序樹
	T=NULL;//初始時bt爲空樹
	int i=0;
	while(i<n){
		//依次將每個元素插入 
		BST_InSert(T,str[i]);
		i++;
	} 
 } 

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