在二进制搜索树中通过引用重定向指针

时间:2017-07-01 00:02:30

标签: c pointers binary-search-tree pass-by-reference

鉴于以下结构:

struct TElem {
  int val;
};

typedef int TKey;

struct Node {
  TKey key;
  struct TElem *elem;
  struct Node *left;
  struct Node *right;
};


struct bst {
  struct Node *root;
};

这两个函数bst_Searchbst_Insert

struct TElem* bst_Search(struct bst *T, TKey c, struct Node **posins)
{
  struct Node *q = T->root;
  posins = &(T->root);                      // (1)

  while (q)
    if (q->key == c)
      return q->elem;
    else if ( c < q->key) {
      q = q->left;
      posins = &(q->left);
    } else {
      q = q->right;
      posins = &(q->right);
    }

  return NULL;
}

void bst_Insert(struct bst *T, TKey c, struct TElem *x)
{
  struct Node **posins;
  struct TElem *v;

  posins = malloc(sizeof *posins);
  v = bst_Search(T, c, posins);             // (2)

  if (!v) {
    struct Node *q = malloc(sizeof *q);
    q->key   = c;
    q->elem  = x;
    q->left  = NULL;
    q->right = NULL;
    *posins  = q;                           // (3)
  } else {
    printf("Key exists %d\n", c);
  }

  free(posins);
}

main()是“主要”

  struct bst *T = malloc(sizeof *T);
  T->root = NULL;

  struct TElem *x = elem_New(10);
  bst_Insert(T, c, x);

我正在尝试插入一个新元素(elem_New工作正常)到BST中,使用辅助函数bst_Search返回指向正确位置的指针到插入。在第一个指向posinsT->root内存地址中调用(1)。 (据我可以调试,这工作正常)。

然后posins地址返回到来电者函数bst_Insert,因为bst_Search找到了一个地方,让它在(2)返回NULL。它正确地进入if语句集q。然后在(3),我希望posins指向的位置(在这种情况下,T-> root指向的地址)现在应该被重定向到新树节点q。相当于T->root = q,但通过引用使用此调用。

3 个答案:

答案 0 :(得分:0)

因为你的&#34; posins&#34;退出你的&#34; bst_Search&#34;

时不会改变
void test(int *p){
// g_c is a gobal int 
p = &g_c;
 printf("%X ",p);}

在调用test(int * p)时做你的想法 p的值会改变为指向g_c吗?不,因为p只是一个参数,当它退出proc

时它不会改变它的值
my english is poor  so i just hope the e.g. code will help your understand~ :)

答案 1 :(得分:0)

你更新q的方式是错误的。让我们说树是这样的:

BST example structure

现在让我们说你搜索10,bst_search(10)(为了简单和理解,我删除了你的参数)

然后,这就是你做的:

posins = 5 // I am writing numeric values instead of addresses for understanding

// Now
10 > 5
p = p->right // => p = 12
posins = p->left // => posins = 9, cause p is pointing to 12

Again, 10 < 12
So, p = p->left; // => p = 9
posins = p->left; // posins = NULL

这是出错的地方,你应该指向9,但你指的是9的左边,这是你应该编码的:

struct TElem* bst_Search(struct bst *T, TKey c, struct Node **posins)
{
  struct Node *q = T->root;
  posins = &(T->root);                      // (1)

  while (q)
    if (q->key == c)
      return q->elem;
    else if ( c < q->key) {
      q = q->left;
      posins = &q;
    } else {
      q = q->right;
      posins = q;
    }

  return NULL;
}

如有任何疑问,请发表评论。

答案 2 :(得分:0)

主要问题是调用参数无法通过posins = &(T->root);等操作进行更新。

  

93)函数可能会改变其参数的值,但这些值   更改不会影响参数的值。另一方面,   可以将指针传递给对象,该函数可以   更改指向的对象的值。

因此,如果您想将调用变量更改为P的值,则必须为*P
struct Node **posins应为struct Node ***posins

整体代码如下所示。

#include <stdio.h>
#include <stdlib.h>

struct TElem {
    int val;
};

typedef int TKey;

struct Node {
    TKey key;
    struct TElem *elem;
    struct Node *left;
    struct Node *right;
};

struct bst {
    struct Node *root;
};

int TKeyCmp(TKey a, TKey b){
/* return value :
** a = b : 0
** a > b : positive value
** a < b : negative value
*/
    return a < b ? -1 : a > b;
}
struct TElem *elem_New(int value){
    struct TElem *ep = malloc(sizeof(*ep));//check omitted
    ep->val = value;
    return ep;
}
void elem_free(struct TElem *ep){
    free(ep);
}
void print(struct Node *np){
    if(np){
        print(np->left);
        printf("(%d, %d)", np->key, np->elem->val);
        print(np->right);
    }
}

struct TElem *bst_Search(struct bst *T, TKey c, struct Node ***posins){
    *posins = &T->root;

    while (**posins){
        int cmp = TKeyCmp(c, (**posins)->key);
        if(cmp == 0)
            return (**posins)->elem;
        else if ( cmp < 0)
            *posins = &(**posins)->left;
        else
            *posins = &(**posins)->right;
    }

    return NULL;
}

void bst_Insert(struct bst *T, TKey c, struct TElem *x){
    struct Node **posins;

    if (!bst_Search(T, c, &posins)) {
        struct Node *q = malloc(sizeof *q);
        q->key   = c;
        q->elem  = x;
        q->right = q->left  = NULL;
        *posins  = q;
    } else {
        elem_free(x);//avoid memory leak
        printf("Key exists %d\n", c);
    }
}

int main(void){
    struct bst *T = malloc(sizeof(*T));

    T->root = NULL;

    bst_Insert(T, 5, elem_New(10));
    bst_Insert(T, 1, elem_New(21));
    bst_Insert(T, 9, elem_New(42));
    bst_Insert(T, 1, elem_New(99));//Key exists 1
    print(T->root);//(1, 21)(5, 10)(9, 42)
    //release bst
}