題目RootedTree
《挑戰程序設計競賽2 算法和數據結構》中8.2章中有這樣一道題。
請編寫一個程序,輸出給定有根樹T中各節點u的信息,信息內容如下。
- u的節點編號
- u的節點種類(根、內部節點、葉)
- u的父節點編號
- u的字節點列表
- u的深度
輸入
第一行輸入結點的個數n,接下來n行按照下述格式輸入各個節點的信息,每個節點占一行。
id k c1 c2 ... ck
id為節點編號,k為該節點的度,也就是有幾個子節點,c1~ck就是它的子節點。
輸出
node id: parent = p, depth = d,type, [c1,...,ck]
示例
輸入
13
0 3 1 4 10
1 2 2 3
2 0
3 0
4 3 5 6 7
5 0
6 0
7 2 8 9
8 0
9 0
10 2 11 12
11 0
12 0
輸出
node 0: parent = -1, depth = 0, root,[1,4,10]
node 1: parent = 0, depth = 1, internal node,[2,3]
node 2: parent = 1, depth = 2, leaf,[]
node 3: parent = 1, depth = 2, leaf,[]
node 4: parent = 0, depth = 1, internal node,[5,6,7]
node 5: parent = 4, depth = 2, leaf,[]
node 6: parent = 4, depth = 2, leaf,[]
node 7: parent = 4, depth = 2, internal node,[8,9]
node 8: parent = 7, depth = 3, leaf,[]
node 9: parent = 7, depth = 3, leaf,[]
node 10: parent = 0, depth = 1, internal node,[11,12]
node 11: parent = 10, depth = 2, leaf,[]
node 12: parent = 10, depth = 2, leaf,[]
左子右兄弟表示法
書里給的算法是一個使用左子右兄弟表示法表示的樹。我沒看懂書中寫的代碼,我自己理解了一下,不知道說的對不對,反正結果是正確的。
和名字一樣,這棵樹的每個節點有兩個附屬節點,左面的附屬節點是當前節點的子節點,右面的附屬節點是當前節點的兄弟節點。左子右兄弟可以把任意形狀的有根樹轉換成二叉樹。
我們先手繪它給的數據。
首先知道0是根節點它的子節點有1,4和10。那根據左子右兄弟樹的定義,我們可以這樣畫。
因為1,4,10都是0的子節點,但是0只有左面一個指向子節點的附屬節點,不能同時指向三個,但是1,4是兄弟關系,我們可以把4接到1的右附屬兄弟節點上,然后10和4又是兄弟關系,我們又可以把10接到4的右節點上。
也就是說在一棵左子右兄弟表示的樹中,當前節點c的左節點是實際樹關系中該節點的直接子節點,並且左子節點的所有右側節點構成的鏈表(如圖中的1,4,10)在實際的樹關系中是平級的,都是c的直接子節點。
所以給定數據的左子右兄弟表示完整版本是這樣的
寫代碼
並不是按照題目中要求的輸入寫的,只是把示例數據給寫死了。寫的也是稍微有些亂。
#include "iostream"
#include "string"
#define N 13
#define RIGHT_CHILD 0
#define LEFT_CHILD 1
using namespace std;
struct Node {
int parent, left, right;
};
struct Node nodeList[N];
int treeData[][N] = {
{0,3,1,4,10},
{1,2,2,3},
{2,0},
{3,0},
{4,3,5,6,7},
{5,0},
{6,0},
{7,2,8,9},
{8,0},
{9,0},
{10,2,11,12},
{11,0},
{12,0}
};
void bindChild(int leftAndRight, int childIdx, int parentIdx) {
if (leftAndRight == LEFT_CHILD)
nodeList[parentIdx].left = childIdx;
else
nodeList[parentIdx].right = childIdx;
nodeList[childIdx].parent = parentIdx;
}
void createTree() {
nodeList[0].parent = -1;
nodeList[0].right = -1;
for (int i = 0; i < N; i++) {
int curNodeChildCount = treeData[i][1];
if (curNodeChildCount == 0) {
nodeList[i].left = -1;
continue;
}
int curChildIdx = treeData[i][2];
bindChild(LEFT_CHILD, curChildIdx, i);
for (int j = 3; j < curNodeChildCount + 2; j++) {
nodeList[curChildIdx].right = treeData[i][j];
nodeList[treeData[i][j]].parent = i;
curChildIdx = treeData[i][j];
}
nodeList[curChildIdx].right = -1;
}
}
int getDepth(int idx) {
struct Node curNode = nodeList[idx];
int depth = 0;
while (curNode.parent != -1) {
depth++;
curNode = nodeList[curNode.parent];
}
return depth;
}
string getType(int idx) {
struct Node node = nodeList[idx];
if (node.parent == -1)
return "root";
else if (node.left == -1)
return "leaf";
else
return "internal node";
}
void printChildsString(int idx){
cout << "[";
struct Node curNode = nodeList[idx];
if (curNode.left == -1) {
cout << "]";
return;
}
cout << curNode.left << ",";
curNode = nodeList[curNode.left];
while (curNode.right != -1) {
cout << curNode.right;
curNode = nodeList[curNode.right];
if (curNode.right != -1)cout << ",";
}
cout << "]";
}
void printNode(int idx){
cout << "node " << idx << ": parent = " << nodeList[idx].parent << ", depth = " << getDepth(idx)
<< ", " << getType(idx) << ",";
printChildsString(idx);
cout << endl;
}
int main() {
createTree();
for (int i = 0; i < N; i++)
printNode(i);
return 0;
}