Icoding题解
题干
树转二叉树
使用队列,编写transfrom函数,将普通树转换成对应的二叉树。二叉树的相关定义如下:
1 2 3 4 5 6 7
| typedef int DataType;
typedef struct Node{ DataType data; struct Node* left; struct Node* right; }BiTNode, *BiTree;
|
普通树节点的定义如下:
1 2 3 4 5 6 7
| #define MAX_CHILDREN_NUM 5 struct _CSNode { DataType data; struct _CSNode *children[MAX_CHILDREN_NUM]; }; typedef struct _CSNode CSNode;
|
其中,子树的根节点的指针存放在children数组的前k个元素中,即如果children[i]的值为NULL,而children[i-1]不为NULL,则表明该结点只有i棵子树,子树根结点分别保存在children[0]至children[i-1]中。
队列相关定义及操作如下:
1 2 3 4 5 6 7 8 9 10 11 12
| struct __Queue { int i, j; void **array; }; typedef struct __Queue Queue;
Queue* create_queue(); bool is_empty_queue(Queue *tree); void* del_queue(Queue *tree); void add_queue(Queue *tree, void *node); void free_queue(Queue *tree);
|
transform函数定义如下:
1
| BiTNode* transform(CSNode *root);
|
其中 root 为普通树的根结点,函数返回该树对应二叉树的根结点。
分析
- 简要分析题干:
将一个普通树转化成二叉树。实际上做起来并不是那么简单,需要队列的辅助。有些类似于层序遍历。
- 应当注意的问题:
- 队列的基本操作
- 二叉树的操作,普通树的操作
- 解题思路:
- 这里选择开两个队列,队列a用于存储普通树的结点,队列b用于存储二叉树的结点。
- 先把根复制到二叉树中,然后分别入队两个根
- 只要a队非空(原普通树的结点没有用完)就继续以下操作的循环
- a、b队列均出队一个结点
- 遍历a队的出队结点的孩子数组
- 第一个孩子作为b队列出队结点的左孩子,prev指针记录这个左孩子的位置。
- 普通树的第一个子节点作为二叉树中结点的左子节点,普通树中剩余的子节点按顺序作为二叉树中左子节点的右子节点链(当然可以选择其他的转换方法,笔者采用的方法会导致根节点没有右子树)
注释代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| BiTNode* transform(CSNode *root) { Queue* CSNodeQueue = create_queue(); Queue* BiTNodeQueue = create_queue();
if (!root || !CSNodeQueue || !BiTNodeQueue) { return NULL; }
CSNode* CurrCSNode = NULL; CSNode* RootNode = NULL; BiTNode* CurrBiNode = (BiTree)malloc(sizeof(BiTNode)); if (!CurrBiNode) return NULL; CurrBiNode->data = root->data; CurrBiNode->left = CurrBiNode->right = NULL; RootNode = CurrBiNode; add_queue(CSNodeQueue, root); add_queue(BiTNodeQueue, CurrBiNode);
while (!is_empty_queue(CSNodeQueue)) { CurrCSNode = del_queue(CSNodeQueue); CurrBiNode = del_queue(BiTNodeQueue); BiTNode* TempNode = NULL; for (int i = 0; i < MAX_CHILDREN_NUM; i++) {
if (!CurrCSNode->children[i]) { break; } else { BiTree ChildBiNode = (BiTree)malloc(sizeof(BiTNode)); ChildBiNode->data = CurrCSNode->children[i]; ChildBiNode->left = ChildBiNode->right = NULL;
if (i == 0) CurrBiNode->left = ChildBiNode; else TempNode->right = ChildBiNode; TempNode = ChildBiNode; add_queue(BiTNodeQueue, TempNode); add_queue(CSNodeQueue, CurrCSNode->children[i]); }
} }
free(BiTNodeQueue); free(CSNodeQueue); return CurrBiNode; }
|
完整代码
有兴趣的可以自行探索,如何将普通二叉树转换为满二叉树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| BiTNode* transform(CSNode *root){ Queue* aqueue = create_queue(); Queue* bqueue = create_queue(); if(root == NULL) return NULL; BiTree BiRoot = (BiTree)malloc(sizeof(BiTNode)); BiRoot->data = root->data; BiRoot->left = NULL; BiRoot->right = NULL; add_queue(bqueue, BiRoot); add_queue(aqueue, root); while(!is_empty_queue(aqueue)) { BiTree curr_binode = del_queue(bqueue); CSNode *curr_node = del_queue(aqueue); BiTree prev = NULL; for(int i = 0; i < MAX_CHILDREN_NUM; i++) { if(curr_node->children[i] == NULL) break; else { BiTree child_binode = (BiTree)malloc(sizeof(BiTNode)); child_binode->data = curr_node->children[i]->data; child_binode->left = NULL; child_binode->right = NULL; if(i == 0) curr_binode->left = child_binode; else prev->right = child_binode; prev = child_binode; add_queue(bqueue, prev); add_queue(aqueue, curr_node->children[i]); } } } free(aqueue); free(bqueue); return BiRoot; }
|