在C语言中递归搜索链表

在C语言中递归搜索链表,c,list,search,recursion,C,List,Search,Recursion,我是C语言的新手,我曾尝试编写一个递归搜索链表的方法,但没有成功。如果在链表的任何节点中都找不到名称,则函数返回0,如果找到1,则返回1。我似乎进入了一个无限循环。任何帮助都将不胜感激 #include<stdlib.h> #include<string.h> struct node { char name[1000]; struct node *next; }; int contains(const struct node *pNode, const

我是C语言的新手,我曾尝试编写一个递归搜索链表的方法,但没有成功。如果在链表的任何节点中都找不到名称,则函数返回0,如果找到1,则返回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);
}
#包括
#包括
结构节点
{
字符名[1000];
结构节点*下一步;
};
int contains(常量结构节点*pNode,常量字符*name)
{
int i;
int length=strlen(名称);
int isEqual=0;
while(pNode!=NULL)
{
等质量=1;
对于(i=0;iname[i]!=name[i])
{
等质量=0;
}
}
}
包含(pNode->next,name);
回报均等;
}
main()
{
结构节点node1={“Sam”,NULL};
结构节点*node1Ptr=&node1;
结构节点node2={“Anna”,node1Ptr};
结构节点*node2Ptr=&node2;
结构节点node3={“Adam”,node2Ptr};
结构节点*node3Ptr=&node3;
int n,k;
//正在测试列表中的名称
n=包含(node3Ptr,“Sam”);
printf(“%d\n”,n);
//测试不在列表中的名称
k=包含(节点3ptr,“最大”);
printf(“%d\n”,k);
}

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

while (pNode != NULL)
因为你永远不会改变
pNode
所指向的内容。基本上,您是在反复检查
Sam
。。。事实上,您甚至都无法进行递归调用

相反,你会想要一个

if(pNode != NULL) 
检查,如果没有,请检查字符串。如果找到字符串,则返回1,否则返回递归调用


如果
pNode==NULL
您希望返回0。

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

while (pNode != NULL)
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);
}
因为你永远不会改变
pNode
所指向的内容。基本上,您是在反复检查
Sam
。。。事实上,您甚至都无法进行递归调用

相反,你会想要一个

if(pNode != NULL) 
检查,如果没有,请检查字符串。如果找到字符串,则返回1,否则返回递归调用

如果
pNode==NULL
您希望返回0

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;
}

如果您想要一个非常紧凑的表单:

// 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;
}

如果到达endof列表,则不应调用contain函数,但应无限次地调用它。 在通话前添加以下内容:

if (pNode ->next != null)
contains(pNode->next,name);
您还需要停止它调用contain,如果它调用了项目,那么您的条件如下:

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

如果到达endof列表,则不应调用contain函数,但应无限次地调用它。 在通话前添加以下内容:

if (pNode ->next != null)
contains(pNode->next,name);
您还需要停止它调用contain,如果它调用了项目,那么您的条件如下:

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

pnodeNULL之后的contains方法中,再次调用导致无限循环的函数

修改如下

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

pnodeNULL之后的contains方法中,再次调用导致无限循环的函数

修改如下

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

您的函数可以简明扼要地写为:

#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);
}
#包括
...
int contains(常量结构节点*pNode,常量字符*name)
{
if(pNode==NULL)
返回0;
if(strcmp(pNode->name,name)==0)
返回1;
返回包含(pNode->next,name);
}
请注意,代码中对
contains()
的递归调用的值从未使用过,因此不会给出任何有用的结果。它的调用在最后无条件完成,这就解释了无限循环

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

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


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

您的函数可以简洁地写成:

#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);
}
#包括
...
int contains(常量结构节点*pNode,常量字符*name)
{
if(pNode==NULL)
返回0;
if(strcmp(pNode->name,name)==0)
返回1;
返回包含(pNode->next,name);
}
请注意,代码中对
contains()
的递归调用的值从未使用过,因此不会给出任何有用的结果。它的调用在最后无条件完成,这就解释了无限循环

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

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


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

这就是我修改代码的方式,现在它可以工作了。谢谢大家的帮助,我真的很感激,我还不熟悉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);
}
int contains(常量结构节点*pNode,常量字符*name){
int i;
int length=strlen(名称);
int isEqual=0;
如果(pNode==NULL){
回报均等;
}
等质量=1;
对于(i=0;iname[i]!=name[i])
{
等质量=0;
打破
}
}
返回isEqual?isEqual:contains(pNode->next,name);
}

这就是我修改代码的方式,现在它可以工作了。谢谢大家的帮助,我真的很感激,而且我还不熟悉str