1. 程式人生 > >資料結構-樹與森林

資料結構-樹與森林

這裡我們討論樹的表示及其遍歷操作,並建立森林與二叉樹的對應關係。

用到的是孩子、兄弟表示法:鏈式儲存,每個結點包含資料域和兩個指標域,左指標指向第一個孩子結點。右指標指向兄弟結點。又稱二叉連結串列儲存法。

單顆樹的二叉連結串列儲存結構中根結點的右指標必為空,若要儲存多棵樹組成的森林,可將後一顆樹的根結點看成前一顆樹根結點的兄弟,即將後一顆樹對應的二叉連結串列拼接到前一顆樹根結點的右指標上,這稱為森林的孩子-兄弟表示法或二叉連結串列儲存法。

首先是輔助巨集:

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define UNDERFLOW -2
#define NULL 0
typedef int Status;
typedef char TElemType;

二叉樹的二叉鏈式儲存結構定義:

typedef struct BiTNode{
   TElemType data;
   struct BiTNode *lchild,*rchild; //左孩子結點 右孩子結點
}BiTNode,*BiTree;

森林的孩子-兄弟表示法的儲存結構定義:

typedef struct CSNode{
TElemType data;
struct CSNode *firstchild,*nextsibling;
}CSNode,*CSTree;

根據已經存在的二叉樹BiT 轉換成孩子兄弟表示法得到的樹或森林T 原二叉樹BiT保持不變.

Status BiTreetoTreeorForest(BiTree BiT,CSTree &T){
	//根據已經存在的二叉樹BiT 轉換成孩子兄弟表示法得到的樹或森林T 原二叉樹BiT保持不變
   if(!BiT)
	   T=NULL;
   else{
       T=(CSTree)malloc(sizeof(CSNode));
       if(!T)
		   exit(OVERFLOW);
	   T->data=BiT->data;
	   BiTreetoTreeorForest(BiT->lchild,T->firstchild);
       BiTreetoTreeorForest(BiT->rchild,T->nextsibling);
   }
   return OK;
}

先序遍歷樹T(森林的話 先序遍歷森林)相當於先序遍歷二叉連結串列儲存結構.

Status PrerootTraverse(CSTree T,Status (*visit)(TElemType)){
	//先序遍歷樹T(森林的話 先序遍歷森林)相當於先序遍歷二叉連結串列儲存結構
   if(!T)
	   return ERROR;
   else{
	   visit(T->data);
       PrerootTraverse(T->firstchild,visit);
       PrerootTraverse(T->nextsibling,visit);
   }
   return OK;
}

後序遍歷樹T(中序遍歷森林)相當於中序遍歷二叉連結串列儲存結構.

Status PostrootTraverse(CSTree T,Status (*visit)(TElemType)){
	//後序遍歷樹T(中序遍歷森林)相當於中序遍歷二叉連結串列儲存結構
   if(!T)
	   return ERROR;
   else{
       PostrootTraverse(T->firstchild,visit);
	   visit(T->data);
       PostrootTraverse(T->nextsibling,visit);
   }
   return OK;
}

求樹或這森林的深度.

int TreeorForestDepth(CSTree T){
	//求樹或這森林的深度
   int d,d1,d2;
   if(!T)
       d=0;
   else{
       d1=TreeorForestDepth(T->firstchild)+1;
       d2=TreeorForestDepth(T->nextsibling);
       d=d1>d2?d1:d2;
   }
   return d;
}

求樹或森林T的葉子數.

int LeafCount_TorF(CSTree T){
	/*求樹或森林T的葉子數
	思路:樹看做森林 森林或者為空 或者分為兩部分 第一課樹,其餘樹組成的子森林
	對後者的葉子樹計算可以遞迴完成 為保證遞迴時規模的減小 對第一顆樹而言 若其
	只有一個結點葉子數為1 否則其葉子數為該結點的子樹森林的葉子樹 ,而子樹森林
	的葉子數可以遞迴求得 第一課樹的葉子樹和其餘樹組成的子森林的葉子樹之和為整
	個森林的葉子樹*/
   int n1,n2;
   if(!T)
	   return 0;
   else {
	   //求第一顆樹的葉子樹
      if(!T->firstchild)
    	   n1=1;
      else  //第一顆樹的子樹森林的葉子樹
		  n1=LeafCount_TorF(T->firstchild);
	  //或其餘樹組成森林的深度
	  n2=LeafCount_TorF(T->nextsibling);
   }
   return n1+n2;
}