我正在为我的任务实现一个avl树。
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
struct TreeNode {
char *item;
struct TreeNode *left;
struct TreeNode *right;
signed char balance;
};
typedef struct TreeNode Node;
void _print_avl (Node *, int , const char *);
Node * get_new_node (char *);
int avl_insert(Node *, char *);
void print_avl (Node *);
void avl_swr(Node*);
int main (int argc, char *argv[])
{
Node *root = get_new_node("thura");
avl_insert(root, "thur2");
print_avl(root);
avl_insert(root, "thur1");
return 0;
}
int avl_insert(Node *root, char *item)
{
assert(root);
if( strcmp(item, root->item) < 0) {
if(!root->left) {
root->left = get_new_node(item);
if(--(root->balance)) return 1;
return 0;
} else {
if(avl_insert(root->left, item)) {
if( root->balance-- < 0) {
avl_swr(root); //Rotate the node right.
print_avl(root); //Here, the tree is corrupted.
return 0;
}
return 1;
}
}
} else {
if(!root->right) {
root->right = get_new_node(item);
if(++(root->balance)) return 1;
return 0;
}
else {
if(avl_insert(root->right, item)) {
root->balance++;
return 1;
}
}
}
return 0;
}
void avl_swr(Node* root)
{
Node *node = root;
root = node->left;
node->left = NULL;
node->balance = 0;
root->right = node;
root->balance++;
print_avl(root); // It is working fine here.
}
Node * get_new_node (char *item) {
Node * node = (Node *)malloc(sizeof(Node));
node->item = item;
node->left = NULL;
node->right = NULL;
node->balance = 0;
return node;
}
void print_avl (Node *node)
{
_print_avl(node, 0, "\t\t");
}
void _print_avl (Node *node, int depth, const char *delim)
{
if(!node)
return;
int i = 0;
while(i++ < depth) printf("%s", delim);
printf("--> %s:%d\n", node->item, node->balance);
depth++;
if(node->left)
_print_avl (node->left, depth, delim);
if(node->right)
_print_avl (node->right, depth, delim);
}
问题是当我旋转树时,使用avl_swr(),它根据print_avl()成功旋转,但是当函数返回到调用者时,树被破坏了。有什么想法吗?
答案 0 :(得分:5)
avl_swr()的问题与函数签名有关:void avl_swr(Node* root)
和作业:root = node->left;
函数返回时,根指针未更新(仅更新函数中的本地副本)。签名应为:void avl_swr(Node** root)
以获得所需的结果。
答案 1 :(得分:1)
更新指针的副本。您需要传入一个指向旋转函数中指针的指针。
答案 2 :(得分:1)
这是因为avl_insert中的根变量在avl_swr中没有变化。将它传递给avl_swr时,会生成指针的副本。你改变了这个指针。
将呼叫更改为root = avl_swr(...)
并让avl_swr返回根目录。
答案 3 :(得分:0)
不是100%肯定,但我确实看到了一个问题。在avl_swr()中,您将root更改为left子树。因此,当您在avl_swr()中打印时,您将拥有root =“thur2”。但是当你返回到avl_insert()时,root仍然没有改变,仍然指向“thura”,现在没有孩子。因此,当您打印该根时,它不显示任何子项。也许这就是你腐败的意思? 解决方案显然是改变avl_insert()中的“root”。您可以通过让avl_swr返回新的根值,或者通过将参数从“Node * root”更改为“Node ** root”来执行此操作,以便将avl_swr中的更改“传回”到avl_insert