【问题标题】:C Programming linked list pointer returning weird valueC编程链表指针返回奇怪的值
【发布时间】:2015-10-31 06:19:21
【问题描述】:

我在尝试将两个已排序的链表合并为一个时遇到了一些问题。这是我的代码:

void sortedMerge(LinkedList *l1, LinkedList *l2, LinkedList *result)
{
    int i = 0;
    while (l1->size > 0 && l2->size > 0) {
        if (l1->head < l2->head) {
            removeNode(l1, 0);
            insertNode(result, i++, l1->head);
        }
        else {
            removeNode(l2, 0);
            insertNode(result, i++, l2->head);
        }
    }
}

int insertNode(LinkedList *ll, int index, int value)
{
    ListNode *pre, *cur;
    if (ll == NULL || index < 0 || index > ll->size + 1)
        return -1;
    if (ll->head == NULL || index == 0) {
        cur = ll->head;
        ll->head = malloc(sizeof(ListNode));
        ll->head->item = value;
        ll->head->next = cur;
        ll->size++;
        return 0;
    }
    if ((pre = findNode(ll, index - 1)) != NULL) {
        cur = pre->next;
        pre->next = malloc(sizeof(ListNode));
        pre->next->item = value;
        pre->next->next = cur;
        ll->size++;
        return 0;
    } 
    return -1;
}

int removeNode(LinkedList *ll, int index)
{
    ListNode *pre, *cur;
    if (ll == NULL || index < 0 || index >= ll->size)
        return -1;
    if (index == 0) {
        cur = ll->head->next;
        free(ll->head);
        ll->head = cur;
        ll->size--;
        return 0;
    }
    if ((pre = findNode(ll, index - 1)) != NULL) {    
        if (pre->next == NULL)
            return -1;
        cur = pre->next;
        pre->next = cur->next;
        free(cur);
        ll->size--;
        return 0;
    }
    return -1;
}

我的主要功能中的代码 sn-p:

case 1:
        printf("Input an integer that you want to add to the linked list 1:\n");
        scanf("%d", &i);
        j = insertSortedLinkedList(&ll1, i);
        printf("Linked list 1 : ");
        printList(&ll1);
        break;
    case 2:
        printf("Input an integer that you want to add to the linked list 2:\n");
        scanf("%d", &i);
        j = insertSortedLinkedList(&ll2, i);
        printf("Linked list 2 : ");
        printList(&ll2);
        break;
    case 3:
        sortedMerge(&ll1, &ll2, &resultMergedList); 
        printf("The resulting linked list is:\n");
        printList(&resultMergedList);
        break;

所以我为 l1 输入了2,4,6,为 l2 输入了1,2,3。预期的输出应该是1,2,2,3,4,6。但是,我收到了4229048, 4228432, 4228565, 0。 我在想是不是因为我得到的输出是内存位置?

有什么想法吗?提前致谢。

【问题讨论】:

  • main 函数基本上是获取 l1 和 l2 的输入,然后调用 sortedMerge。在 sortedMerge 内部,我然后调用 removeNode 和 insertNode
  • 复制和调试问题的唯一方法是使用工作程序(可能是 main 中发生的其他未定义行为)
  • insortedLinkedList() 工作正常,因为它来自我的其他问题。因为太长我没有发。基本上,该功能是填充 l1 和 l2。
  • 被否决为无法调试的不完整程序 - 请参阅 mvce 特别是完整部分
  • 您发布了一个小 sn-p 提示另一个功能(也未发布)。创建 mvce 的一部分是将问题减少到具有相同问题的最小程序。如果您无法做到这一点,至少有一个完整的程序可以复制该问题

标签: c pointers linked-list nodes


【解决方案1】:

正如 kcraigie 所指出的,您应该使用它创建一个新节点item。编译器应该警告你,你正在传递一个需要整数的指针。

快速修复似乎是这样的:

    removeNode(l1, 0);
    insertNode(result, index++, l1->head->item);

但事实并非如此:removeNode 将改变l1 的头部,很可能是NULL。取消引用NULL 可能会给您带来分段违规。

该修复还有其他问题:如果成功,它会在移除的头之后添加节点的项目。所以做这样的事情:

    int item = l1->head->item;

    removeNode(l1, 0);
    insertNode(result, index++, item);

更正后,您的合并仍未完成:您最终会遇到其中一个列表为空的情况。你不处理这种情况。

还有改进的余地。您采取简单的方法,只需销毁列表并使用相同的数据创建一个新列表。这是对您的问题的有效解决方案,但只需重新排列(或重新链接)现有节点即可解决问题。

这是合并列表的方法的更正版本:

void sortedMerge(LinkedList *l1, LinkedList *l2, LinkedList *result)
{
    int index = 0;
    while (l1->size > 0 && l2->size > 0) {
        if (l1->head->item < l2->head->item) {
            int item = l1->head->item;

            removeNode(l1, 0);
            insertNode(result, index++, item);
        } else {
            int item = l2->head->item;

            removeNode(l2, 0);
            insertNode(result, index++, item);
        }
    }

    while (l1->size) {
        int item = l1->head->item;

        removeNode(l1, 0);
        insertNode(result, index++, item);
    }

    while (l2->size) {
        int item = l2->head->item;

        removeNode(l2, 0);
        insertNode(result, index++, item);
    }    
}

