c - 链表-获取段错误

标签 c linked-list singly-linked-list

void AlternatingSplit(struct Node* source, struct Node** aRef, 
                        struct Node** bRef) 
{
/* split the nodes of source to these 'a' and 'b' lists */
struct Node* a ; 
struct Node* b;

struct Node* current = source;
if(current){
    a=current;
    b=current->next;
    current=b->next;
    a->next=NULL;
    b->next=NULL;
}

while(current) {    
    a->next=current;
    b->next=current->next;

    if(b)
        current=b->next;

    b=b->next;
    a=a->next;
}

*aRef = a;
*bRef = b;
}

我在这里遇到段错误,我不知道为什么请帮忙。

本题是交替拆分链表节点。我正在使用两个指针 a 和 b 并交替添加到它但它给出错误。请帮助我

最佳答案

与大多数链表重排练习一样,指向指针的指针使工作变得非常、非常容易。这个练习的目的是展示你改变 next 指针的能力,而不用改变 said-same 的数据值。指向指针的指针是在 C 中执行此操作的绝佳方式。

这特别简单,因为您已经为您提供了目标指针到指针的参数,我们可以重复使用这些参数来构建每个列表。通过演示使用单个头指针和指向指针 p 的指针构建前向链表的技术,可以最好地理解其工作原理:

struct Node *head, **pp = &head;
for (int i = 1; i <= 20; ++i)
{
    *pp = malloc(sizeof **pp);
    (*pp)->data = i;
    pp = &(*pp)->next;
}
*pp = NULL;

是的,它需要错误检查,但算法是这里关注的重点。此代码仅使用 pp 来构建实际列表。规则是这样的:pp 是指向 Node 的指针,总是 保存指向 Node< 的下一个指针的地址 来填充。这就是指向指针的指针所做的:保存指针的地址。在这种情况下,pp 最初保存头指针的地址。随着每个新节点的添加,pp 获取先前刚刚添加的节点的 next 指针的地址。有道理,对吧?那将是我们要挂起下一个节点的下一个指针。这个过程一直持续到我们完成循环。在该指针 pp 中保存着 last 节点的 next 指针的地址,我们将其设置为 NULL 以终止列表。

现在,了解我们上面学到的知识,考虑一下:

void AlternatingSplit(struct Node* source, struct Node** a, struct Node** b)
{
    while (source)
    {
        *a = source;
        a = &(*a)->next;

        source = source->next;
        if (source)
        {
            *b = source;
            b = &(*b)->next;
            source = source->next;
        }
    }

    *a = *b = NULL;
}

示例

下面显示了一个使用我首先展示的前向链接构建算法和我之后展示的拆分算法的简短示例。包括一些用于打印列表的实用函数。我将释放列表(现在有两个,记住遍历两个并释放每个节点)作为练习供您使用:

#include <stdio.h>
#include <stdlib.h>

struct Node
{
    int data;
    struct Node *next;
};

void AlternatingSplit(struct Node* source, struct Node** a, struct Node** b)
{
    while (source)
    {
        *a = source;
        a = &(*a)->next;

        if ((source = source->next))
        {
            *b = source;
            b = &(*b)->next;
            source = source->next;
        }
    }

    *a = *b = NULL;
}

void PrintList(struct Node const *p)
{
    while (p)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    fputc('\n', stdout);
}


int main(void)
{
    struct Node *head, **pp = &head;
    for (int i = 1; i <= 20; ++i)
    {
        *pp = malloc(sizeof **pp);
        (*pp)->data = i;
        pp = &(*pp)->next;
    }
    *pp = NULL;

    PrintList(head);

    struct Node *a = NULL, *b = NULL;
    AlternatingSplit(head, &a, &b);

    PrintList(a);
    PrintList(b);

    return EXIT_SUCCESS;
}

输出

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 3 5 7 9 11 13 15 17 19
2 4 6 8 10 12 14 16 18 20

关于c - 链表-获取段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51452473/

相关文章:

c - 在 memcmp 中我们可以使用数组而不是指针吗

java - UP2 IoT GrovePi - 通过编程获取已连接设备列表(Python/C/CPP/Java)

java - 使用泛型制作链表

c - 试图从c中的双链表中删除一个元素

c - 添加多个患者 C 指针

python - 如何创建循环链表

C - 交换单链表中的第一个和最后一个元素

c++ - fscanf C++ 等价物

Java LinkedList 在索引处插入对象

c - 读取: separated fscanf in C