没有节点结构的二进制搜索树递归

时间:2017-10-07 13:39:20

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

我必须为大学完成一个项目,但我无法弄清楚它是如何完成的。

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

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

非常感谢!!!

这是我的Header文件(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);
    }
  }
}

2 个答案:

答案 0 :(得分:0)

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

如果您希望函数f能够更改变量x,最简单的解决方案是让f获取指针并将其称为f(&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的指针,该指针包含指向自身的指针。类似地,树插入函数bst_insert包含对节点插入函数bst_node_insert的调用,该函数包含对自身的调用。

答案 1 :(得分:0)

由于您说您无法更改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) {