您可以将重复的删除和插入重构为一个新函数。

【讨论】:

  • 但是根据您提供的解决方案,当我为 l1 输入 1、2、3 和为 l2 输入 2、4、6 时。我得到的输出是 1,2,1,1,这真的很奇怪。此外,l1 和 l2 的最后 2 个数字也丢失了。有什么想法吗?
  • 因为你的代码不完整,所以我的回答不可能是完整的解决方案。我解释了为什么您的最后一个节点丢失:while 循环在其中一个列表为空时停止,但您必须注意仍在另一个列表中的节点。
  • 还有一个bug:if (l1-&gt;head &lt; l2-&gt;head)比较指针,你要比较item值:if (l1-&gt;head-&gt;item &lt; l2-&gt;head-&gt;item)
  • 是的,我也注意到了。但是你认为我在解决这个问题的正确逻辑轨道上吗?还是我必须想出另一种算法?
  • 你在正确的轨道上。正如我所说,从原始列表中弹出节点并将它们附加到新列表中是一个很好的解决方案。但是您必须进行一些更改并添加代码来处理剩余的节点。我添加了一个糟糕的例子。
【解决方案2】:

您正在使用 l1->head 而不是 l1->head->item 在结果链表上调用 insertNode()。

相反,尝试将头部的项目插入到 result 中,然后再释放它:

while (l1->size > 0 && l2->size > 0) {
    if (l1->head < l2->head) {
        insertNode(result, index++, l1->head->item);
        removeNode(l1, 0);
    } else {
        insertNode(result, index++, l2->head->item);
        removeNode(l2, 0);
    }
}

此外,当您的一个列表用完时,您会退出并忽略另一个列表中的剩余项目。您可以在上述循环之后添加此代码:

while (l1->size > 0) {
    insertNode(result, index++, l1->head->item);
    removeNode(l1, 0);
}
while (l2->size > 0) {
    insertNode(result, index++, l2->head->item);
    removeNode(l2, 0);
}

不是最有效的,但应该可以。

【讨论】:

  • 它在一段时间后停止工作。有任何想法吗?你没有错误信息。当我在调试模式下运行时,它告诉我访问冲突
  • 是的,您的问题可能是:removeNode(l1, 0); insertNode(result, index++, l1-&gt;head); 您正在删除 l1->head,释放内存,然后尝试使用 insertNode() 添加它
  • @kcraigie 同意了。如果您要释放包含该值的节点,然后尝试使用该值,那很可能是导致您的问题的原因。
  • @kcraigie 你打败了我两次,一次是最初的评论,然后是我编辑评论的时候哈
  • @Plopperzz 对不起,我给你的评论点赞作为安慰奖 ;)
【解决方案3】:

示例合并排序列表函数,以及一个排序列表函数,它使用指向列表节点的指针数组以及合并列表函数来实现链表的快速排序。

NODE * MergeLists(NODE *pSrc1, NODE *pSrc2)
{
NODE *pDst = NULL;                      /* destination head ptr */
NODE **ppDst = &pDst;                   /* ptr to head or prev->next */
    if(pSrc1 == NULL)
        return pSrc2;
    if(pSrc2 == NULL)
        return pSrc1;
    while(1){
        if(pSrc2->data < pSrc1->data){  /* if src2 < src1 */
            *ppDst = pSrc2;
            pSrc2 = *(ppDst = &(pSrc2->next));
            if(pSrc2 == NULL){
                *ppDst = pSrc1;
                break;
            }
        } else {                        /* src1 <= src2 */
            *ppDst = pSrc1;
            pSrc1 = *(ppDst = &(pSrc1->next));
            if(pSrc1 == NULL){
                *ppDst = pSrc2;
                break;
            }
        }
    }
    return pDst;
}

#define NUMLISTS 32                     /* size of aList[] */
NODE * SortList(NODE *pList)
{
NODE * aList[NUMLISTS];                 /* array of lists */
NODE * pNode;
NODE * pNext;
int i;
    if(pList == NULL)                   /* check for empty list */
        return NULL;
    for(i = 0; i < NUMLISTS; i++)       /* zero array */
        aList[i] = NULL;
    pNode = pList;                      /* merge nodes into aList[] */
    while(pNode != NULL){
        pNext = pNode->next;
        pNode->next = NULL;
        for(i = 0; (i < NUMLISTS) && (aList[i] != NULL); i++){
            pNode = MergeLists(aList[i], pNode);
            aList[i] = NULL;
        }
        if(i == NUMLISTS)
            i--;
        aList[i] = pNode;
        pNode = pNext;
    }
    pNode = NULL;                       /* merge array into one list */
    for(i = 0; i < NUMLISTS; i++)
        pNode = MergeLists(aList[i], pNode);
    return pNode;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    • 2023-04-07
    • 2021-07-28
    • 2014-09-11
    • 2016-01-31
    相关资源
    最近更新 更多