C 链表-获取分段错误

C 链表-获取分段错误,c,linked-list,singly-linked-list,C,Linked List,Singly Linked List,我不知道为什么,请帮忙 这个问题是要交替拆分linkedlist节点。我使用了两个指针a和b,并交替添加到它,但它给出了错误。请帮助我您的代码中几乎没有错误- 尝试访问节点->下一步,而不检查节点是否存在 根据链表的长度(即,如果长度(链表)下一步,而不检查节点是否存在 根据链表的长度(即,如果长度(链表)next;当前=b->next看起来很可疑。如果列表中没有至少3个节点,则会出现问题。实际上,如果没有至少2个节点,且节点数为偶数,则会出现问题。堆栈溢出不是免费的调试服务,您应该尝试使用调

我不知道为什么,请帮忙


这个问题是要交替拆分linkedlist节点。我使用了两个指针a和b,并交替添加到它,但它给出了错误。请帮助我

您的代码中几乎没有错误-

  • 尝试访问节点->下一步,而不检查节点是否存在
  • 根据链表的长度(即,如果长度(链表)<3),不处理拐角情况
  • 然后出现了一个错误,您试图创建新的链表,最后aRef和bRef被分配到各自链表中的最后一个节点
请尝试处理这些问题,下面的代码可供参考

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;
}
希望这会有所帮助


不断询问,不断增长:)

代码中几乎没有错误-

  • 尝试访问节点->下一步,而不检查节点是否存在
  • 根据链表的长度(即,如果长度(链表)<3),不处理拐角情况
  • 然后出现了一个错误,您试图创建新的链表,最后aRef和bRef被分配到各自链表中的最后一个节点
请尝试处理这些问题,下面的代码可供参考

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;
}
希望这会有所帮助


不断询问,不断增长:)

像大多数链表重排练习一样,指向指针的指针使工作变得越来越容易。本练习的重点在于,在不更改所述指针的数据值的情况下,灵活地更改
下一个
指针。在C中,指向指针的指针是一种很好的方法

这尤其微不足道,因为已经为您提供了指向指针参数的目标指针,我们可以重用它来构建每个列表。通过演示一种使用单头指针和指向指针的指针构建前向链表的技术,可以更好地理解其工作原理:

void AlternatingSplit(struct Node* source, struct Node** aRef, 
                    struct Node** bRef) 
{

struct Node* a,b; 
struct Node* current = source;

if(current){
       a=current;
       b=current->next;
       // moving 'current' one step at a time will secure the code from crashing for corner cases
       current = current->next;
       if(b)
             current=b->next;
       a->next=NULL;
       b->next=NULL;

       //link aRef bRef right here
       *aRef = a;
       *bRef = b;
       }

 else {
      *aRef = source; // Null
      *bRef = source; // Null
      return;
      }

while(current) 
{
     a->next=current;
     a=a->next;
     b->next=current->next;
     b=b->next;
     current=current->next;
     if(b){
          current = b->next;
          }
 }
 b->next = NULL;
 a->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;
}

像大多数链表重排练习一样,指向指针的指针使工作变得非常简单。本练习的重点在于,在不更改所述指针的数据值的情况下,灵活地更改
下一个
指针。在C中,指向指针的指针是一种很好的方法

这尤其微不足道,因为已经为您提供了指向指针参数的目标指针,我们可以重用它来构建每个列表。通过演示一种使用单头指针和指向指针的指针构建前向链表的技术,可以更好地理解其工作原理:

void AlternatingSplit(struct Node* source, struct Node** aRef, 
                    struct Node** bRef) 
{

struct Node* a,b; 
struct Node* current = source;

if(current){
       a=current;
       b=current->next;
       // moving 'current' one step at a time will secure the code from crashing for corner cases
       current = current->next;
       if(b)
             current=b->next;
       a->next=NULL;
       b->next=NULL;

       //link aRef bRef right here
       *aRef = a;
       *bRef = b;
       }

 else {
      *aRef = source; // Null
      *bRef = source; // Null
      return;
      }

while(current) 
{
     a->next=current;
     a=a->next;
     b->next=current->next;
     b=b->next;
     current=current->next;
     if(b){
          current = b->next;
          }
 }
 b->next = NULL;
 a->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;
}

你需要提供一个MCVE。但是
b=current->next;当前=b->next看起来很可疑。如果列表中没有至少3个节点,则会出现问题。实际上,如果没有至少2个节点,且节点数为偶数,则会出现问题。堆栈溢出不是免费的调试服务,您应该尝试使用调试器或其他更简单的方法(如调试打印语句)调试代码。您还可以分别测试代码的每一部分,以准确地找出导致问题的代码的哪一部分,并做出正确的判断。这并不是你唯一一次在代码中遇到bug,学习调试程序比让别人帮你找到bug更有帮助。现在,很多开发环境都带有调试工具。调试器是蜜蜂的膝盖。它们允许您控制程序的执行,如果需要,一条指令一条指令地执行,并在执行过程中检查变量。这是一个非常有用的工具,用于了解程序真正在做什么。您需要提供一个MCVE。但是
b=current->next;当前=b->next看起来很可疑。如果列表中没有至少3个节点,则会出现问题。实际上,如果没有至少2个节点,且节点数为偶数,则会出现问题。堆栈溢出不是免费的调试服务,您应该尝试使用调试器或其他更简单的方法(如调试打印语句)调试代码。您还可以分别测试代码的每一部分,以准确地找出导致问题的代码的哪一部分,并做出正确的判断。这并不是你唯一一次在代码中遇到bug,学习调试程序比让别人帮你找到bug更有帮助。现在,很多开发环境都带有调试工具。调试器是蜜蜂的膝盖。它们允许您控制程序的执行,如果需要,一条指令一条指令地执行,并在执行过程中检查变量。这是一个非常有用的工具,用于了解程序真正在做什么。无关。一致的缩进样式有助于检测错误并使程序员保持理智。这个例子似乎从Ratliff缩进部分切换到了Allman。哇,这是我没想到的。我才意识到。在你的评论之后,我学到了一些新东西。谢谢,没关系。一致的缩进样式有助于检测错误并使程序员保持理智。这个例子似乎从Ratliff缩进部分切换到了Allman。哇,这是我没想到的。朱