【问题标题】:Unable to iterate the linked list in C无法在C中迭代链表
【发布时间】:2018-03-23 03:18:48
【问题描述】:

我正在尝试打印链接列表的所有成员。我正在遍历列表并计算列表中整数的重复副本(如果有)。但是当我再次遍历列表以检查重复副本时,我的 ipNext 指向 null 终止我之前的遍历循环。

插入数据函数:

void insertIP(bstNode *head, char user[], int ip){
    if(head != NULL){
        bstNode* startList = head;
        while ((startList) && (strcmp(startList->data, user) != 0) ){
            if(strcmp(user, startList->data)<0)
            {
                startList=startList->left; 
            }
            else if(strcmp(user, startList->data)>0)
            {
                startList=startList->left; 
            }
        }

        if (startList != NULL){

            IP* new = (IP*)malloc(sizeof(IP));
            new->ip = ip;

            //new->count = (new->count + 1);
            new->ipNext=NULL;

            IP* temp = startList->ipHead;
            startList->ipHead = new;
            new->ipNext = temp;
        }
    }
}

迭代函数,它查找特定数据条目并计算它在链表中出现的次数(如果有)。

bstNode* search(char* key, bstNode* root)
{
    int res;
    bstNode *leaf = root;
    if( leaf != NULL ) {
        res = strcmp(key, leaf->data);
        if( res < 0)
            search( key, leaf->left);
        else if( res > 0)
            search( key, leaf->right);
        else
        {
            printf("\n'%s' found!\n", key);

            //int count = 0;
            bstNode *temp = leaf;

            while (temp->ipHead != NULL) {

                int tempip = temp->ipHead->ip;
                int ipcount = 0;


                uint32_t ip = tempip;
                struct in_addr ip_addr;
                ip_addr.s_addr = ip;

                bstNode *cpy = leaf;
                ipcount = count(&cpy, tempip);

                //temp = leaf;

                printf("The IP address is %s\n C:%d\n", inet_ntoa(ip_addr), ipcount);

                temp->ipHead = temp->ipHead->ipNext;
            }
        }
    }
    else printf("\nNot in tree\n");
    return leaf;
}

支持函数(这会将 ipNext 值设置为 null,从而终止搜索循环。即使我传递了指针的副本,我认为这是我的问题)。

int count(bstNode** start, int item)
{
    bstNode* current = *start;

    int count = 0;
    while (current->ipHead->ipNext != NULL)
    {
        if (current->ipHead->ip == item)
        {
            count++;
        }
        current->ipHead = current->ipHead->ipNext;
    }
    return count;
}

数据结构声明:

typedef struct ip{
    int ip;
    struct ip *ipNext;
}IP;

typedef struct bstNode
{
    char data[32];
    struct bstNode* left;
    struct bstNode* right;
    IP *ipHead; 
}bstNode;

BST 插入函数:

bstNode *insert(bstNode *root, char *word, int ip)
{

    bstNode *node = root; 

    if(node==NULL){
        node= malloc(sizeof(bstNode));
        //IP* ipNode=malloc(sizeof(IP));
        strcpy(node->data, word);
        node->left=NULL;
        node->right=NULL;
        insertIP(node, word, ip);
    }
    else{
        if(strcmp(word, node->data)<0)
            node->left=insert(node->left, word, ip);
        else if(strcmp(word, node->data)>0)
            node->right=insert(node->right, word,ip);
        else if(strcmp(word, node->data) == 0) {
            insertIP(node, word, ip);
        }
    }


    return node;
    }

感谢大家的帮助!

【问题讨论】:

  • current-&gt;ipHead = current-&gt;ipHead-&gt;ipNext - 对于应该只读遍历链表和计数节点的函数来说,这是一个真的坏主意。使用临时指针;不是带有覆盖的列表头。将const 单个间接指针传递给这个函数(这是它真正需要的,所以......)会在编译时发现这个错误。无关,我强烈建议不要将局部变量命名为与它们所在的函数相同的名称。
  • 你是在做一个二叉搜索树还是一个排序链表,如果它的二叉搜索树你没有在插入中设置右侧节点
  • @Pras 它看起来是一棵二叉搜索树,其节点包含 IP 记录的链表链。
  • 顺便说一句,您的搜索功能中的temp-&gt;ipHead = temp-&gt;ipHead-&gt;ipNext; 也存在同样的问题。您可能需要查看有关指针的文本/课程参考。您似乎认为制作指针的副本意味着您可以修改它所指向的内容而不会产生影响。实际上,这意味着您现在拥有 两个 指针,您可以/将通过这些指针修改数据。
  • @WhozCraig Right..显然 bst 是由用户,Anon_Singh 在插入函数中你应该在这里取正确的子树 "else if(strcmp(user, startList->data)>0){startList=startList- >左;}”

标签: c loops pointers linked-list iterator


【解决方案1】:

正如 cmets 中所指出的,这是您的问题:

    while ((startList) && (strcmp(startList->data, user) != 0) ){
        if(strcmp(user, startList->data)<0)
        {
            startList=startList->left; 
        }
        else if(strcmp(user, startList->data)>0)
        {
            startList=startList->left; 
        }
    }

在这两种情况下,您都在走左路。我不会将此作为答案发布(因为 Pras 已经在 cmets 中回答了它,但是当我看到这种未优化的代码时,它让我很困扰:您可以多次调用 strcmp() 函数数据和结果将始终相同。如果比较长字符串,strcmp() 可能是一项代价高昂的操作,而且您在树内执行此操作,因此此操作可以执行很多次。所以为什么不您第一次将结果分配到变量中,然后测试结果,而不是再次调用 strcmp()。像:

    int result;

    while (startList && (result = strcmp(startList->data, user)) ) {
        if (result < 0)
        {
            startList = startList->left; 
        }
        else if (result > 0)
        {
            startList = startList->right; 
        }
    }

其实第二个if不需要,你可以用一个简单的else,因为对0的测试是在while语句的条件下完成的,所以很明显如果结果不是0。

【讨论】:

    猜你喜欢
    • 2013-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多