數據結構基礎(5) 樹與森林

CONTENT

  • 樹的存儲結構:
    1.雙親表示
    2.孩子鏈表表示
    3.樹的二叉鏈表(重點)
  • 樹,森林與二叉樹的轉換(firstchild,nextsibling)
  • 遍歷
    在這裏插入圖片描述
  • 如何建樹:轉爲二叉樹利用二叉樹序列來建樹;直接對輸入的父親孩子對進行建樹
#include "stdio.h"
#include "stdlib.h"
#define N 30

typedef struct node
{
	char data;
	struct node *fir,*sib,*pa;//左第一個孩子(子樹森林),兄弟節點(其餘子樹構成的森林),父節點 
}TR;

TR *createtree(char *pre,int *k);//建樹 
int height(TR *T);//求樹的高度(遞歸:max(子樹的高度加1與其餘樹組成森林中樹高度的最大值)) 
void preorder(TR *T);//先序遍歷 (相當於二叉樹的先序遍歷) \*/ 
void postorder(TR *T);//後序遍歷 (相當於二叉樹的中序遍歷)\*/
void layer(TR *T);//層次遍歷 (隊列,非遞歸) 
TR *deltree(TR *T);//刪除樹 
void showtree(TR *T);//括號形式顯示樹 
void getpa(TR *T);//爲節點的父節點賦值 
void showpa(TR *T);//輸出各點的父節點 
TR *findpa(TR *T,TR **pa,char data);//返回值爲data的節點指針,同時靠二重指針帶出其父節點的指針 
void allpath(TR *T,char *route,int top); //輸出所有根到葉子的路徑 



main()
{
	char pre[]="ABE F  C DGH I J     ";
	TR *T=NULL,*p,*pa;
	char data;
	int k=0;
	T=createtree(pre,&k);
	printf("\n樹:\n");
	if(!T)
		printf("樹爲空\n");
	else
	    showtree(T);	
	printf("\n\n");
	printf("\n先序遍歷:\n");
	preorder(T);
	printf("\n後序遍歷:\n");
	postorder(T);
	printf("\n層次遍歷:\n");
	layer(T);
	printf("\n樹的高度=%d\n",height(T));
	printf("\n\n請輸入帶查找的節點數據:");
	scanf("%c",&data);
	while(data!='#')
	{
		getchar();
		pa=p=NULL;
		p=findpa(T,&pa,data);
		if(!p)
			printf("%c不存在\n",data);
		else
		{
			if(!pa)
				printf("%c是根節點,沒有父節點\n",data);
			else
				printf("%c的父節點是%c\n",data,pa->data);
		}
		printf("\n請輸入帶查找的節點數據:");
	    scanf("%c",&data);
	}
	printf("\n");
	getpa(T);
	showpa(T);
	char route[N];
	printf("輸出所有到葉子節點的路徑:\n");
	allpath(T,route,-1);
	T=deltree(T);	
}


TR *createtree(char *pre,int *k)
{
	TR *T;
	if(pre[*k]==' ')
		return NULL;
	else
	{
		T=(TR *)malloc(sizeof(TR));
		T->data=pre[*k];
		(*k)++;		
		T->fir=createtree(pre,k);
		(*k)++;
		T->sib=createtree(pre,k);
		return T;

	}

}
int height(TR *T)
{	
	int h1,h2;
	if(T)
	{	//一棵樹的高度是這棵樹的子樹高度加1與兄弟節點樹高度中的最大值 
		h1=1+height(T->fir);
		h2=height(T->sib);
		return h1>h2?h1:h2;
	}
	else return 0;
}



void preorder(TR *T)
{
	if(T)
	{
		printf("%c ",T->data);
		preorder(T->fir);
		preorder(T->sib);
	}
	
	
}

void postorder(TR *T)//樹的後序遍歷就是對應二叉樹的中序遍歷 
{
	TR *t[N],*p=T;
	int top=-1;
	while(top>=0||p)
	{
		while(p)
		{
			top++;
			t[top]=p;
			p=p->fir;
		}
		p=t[top];
		top--;
		printf("%c ",p->data);
		p=p->sib;
	}
	/*if(T)
	{
		postorder(T->fir);
		printf("%c ",T->data);
		postorder(T->sib);
	}*/
	
	
}
void layer(TR *T)//隊列 
{
	TR *p=T;
	int front=-1,rear=-1;
	TR *t[N];
	t[++rear]=T;
	printf("%c ",p->data);
	while(rear!=front)
	{	
		p=t[front+1]->fir;
		while(p)
		{	
			t[++rear]=p;
			printf("%c ",p->data);
			p=p->sib;
		}
		front++;
		
	}
	printf("\n");
}

TR *deltree(TR *T)//銷燬樹
{
	TR *p=T,*p2;
	if(!T)
		return NULL;
	else
	{
		p=T->fir;
		while(p)
		{
			p2=p->sib;
			free(p);
			p=p2;
		}
		free(T);
		return NULL;
	}
	
}
void showtree(TR *T)
{	
	TR *p;
	if(T)
	{
		printf("%c",T->data);
		p=T->fir;
		if(p)
		{	
			printf("(");
			showtree(p);
			p=p->sib;
			while(p)
			{	
				printf(",");
				showtree(p);
				p=p->sib;
			}
			printf(")");
		} 
	} 
}


TR *findpa(TR *T,TR **pa,char x)
{
	TR *target=NULL,*p;
	if(T)
	{
		if(T->data==x)
		{	*pa=NULL;
			return T;
		}
		else
		{
			p=T->fir;
			while(p)
			{	if(p->data==x)
				{
					*pa=T;
					return p; 
				}
				target=findpa(p,pa,x);
				if(target) return target;
				p=p->sib;
			}
		}
	 } 
}


void getpa(TR *T)
{	
	TR *p;
	if(T)
	{
		p=T->fir;
		while(p)
		{	
			getpa(p);
			//與p->pa順序不能呼喚,不然先賦值正確的pa被後來的NULL覆蓋了 
			p->pa=T;
			p=p->sib;
		}
		T->pa=NULL;	
	}
	
}
void showpa(TR *T)
{
	if(T)
	{
		if(!(T->pa))
			printf("%c---NULL\n",T->data);
		else
			printf("%c---%c\n",T->data,T->pa->data);
		showpa(T->fir);
		showpa(T->sib);
	}	
}
void allpath(TR *T,char *route,int top)
{	TR *p;
	if(T)
	{	route[++top]=T->data;
		if(!T->fir)
		{
			int i;
			for(i=0;i<=top;i++)
			printf("%c ",route[i]);
			printf("\n");
		}
		else
		{	
			p=T->fir;
			while(p)
			{
				allpath(p,route,top);
				p=p->sib; 
			}	
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章