鉴于以下结构:
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_Search
和bst_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
返回指向正确位置的指针到插入。在第一个指向posins
到T->root
内存地址中调用(1)。 (据我可以调试,这工作正常)。
然后posins
地址返回到来电者函数bst_Insert
,因为bst_Search
找到了一个地方,让它在(2)返回NULL
。它正确地进入if
语句集q
。然后在(3),我希望posins
指向的位置(在这种情况下,T-> root指向的地址)现在应该被重定向到新树节点q
。相当于T->root = q
,但通过引用使用此调用。
答案 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的方式是错误的。让我们说树是这样的:
现在让我们说你搜索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
}