普通树转二叉树:左儿子右兄弟表示法

本文介绍了左儿子右兄弟表示法的基本概念及其在动态规划中的应用。通过将原树转换为二叉树形式,便于理解和实现动态规划算法。文章提供了一个简单的递归模板来完成树的转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  这两天在吃力地学DP的优化,被虐地不行不行的。搞个小插曲。

  左儿子右兄弟,顾名思义,是一棵转换后的树,它是一棵二叉树,一个节点的左子树表示的是原树中这个节点的子节点,一个节点的右子树表示的是这个节点在原树中的兄弟(父节点相同的点)。

  这么表示有什么好处呢?在DP时二叉树的优势相比于普通树是很明显的,或许有时它不能优化时间,但至少可以优化“思路”。

  最近并没有碰到要转二叉树的题,也没什么题解可写,等碰到了再补充吧,现在先把模板贴在这里喽。直接递归建树即可,原树是用vector保存的。

void dfs(int u){
	if(!u || !G[u].size()) return;
	lc[u] = G[u][0];
	dfs(lc[u]);
	int v = lc[u];
	for(int i = 1; i < G[u].size(); i++){
		rc[v] = G[u][i];
		dfs(rc[v]);
		v = rc[v];
	}
}

### 树结构换为二叉树的算法实现 树结构可以通过“儿子兄弟”的方式换为二叉树。这种换的核心思想是将树中的每个节点的第一个子节点作为其子节点,而将其后续兄弟节点依次连接为其子节点。 以下是基于上述描述的具体实现: #### 孩子兄弟表示法 在孩子兄弟表示法中,每个节点有两个指针字段:`first_child` 和 `next_sibling`。前者指向该节点的第一个子节点,后者指向同一父节点下的下一个兄弟节点[^1]。 #### 换逻辑 为了将普通的多叉树换为二叉树,遵循以下原则: - 将原树中某个节点的第一个子节点设置为新二叉树中该节点的子节点。 - 将原树中某节点的所有兄弟节点链接起来,形成一条链表,并将这条链表映射到新二叉树中该节点的子节点上。 #### C语言实现代码 下面提供了一个完整的C语言程序来演示这一过程: ```c #include <stdio.h> #include <stdlib.h> // 定义树节点结构体 typedef struct TreeNode { char data; struct TreeNode *first_child, *next_sibling; } TreeNode; // 定义二叉树节点结构体 typedef struct BinaryTreeNode { char data; struct BinaryTreeNode *left, *right; } BinaryTreeNode; // 创建一个新的树节点 TreeNode* createTreeNode(char value) { TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode)); newNode->data = value; newNode->first_child = NULL; newNode->next_sibling = NULL; return newNode; } // 创建一个新的二叉树节点 BinaryTreeNode* createBinaryTreeNode(char value) { BinaryTreeNode* newNode = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode)); newNode->data = value; newNode->left = newNode->right = NULL; return newNode; } // 将普通树换为二叉树 BinaryTreeNode* treeToBinaryTree(TreeNode* root) { if (!root) return NULL; // 创建新的二叉树根节点 BinaryTreeNode* binaryRoot = createBinaryTreeNode(root->data); // 如果有第一个子节点,则递归处理并挂载到子节点 if (root->first_child) { binaryRoot->left = treeToBinaryTree(root->first_child); } // 处理兄弟节点 BinaryTreeNode* current = binaryRoot; TreeNode* sibling = root->next_sibling; while (sibling) { current->right = createBinaryTreeNode(sibling->data); // 连接兄弟 current = current->right; // 移动到侧 if (sibling->first_child) { // 若存在子节点继续递归 current->left = treeToBinaryTree(sibling->first_child); } sibling = sibling->next_sibling; // 遍历下一兄弟节点 } return binaryRoot; } // 层序遍历打印二叉树(用于验证) void levelOrderTraversal(BinaryTreeNode* root) { if (!root) return; printf("Level Order Traversal of the converted binary tree:\n"); BinaryTreeNode* queue[100]; int front = 0, rear = 0; queue[rear++] = root; while (front != rear) { BinaryTreeNode* node = queue[front++]; printf("%c ", node->data); if (node->left) queue[rear++] = node->left; if (node->right) queue[rear++] = node->right; } printf("\n"); } int main() { // 构建一个多叉树 A -> B,C,D,E,F,G,H,I,J,K TreeNode* a = createTreeNode('A'); TreeNode* b = createTreeNode('B'); a->first_child = b; TreeNode* c = createTreeNode('C'); b->next_sibling = c; TreeNode* d = createTreeNode('D'); c->next_sibling = d; TreeNode* e = createTreeNode('E'); d->next_sibling = e; TreeNode* f = createTreeNode('F'); e->next_sibling = f; TreeNode* g = createTreeNode('G'); b->first_child = g; TreeNode* h = createTreeNode('H'); g->next_sibling = h; TreeNode* i = createTreeNode('I'); h->next_sibling = i; TreeNode* j = createTreeNode('J'); c->first_child = j; TreeNode* k = createTreeNode('K'); j->next_sibling = k; // 执行树二叉树的操作 BinaryTreeNode* binaryRoot = treeToBinaryTree(a); // 输出层序遍历结果 levelOrderTraversal(binaryRoot); return 0; } ``` 以上代码实现了从普通树二叉树换,并通过层序遍历来展示最终的结果。对于输入序列 `ABCDEFGHIIJK` 的树,经过换后的输出应为 `ABFCGDHIEJK`[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值