左子右兄弟表示法


題目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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM