Loading

左子右兄弟表示法

题目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;
}
posted @ 2020-10-11 14:55  yudoge  阅读(1045)  评论(0编辑  收藏  举报