【问题标题】:Binary Search Tree Recursion without a node struct没有节点结构的二叉搜索树递归
【发布时间】:2018-03-19 03:37:11
【问题描述】:

我必须为大学完成一个项目,但我不知道如何完成。

问题是我想用以下给定的函数构建一个二叉搜索树应用程序。我需要构建某种递归,但我的问题是 bst_insert(tree *bst, int key) 函数将 tree 作为输入而不是节点。所以我写在下面的想法 (bst_insert(bst->root_node->left, key);) 不起作用。

有人知道我可以做些什么来获得有效的解决方案吗?

非常感谢!!!

这是我的头文件(tree.h)的一部分

    typedef struct node {
      int key;
      struct node *left;
      struct node *right;
    } node;

    typedef struct tree {
      node *root_node;
      int (*compare_keys)(int x, int y);
    } tree;

    void bst_insert(tree *bst, int key);

这是tree.c文件的一部分

void init(tree *bst) {
  bst->root_node = 0;
  bst->compare_keys = 0;
}

void bst_insert(tree *bst, int key) {    
  if (bst->root_node == NULL) {
    bst->root_node = (node*)malloc(sizeof(node));
    bst->root_node->key = key;
    bst->root_node->left = NULL;
    bst->root_node->right = NULL;
  }
  else {
    if (key < bst->root_node->key) {
      bst_insert(bst->root_node->left, key);
    }
    if (key > bst->root_node->key) {
      bst_insert(bst->root_node->right, key);
    }
  }
}

【问题讨论】:

  • 您显然与指定该项目的人存在分歧。你或许应该和他们谈谈。
  • “函数将树作为输入而不是节点”——这就是惯例。
  • 为什么不改bst_insert取一个节点?
  • @4386427 我不允许更改这行代码“void bst_insert(tree *bst, int key)”
  • @TheoG - 但是您可以更改函数内的所有内容,对吧?

标签: c recursion search malloc binary-search-tree


【解决方案1】:

即使你被允许,直接传递bst-&gt;root_node-&gt;left 也是行不通的。函数参数按值传递,递归调用可能需要更改bst-&gt;root_node-&gt;left的值(如果是NULL)。

如果您希望函数f 能够更改变量x,最简单的解决方案是让f 获取一个指针并将其称为f(&amp;x)(传递x 的地址) .我们可以将其应用于您的递归插入函数:

void bst_insert(node **ppnode, int key) {    
    if (*ppnode == NULL) {
        *ppnode = malloc(sizeof **ppnode);
        (*ppnode)->key = key;
        (*ppnode)->left = NULL;
        (*ppnode)->right = NULL;
    }
    else if (key < (*ppnode)->key) {
        bst_insert(&(*ppnode)->left, key);
    }
    else if (key > (*ppnode)->key) {
        bst_insert(&(*ppnode)->right, key);
    }
}

这段代码可以工作,但正如你所说,它的类型错误。

不过,这不是什么大问题:我们可以简单地重命名这个函数并提供一个具有正确名称和类型的包装器。

static void bst_node_insert(node **ppnode, int key) {    
    if (*ppnode == NULL) {
        *ppnode = malloc(sizeof **ppnode);
        (*ppnode)->key = key;
        (*ppnode)->left = NULL;
        (*ppnode)->right = NULL;
    }
    else if (key < (*ppnode)->key) {
        bst_node_insert(&(*ppnode)->left, key);
    }
    else if (key > (*ppnode)->key) {
        bst_node_insert(&(*ppnode)->right, key);
    }
}

void bst_insert(tree *bst, int key) {
    bst_node_insert(&bst->root_node, key);
}

这段代码的结构反映了您的数据类型的结构:您有一个tree,其中包含一个指向node 的指针,而node 又包含指向自身的指针。同样,树插入函数bst_insert 包含对节点插入函数bst_node_insert 的调用,其中包含对自身的调用。

【讨论】:

    【解决方案2】:

    既然你说不能改变bst_insert的定义,我想解决的办法是在调用函数之前新建一个临时树。感觉有点奇怪,但类似下面的代码应该可以工作:

    tree tempTree;
    ...
    if (key < bst->root_node->key) {
      if (bst->root_node->left == NULL)
      {
          // Add a new node
          bst->root_node->left = malloc(sizeof(node));
          bst->root_node->left->key = key;
          bst->root_node->left->left = NULL;
          bst->root_node->left->right = NULL;
          return;
      }
    
      // Make a temporary tree for a recursive call
      tempTree.root_node = bst->root_node->left;
      tempTree.compare_keys = bst->compare_keys;
      bst_insert(&tempTree, key);
      return;
    }
    

    此外,我认为你在这行做错了什么:

    if (key < bst->root_node->key) {
    

    我很确定您应该使用compare_keys 函数。也许像:

    if (compare_keys(key, bst->root_node->key) < 0) {
    

    【讨论】:

    • 这实际上不起作用。试试看:你的代码实际上从来没有在用户调用它的树中插入任何东西。
    • @Melpomene - 对!那是错误的-谢谢。答案已更新。
    • 为了避免事后bst-&gt;root_node-&gt;left = tempTree.root_node;,有很多冗余代码。
    • @4386427 我认为您使用 compare_keys 的想法是正确的,但我不明白树结构中的“compare_keys”与我的 tree.c 文件中的另一个函数之间的关系我之前没有提到过: void init_with_comp_operator(tree *bst, int(*comp)(int x, int y)) { bst_init(bst); bst->compare_keys = comp; }
    猜你喜欢
    • 2012-01-26
    • 1970-01-01
    • 2013-10-24
    • 2014-01-02
    • 2014-12-21
    • 2014-05-10
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多