我一直试图让这个BST在最近几天工作,而我却陷入了搜索功能。逻辑似乎是正确的(除非我缺少非常重要的细节)但代码仍然有问题。可能是因为我正在处理字符串?无论如何,这里有一些代码:
编辑:我已经找到了似乎出错的地方。事实证明我的根始终为空。我放置了一个 printf 来测试NULL-case是否为true,并且它总是打印为true。我在这个问题的底部添加了我的树初始化。
(更新的)搜索功能:
//Thank you, M Oehm
node* search(node * tree, char *key)
{
/* char *key is user input */
int cmp;
if(tree == NULL) {
return NULL;
}
cmp = strcmp(key, tree->key);
if(cmp < 0) return search(tree->left, key);
if(cmp > 0) return search(tree->right, key);
return tree;
}
主要功能的实施:
printf("Enter a string to search the tree with: ");
fgets(findNode, MAX_WORD, stdin);
findString = malloc(sizeof(char)*strlen(findNode)+1);
strcpy(findString,findNode);
printf("findString: %s\n", findString);
searched = search(&root, findString);
if(searched == NULL) {
printf("No_such_key\n");
free(findString);
}
else {
printNode(searched);
free(findString);
}
break;
树初始化(通过文件解析):
/* Loop through each line in the file*/
while(fgets(buffer, sizeof(buffer), file) != NULL) {
tempToken = strtok(buffer, " \n");
while(tempToken != NULL) {
/* Assign default values */
curr = (node *)malloc(sizeof(node));
curr->left = curr->right = NULL;
curr->key = malloc(sizeof(char)*strlen(tempToken)+1); /* +1 for '\0' */
strcpy(curr->key, tempToken);
curr->frequency = 1;
/* Insert node into tree */
insert(&root, curr);
/* Get next token */
tempToken = strtok(NULL, " \n");
}
}
/* Test insertion worked; close file */
print_inorder(root);
fclose(file);
插入功能:
void insert(node ** tree, node * item)
{
/* If no root, item is root */
if(!(*tree)) {
*tree = item;
return;
}
/* If item value is less than node in tree, assign to left */
if(strcmp(item->key,(*tree)->key) < 0) {
insert(&(*tree)->left, item);
}
else if(strcmp(item->key,(*tree)->key) > 0) {
insert(&(*tree)->right, item);
}
else if(strcmp(item->key,(*tree)->key) == 0) {
(*tree)->frequency++;
}
}
打印功能向我显示插入功能正常。
答案 0 :(得分:2)
您的代码中有两个错误:您不会检查传递指针的根节点是否为空,并且您不会从递归函数返回结果。
您的功能不会修改树,因此您不必将指针传递给节点。该方法对于修改树的函数很有用,例如用于插入或删除节点。您的函数应传递指向根节点的指针。这也向用户发出信号,表明该树不会被修改。
所以这是一个更正版本:
node* search(node *tree, const char *key)
{
int cmp;
if (tree == NULL) return NULL;
cmp = strcmp(key, tree->key);
if (cmp < 0) return search(tree->left, key);
if (cmp > 0) return search(tree->right, key);
return tree;
}
必须像这样调用该版本:
node *hit = search(tree, "bingo!");
请注意,此函数仅执行一次字符串比较,并将结果保存在临时变量中。您的代码最多会调用strcmp
三次。
你不必在这里使用递归。它甚至有点浪费,因为你必须在第一次通话时渗透答案。当每个步骤都必须维护一个可以表示为局部变量的状态时,递归很有用。在这里,您只需更改输入node
。
这是search
函数的非递归变体:
node* search(node *tree, const char *key)
{
while (tree) {
int cmp = strcmp(key, tree->key);
if (cmp == 0) return tree;
tree = (cmp < 0) ? tree->left : tree->right;
}
return NULL;
}
答案 1 :(得分:1)
search(&(*tree)->left, key);
应该是:
return search(&(*tree)->left, key);
相同的情况。
答案 2 :(得分:1)
尝试将您的功能更改为此类功能。
node* search(node * tree, char * key)
{
if(tree == NULL) {
return NULL;
}
if(strcmp(key,tree->key) < 0) {
return search(tree->left, key);
}
else if(strcmp(key,tree->key) > 0) {
return search(tree->right, key);
}
printf("Success!\n");
return tree;
}
一个简单的节点*就足以解决您的问题了。不需要双指针。