在C中递归搜索链表

时间:2014-02-26 16:09:21

标签: c list search recursion

我是C的新手,我试图编写一种递归搜索链表的方法,但是我没有成功。如果在链表的任何节点中找不到名称,则该函数包含返回0,并且找到1是。我似乎进入了无限循环。任何帮助将不胜感激!

#include<stdlib.h>
#include<string.h>

struct node
{
    char name[1000];
    struct node *next;
};

int contains(const struct node *pNode, const char *name)
{
    int i;
    int length = strlen(name);
    int isEqual = 0;

    while (pNode != NULL)
    {
        isEqual = 1;
        for (i = 0; i < length; i++)
        {
            if (pNode->name[i] != name[i])
            {
                isEqual = 0;
            }
        }
    }

    contains(pNode->next, name);

    return isEqual;
}

main()
{
    struct node node1 = { "Sam", NULL };
    struct node *node1Ptr = &node1;
    struct node node2 = { "Anna", node1Ptr };
    struct node *node2Ptr = &node2;
    struct node node3 = { "Adam", node2Ptr };
    struct node *node3Ptr = &node3;

    int n, k;

    // testing for a name that is the list
    n = contains(node3Ptr, "Sam");
    printf("%d\n", n);
    // testing for a name that is not in the list
    k = contains(node3Ptr, "Max");
    printf("%d\n", k);
}

6 个答案:

答案 0 :(得分:4)

您的功能可以简洁地写成:

#include <string.h>
...
int contains(const struct node *pNode, const char *name)
{
    if(pNode == NULL)
        return 0;
    if(strcmp(pNode->name, name) == 0)
        return 1;
    return contains(pNode->next, name);
}

请注意,代码中对contains()的递归调用的值永远不会被使用,因此不会给出任何有用的东西。它的调用在最后无条件地完成,这解释了无限循环。

编译启用所有(合理)警告(GCC和clang -Wall),它应该告诉你许多boo-boos。作为一项个人政策,如果不是-Wall干净,那么最好有充分的理由相信我是对的并且编译器过于热心。

您还可以简化数据结构的大部分设置,但这是另一次。

很高兴您根据需要使用const进行装饰。

答案 1 :(得分:1)

int contains(const struct node *pNode, const char *name)
{
    if (pNode == NULL)  // Recursive base-case:  If there is no Node,
    {                   // we are at the end of the list, and the name was never found.
        return 0;       // Therefore, return 0
    }

    // If this node matches the name, return 1.  
    // If this node does NOT match the name, check the next node.
    return !strcmp(pNode->name, name)? 1 : contains(pNode->next, name);
}

如果你想要一个非常紧张的形式:

// Untested, but I think it works... or is at least close.
int contains(const struct node *pNode, const char *name)
{
    return pNode? (!strcmp(pNode->name, name) || contains(pNode->next, name)) : pNode;
}

答案 2 :(得分:0)

您的无限循环是以下行的直接结果:

while (pNode != NULL)

因为永远不会改变 pNode所指向的内容。基本上你反复检查Sam ......事实上,你甚至没有 来进行递归通话。

相反,你想要一个

if(pNode != NULL) 

检查,如果没有,检查字符串。如果找到该字符串,则返回1,否则返回递归调用。

如果pNode==NULL想要返回0。

答案 3 :(得分:0)

如果你到达列表的末尾,你不应该调用函数包含但是你无限地调用它。 在通话前添加此内容:

if (pNode ->next != null)
contains(pNode->next,name);

你还需要阻止它调用包含物品,如果你对物品这样做,那么你的情况就像:

if (pNode ->next != null && !isEqual)
contains(pNode->next,name);

答案 4 :(得分:0)

pnode NULL 之后的包含方法中,您再次调用导致无限循环的函数。

修改如下。

if(pnode== NULL) {
return 0;
}

答案 5 :(得分:0)

这是我修改代码的方法,现在它可以工作了。谢谢大家的帮助,我真的很感激,并且我对strcmp函数并不熟悉,但我会深入研究。再次,谢谢。

int contains(const struct node *pNode, const char *name){
  int i;
  int length = strlen(name);
  int isEqual = 0;

  if(pNode == NULL){ 
      return isEqual;
    }

  isEqual = 1;
  for (i = 0; i < length; i++)
    {
        if (pNode->name[i] != name[i])
        {
            isEqual = 0;
            break;
        }
    }


 return isEqual? isEqual : contains(pNode->next, name);
}