[樹] 6.68 樹的層次序列+每個結點的度 建立 孩子兄弟連結串列CSTree
阿新 • • 發佈:2018-12-13
題目來源:嚴蔚敏《資料結構》C語言版本習題冊 6.68
【題目】6.68 已知一棵樹的由根至葉子結點按層次輸入的結點序列及每個結點的度(每層中自左至右輸入),試寫出構造此樹的孩子-兄弟連結串列的演算法
【思路】
- 先建立結點
- 為每個結點找爸爸
【獲得】
- 類似於層次序列、按順序儲存的結構 轉換成其他儲存方式–>都可以建立一個輔助的陣列
【答案】
/*-----------------------------------------
|6.68 層次序列+每個結點的度-->構造CSTree |
-----------------------------------------*/
CSTree CreateCSTreeByLevelDegree(char *levelstr, int *num) {
int cnt,i,parent;
CSNode *p;
CSNode *tmp[maxSize];
//先建立結點
for (i=0; i < strlen(levelstr); ++i) {
p = (CSNode *)malloc(sizeof(CSNode)); if (!p) exit(OVERFLOW);
p->data = levelstr[i];p->firstchild=p->nextsibling=NULL;
tmp[ i]=p;
}
//連線
parent=0; //孩子的爸爸
cnt=0; //計數器:表示已經找了幾個孩子
i=1; //遍歷結點,為他們找爸爸
while (i<strlen(levelstr)) {
if (num[parent]==0 || cnt==num[parent]) { //這個父親沒有孩子 || parent的孩子已經找完了
cnt=0; //計數器歸0
parent++; //位移一位
continue;
}
//這個父親有孩子(i是parent的孩子)
cnt++;
if (cnt==1) { //i是parent的第一個孩子
tmp[parent]-> firstchild = tmp[i];
} else { //不是第一個孩子
tmp[i-1]->nextsibling = tmp[i]; //它是前面的兄弟
}
i++;
}
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.68 層次序列+每個結點的度-->構造CSTree |
-----------------------------------------*/
CSTree CreateCSTreeByLevelDegree(char *levelstr, int *num) {
int cnt,i,parent;
CSNode *p;
CSNode *tmp[maxSize];
//先建立結點
for (i=0; i < strlen(levelstr); ++i) {
p = (CSNode *)malloc(sizeof(CSNode)); if (!p) exit(OVERFLOW);
p->data = levelstr[i];p->firstchild=p->nextsibling=NULL;
tmp[i]=p;
}
//連線
parent=0; //孩子的爸爸
cnt=0; //計數器:表示已經找了幾個孩子
i=1; //遍歷結點,為他們找爸爸
while (i<strlen(levelstr)) {
if (num[parent]==0 || cnt==num[parent]) { //這個父親沒有孩子 || parent的孩子已經找完了
cnt=0; //計數器歸0
parent++; //位移一位
continue;
}
//這個父親有孩子(i是parent的孩子)
cnt++;
if (cnt==1) { //i是parent的第一個孩子
tmp[parent]->firstchild = tmp[i];
} else { //不是第一個孩子
tmp[i-1]->nextsibling = tmp[i]; //它是前面的兄弟
}
i++;
}
return tmp[0];
}
int main() {
/*6.58測試資料
RABCDEFGHI
3 2 0 1 0 0 3 0 0 0
*/
CSTree CST;
char levelstr[50]; //層次遍歷的序列
int num[50]; //每個結點的度
int i,cnt;
scanf("%s", levelstr);
for (i=0; i<strlen(levelstr); i++) scanf("%d", &num[i]);
CST = CreateCSTreeByLevelDegree(levelstr, num);
TreePrintEdge(CST); // 6.59
cnt = TreeLeafCnt(CST); //6.60 葉子結點個數
printf("TreeLeafCnt:%d\n", cnt);
cnt = TreeDegree(CST); //6.61 樹的度
printf("TreeDegree:%d\n", cnt);
cnt = TreeDepth(CST); //6.62 樹的深度
printf("TreeDepth:%d\n", cnt);
return 0;
}