我正在实现使用Array实现表示的二进制搜索树。到目前为止,这是我的代码:请注意我已完成树的结构,并将其保存为链接列表。我想将此链接列表转换为数组。
我对如何解决这个问题的想法如下。创建一个return_array函数。将数组的大小设置为最大节点数(2 ^(n-1)+1)并通过链表。根节点将是阵列上的@ position 0,然后他的L-child =(2 * [index_of_parent] +1)并且R-child =(2 * [index_of_parent] +2)。我环顾四周寻找一些东西可以让我了解如何跟踪每个节点以及如何通过每个节点。
我是否过度思考这个问题? 可以有一个递归吗?
另外,我正在考虑创建一个可视树而不是一个数组但不知道如何正确地将它分开。如果有人知道如何做到这一点,那么更好地理解它将是非常棒的。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
using namespace std;
struct node {
int data;
struct node* left;
struct node* right;
};
void inorder(struct node* node){
if(node){
inorder(node->left);
cout << node->data << " ";
inorder(node->right);
}
}
void insert(struct node** node, int key){
if(*node == NULL){
(*node) = (struct node*)malloc(sizeof(struct node));
(*node)->data = key;
(*node)->left = NULL;
(*node)->right = NULL;
printf("inserted node with data %d\n", (*node)->data);
}
else if ((*node)->data > key){
insert((&(*node)->left),key);
}
else
insert((&(*node)->right),key);
}
int max_tree(struct node* node){
int left,right;
if(node == NULL)
return 0;
else
{
left=max_tree(node->left);
right=max_tree(node->right);
if(left>right)
return left+1;
else
return right+1;
}
}
//This is where i dont know how to keep the parent/children the array.
void return_array(struct node* node, int height){
int max;
height = height - 1;
max = pow(2, height) - 1;
int arr [height];
}
int main(){
int h;
struct node* root = NULL;
insert(&root, 10);
insert(&root, 20);
insert(&root, 5);
insert(&root, 2);
inorder(root);
cout << endl;
cout << "Height is: ";
cout << max_tree(root);
h = max_tree(root)
return_array(root, h)
}
答案 0 :(得分:5)
如果要将树节点存储在数组中,最好从数组的1个位置开始!所以父节点与子节点之间的关系应该很简单:
parent = n;
left = 2n;
right = 2n + 1;
你应该BFS树,并将节点存储在数组中(如果节点为null,你也应该使用标志ex 0存储在数组中),你应该得到树的数组!
答案 1 :(得分:4)
考虑到您希望使用
有效地存储二进制搜索树l = 2i + 1
r = 2i + 2
每次树遇到树末端没有发生的叶节点(广度优先)时,会浪费空间。请考虑以下简单示例:
2
/ \
1 4
/ \
3 5
这(当将广度优先转换为数组时)导致
[ 2, 1, 4, -, -, 3, 5 ]
并浪费阵列中的两个插槽。
现在,如果您想将相同的树存储在数组中而不浪费空间,只需将其转换为数组 depth-first :
[ 2 1 4 3 5 ]
要从中恢复原始树,请对每个节点执行以下步骤:
对于每个节点(包括root),请选择
a)将左子项作为当前键后数组中的下一个较小键
b)右子项作为数组中的下一个更大的键,不大于最后一次分支时遇到的最小父键,并且小于直接父键的时候你目前在它的左分支
显然找到正确的b)稍微更复杂,但不是太多。请参阅我的代码示例here。
如果我没有弄错的话,在任何一种情况下,转换到数组和从数组转换都需要O(n)。由于没有浪费空间,空间复杂性也是O(n)。
这是有效的,因为二进制搜索树比普通二叉树具有更多结构;在这里,我只是使用左子项的二叉搜索树属性较小,而右子项比当前节点的键大。
修改强>
在对该主题做了一些进一步的研究之后,我发现在预订遍历顺序中重建树更加简单。这样做的递归函数分别实现了here和here。
它基本上由以下步骤组成:
当前的最小值和最大值由树内的位置定义(左子:小于父,右子:大于父)。
有关详细信息,请参阅我的源代码链接。
答案 2 :(得分:0)
为此,您必须按照以下步骤操作。
在我们到达列表末尾之前,请执行以下操作。
一个。将一个节点从队列中出列。这是当前的父母。
湾遍历列表中的两个节点,将它们添加为当前父节点的子节点。
℃。将两个节点排入队列。
时间复杂度:上述解决方案的时间复杂度为O(n),其中n为节点数。