在C中实现Tree的指针问题

时间:2009-10-13 13:01:32

标签: c algorithm tree binary-tree

我正在为我的任务实现一个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()成功旋转,但是当函数返回到调用者时,树被破坏了。有什么想法吗?

4 个答案:

答案 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