我有一个编写自平衡二叉搜索树的任务。我决定使用AVL树,就像我们在课堂上讨论的那样。然后使用{3,5,61,9,32,7,1,45,26,6}的给定输入,我期望输出:
7
6-----|-----32
3----| 9----|----45
1---| |---26 |---61
也就是说,除非我严重误解并因此误算了AVL树在平衡时应该做什么。我得到的输出完全不同:
5
3-----|-----61
1----| 9----|
7---|---32
6--| 26--|--45
同样,除非我完全错了,否则那棵树不平衡。我用来设置树的函数定义如下:
node* insertKeyAVL(node* n, int e)
{
int cmpVal;
if (n == NULL){
n = create_node();
n->data = e;
} else if (e < n->data) {
if (n->left == NULL){
n->left = create_node();
n->left->data = e;
n->left->parent = n;
} else {
n->left = insertKeyAVL(n->left, e);
}
cmpVal = height(n->left) - height(n->right);
} else {
if (n->right == NULL){
n->right = create_node();
n->right->data = e;
n->right->parent = n;
} else {
n->right = insertKeyAVL(n->right, e);
}
cmpVal = height(n->right) - height(n->left);
}
if (cmpVal > 2){
if (n->left){
if (e < n->left->data)
n = rotate_left(n);
else
n = rotate_right_left(n);
} else if (n->right){
if (e > n->right->data)
n = rotate_right(n);
else
n = rotate_left_right(n);
}
}
n->height = max(height(n->left), height(n->right)) + 1;
return n;
}
我用来存储所有数据的结构定义如下:
typedef struct node
{
struct node *parent;
struct node* left;
struct node* right;
int data;
int height;
} node;
函数rotate_left_right和rotate_right_left是旋转第一个后修复方向然后第二个后修复方向的基本函数,并且它们都依赖于rotate_left和rotate_right各自的方向。向左旋转定义如下:
node* rotate_left(node* n)
{
node* tmp = n->left;
n->left = tmp->right;
tmp->right = n;
tmp->parent = n->parent;
n->parent = tmp;
n->height = max(height(n->left), height(n->right)) + 1;
tmp->height = max(height(tmp->left), n->height) + 1;
return tmp;
}
rotate_right类似,但调整为右旋。
我想知道这段代码在哪里混乱,以至于它不会产生所需的输出。
答案 0 :(得分:0)
当您在预期结果中添加26时,cmpval为5变为2,这是无效的,这就是为什么代码重新执行并将结果作为您的结果。
答案 1 :(得分:0)
我没有完整的答案,我不确定您的代码是否可以挽救,因为它错过了很多部分。令人惊讶的主要原因是缺少cmpVal的初始化,然后将其与2进行比较。但是如果n是NULL
其UB。
cmpVal是AVL的余额,但具有绝对值。不幸的是,在重新平衡时,您会检查是否存在左孩子或右孩子。但这没有告诉你什么。您需要知道天平的符号才能选择旋转方向。你可以同时拥有两个孩子,但仍然需要平衡。
您的插入看起来很奇怪,因为在检查节点不是NULL之后,您检查子节点是否相同。但是这里的递归会完全通过执行检查来保存两张支票。