[樹] 6.66 雙親表示法PTree 轉 孩子兄弟表示式CSTree
阿新 • • 發佈:2018-12-13
題目來源:嚴蔚敏《資料結構》C語言版本習題冊 6.66
【題目】6.66 假設有n個結點的樹T採用了雙親表示法,寫出由此建立樹的孩子-兄弟連結串列的演算法。
【答案】
/*---------------------------------
|6.66 雙親表示法-->孩子兄弟表示式|
---------------------------------*/
#define MAX_TREE_SIZE 50
typedef struct PTNode{
TElemType data;
int parent; //雙親的位置域
}PTNode;
typedef struct{
PTNode nodes[ MAX_TREE_SIZE];
int r,n;
}PTree;
CSTree CreateCSTreeByPTree(PTree T) {
CSNode *tmp[MAX_TREE_SIZE]; //建立一個輔助的陣列,仿照PTree結點的位置存放
CSNode *p, *q;
int i,parent;
if (T.n<=0) return NULL;
for (i=0; i<T.n; i++) { //雙親表按層序儲存
//建立新結點
p = (CSNode *)malloc(sizeof(CSNode)); if(!p) exit(OVERFLOW);
//賦值
p-> data = T.nodes[i].data;p->firstchild=p->nextsibling=NULL;
//連線
parent=T.nodes[i].parent; //父親
if (parent!=-1) { //不是根結點
if (tmp[parent]->firstchild==NULL) tmp[parent]->firstchild=p; //第一個孩子
else { //不是第一個孩子
for (q=tmp[parent]->firstchild; q->nextsibling; q=q->nextsibling) ; //找到最後一個孩子
q->nextsibling = p; //連線
}
}
tmp[i]=p;
}
return tmp[0];
}
【完整程式碼】
/*-------------------
|樹-孩子兄弟表達法 |
-------------------*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#ifndef BASE
#define BASE
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int bool;
#endif
#define TElemType char
typedef struct CSNode{
TElemType data;
struct CSNode *firstchild, *nextsibling;
}CSNode, *CSTree;
/*-------------------
|6.59 輸出T的所有邊 |
-------------------*/
void TreePrintEdge(CSTree T) {
CSNode *p;
for (p=T->firstchild; p; p=p->nextsibling) {
printf("(%c,%c)\n", T->data, p->data); //輸出T的孩子
TreePrintEdge(p); //輸出p的孩子
}
}
/*-------------------------
|6.60 統計葉子結點的個數 |
-------------------------*/
int TreeLeafCnt(CSTree T) {
// 樹的葉子結點-->沒有孩子
int ret=0;
CSNode *p;
if (!T) return 0;
else if (!T->firstchild) return 1;
else {
for (p=T->firstchild; p; p=p->nextsibling) ret += TreeLeafCnt(p);
return ret;
}
}
/*-------------------------
|6.61 求樹的度 |
-------------------------*/
int TreeDegree(CSTree T) {
// 最大的孩子數
int max=-1;
int cnt=0;
CSNode *child;
if (!T) return -1; //空樹
else if (!T->firstchild) return 0; //只有一個根結點,度為0
else {
for (cnt=0,child=T->firstchild; child; child=child->nextsibling) cnt++; //求自己的度
max = cnt; //當前的最大值
for (child=T->firstchild; child; child=child->nextsibling) {
cnt = TreeDegree(child);
if (cnt>max) max=cnt;
}
return max;
}
}
/*-------------------------
|6.62 求樹的深度 |
-------------------------*/
int TreeDepth(CSTree T) {
int h1,h2;
if (!T) return 0;
else {
h1 = TreeDepth(T->firstchild)+1; //T孩子的深度+1
h2 = TreeDepth(T->nextsibling); //T兄弟的深度
return h1>h2 ? h1 : h2;
}
}
/*---------------------------------
|6.66 雙親表示法-->孩子兄弟表示式|
---------------------------------*/
#define MAX_TREE_SIZE 50
typedef struct PTNode{
TElemType data;
int parent; //雙親的位置域
}PTNode;
typedef struct{
PTNode nodes[MAX_TREE_SIZE];
int r,n;
}PTree;
CSTree CreateCSTreeByPTree(PTree T) {
CSNode *tmp[MAX_TREE_SIZE]; //建立一個輔助的陣列,仿照PTree結點的位置存放
CSNode *p, *q;
int i,parent;
if (T.n<=0) return NULL;
for (i=0; i<T.n; i++) { //雙親表按層序儲存
//建立新結點
p = (CSNode *)malloc(sizeof(CSNode)); if(!p) exit(OVERFLOW);
//賦值
p->data = T.nodes[i].data;p->firstchild=p->nextsibling=NULL;
//連線
parent=T.nodes[i].parent; //父親
if (parent!=-1) { //不是根結點
if (tmp[parent]->firstchild==NULL) tmp[parent]->firstchild=p; //第一個孩子
else { //不是第一個孩子
for (q=tmp[parent]->firstchild; q->nextsibling; q=q->nextsibling) ; //找到最後一個孩子
q->nextsibling = p; //連線
}
}
tmp[i]=p;
}
return tmp[0];
}
int main() {
PTree PT;
CSTree CST;
PT.n=10;PT.r=0;
PT.nodes[0].data='R';PT.nodes[0].parent=-1;
PT.nodes[1].data='A';PT.nodes[1].parent=0;
PT.nodes[2].data='B';PT.nodes[2].parent=0;
PT.nodes[3].data='C';PT.nodes[3].parent=0;
PT.nodes[4].data='D';PT.nodes[4].parent=1;
PT.nodes[5].data='E';PT.nodes[5].parent=1;
PT.nodes[6].data='F';PT.nodes[6].parent=3;
PT.nodes[7].data='G';PT.nodes[7].parent=6;
PT.nodes[8].data='H';PT.nodes[8].parent=6;
PT.nodes[9].data='I';PT.nodes[9].parent=6;
CST = CreateCSTreeByPTree(PT);
TreePrintEdge(CST);
return 0;
}