【问题标题】:Unable to exit the while loop无法退出 while 循环
【发布时间】:2015-02-06 18:37:47
【问题描述】:

我尝试编写一个名为“分离链表中的偶数和奇数节点”的单链表程序,但无法从 while 循环中退出。

我能够成功编译运行代码。我一步步跟踪程序四次以上,但找不到catch。

我所说的“在链接列表中分离偶数和奇数节点”的意思

输入:17->15->8->12->10->5->4->1->7->6->NULL ;输出:8->12->10->4->6->17->15->5->1->7->NULL

输入:8->12->10->5->4->1->6->NULL ;输出:8->12->10->4->6->5->1->NULL

如果所有数字都是偶数,则不要更改列表 输入:8->12->10->NULL 输出:8->12->10->NULL

如果所有数字都是奇数,则不要更改列表 输入:1->3->5->7->NULL 输出:1->3->5->7->NULL

我是如何解决这个问题的:

temp : 遍历列表。

evenPtr :指向偶数数据节点的指针。

oddPtr :指向奇数数据节点的指针。

oddPtrStart : 跟踪奇数数据节点的开始。

我的功能如下:

struct node *segregateEvenOddNodesSLL(struct node *temp)
{
    struct node *evenPtr,*oddPtr,*oddPtrStart,*head=NULL;

    head=temp;  

    while(1)
    {  
        if(((temp->data)%2)==0)   // even 
        {

            if(evenPtr==NULL)
            {
                head=temp;
                evenPtr=temp;
            }
            else
            {
                evenPtr->link=temp;
                evenPtr=temp;
            }  


        }

        else               // odd
        {
            if(oddPtr==NULL)
            {  
                oddPtrStart=temp;
                oddPtr=temp;
            }
            else
            {
                oddPtr->link=temp;
                oddPtr=temp;
            }



        }

        temp=temp->link;
        if(temp==NULL)
        {
            break;
        }

        printf("\n Inside  While.... \n");

    }// end of while.

    if(evenPtr==NULL)
    { 
        return head;
    }
    else if(oddPtr==NULL)
    {
        return head;
    }
    else
    {
        oddPtr->link=NULL;
        evenPtr->link=oddPtrStart;

        return head;
    }


}

使用 head=segregateEvenOddNodesSLL(head); 调用函数

像往常一样,单链表的结构是:

struct node 
{
int data;
struct node *link;
};

【问题讨论】:

  • 额外(虚拟)功劳:在不使用多个if / else 构造或多个循环构造的情况下实施该过程。

标签: c while-loop linked-list break


【解决方案1】:

检查以下行:

struct node *evenPtr,*oddPtr,*oddPtrStart,*head=NULL;

这需要:

struct node *evenPtr=NULL,*oddPtr=NULL,*oddPtrStart=NULL,*head=NULL;

我是这样发现的:

  1. 编译器应该会警告您忘记初始化这些值。
  2. 单步执行,您应该会立即注意到,一旦进入 while 循环,oddPtr 和/或 evenPtr 不为空。

【讨论】:

  • 但是我使用临时指针存在 while 循环,而不是使用指针的其余部分。
  • 在进入循环退出测试之前,您读取了evenPtr 和/或oddPtr 的值(将它们与NULL 进行比较)。这些变量未初始化,因此它们可以包含任何内容。它们可能包含垃圾,但您可能很不幸,其中一个或两个包含作为参数temp 传入的相同值,或指向列表中其他节点之一的指针,在这种情况下,第一次迭代您的循环将输入列表转换为循环列表。
  • 即使未初始化的变量有无意义的值,初始化失败显然是个bug。修复它。
【解决方案2】:

首先,您在初始化变量evenPtroddPtr 之前测试它们的值。看起来您想在进入循环之前将它们中的每一个初始化为 NULL

完成后,如果...

    temp=temp->link;
    if(temp==NULL)
    {
        break;
    }

...永远不会到达break 以触发循环退出,并且您永远不会遇到分段错误或其他内存访问错误,那么最可能的解释是您的链表是循环的。您可以通过在每次迭代中打印当前节点的 data 来提示自己。

还要注意,循环后的代码存在缺陷:如果列表不包含偶数项,则所有节点都将丢失。

【讨论】:

    【解决方案3】:

    这是一个解决方案,它使用列表生成器来制作初始列表和偶数/奇数列表。我使用了一个轻微的“作弊” - 最简单的列表是按相反的顺序制作的,因此制作次要的偶数和奇数列表会将它们颠倒到原始顺序。

    另一种方法是对原始列表进行冒泡排序,如果“奇”出现在“偶”之前,则交换数据字段,但此答案试图与 OP 的做法保持一致。

    #include <stdio.h>
    #include <stdlib.h>
    
    struct node {
        int data;
        struct node *link;
    };
    
    struct node* add_node(struct node *list, int id) {
        struct node *n = malloc( sizeof (struct node) );
        if (n == NULL) {
            printf("Fatal Error: Out of memory!\n");
            exit(1);
        }
        n->data = id;
        n->link = list;
        return n;
    }
    
    struct node *segregateEvenOddNodesSLL(struct node *temp) {
        struct node *odd=NULL,*even=NULL, *last = NULL;
        while(temp) {  
            if(((temp->data)%2)==0) {       // even
                even = add_node (even, temp->data);
                if (last == NULL)
                    last = even;
            }
            else
                odd = add_node (odd, temp->data);
            temp = temp->link;
        }
        if(even) {
            last->link = odd;            // append odd list
            return even;
        }
        return odd;
    }
    
    void show (struct node *list) {
        printf("List: ");
        while(list != NULL) {
            printf("%3d", list->data); 
            list = list->link;
        }
        printf("\n");
    }
    
    void free_list(struct node *list) {
        struct node *tmp;
        while (list) {
            tmp = list->link;    
            free(list);
            list = tmp;
        }
    }
    
    void make_list(int *array, int elements) {
        struct node *list = NULL, *newlist;
        int i;
        printf("Array:");
        for (i=0; i<elements; i++) {
            printf ("%3d", array[i]);               // show unsorted array
            list = add_node(list, array[i]);        // make the linked list
        }
        printf("\n");
        newlist = segregateEvenOddNodesSLL(list);   // sort it
        show (newlist);                             // show sorted list
        printf ("\n");
        free_list (list);
        free_list (newlist);
    }
    
    int main(void) { 
        int data1[10] = { 17, 15, 8, 12, 10, 5, 4, 1, 7, 6 };
        int data2[7] = { 8, 12, 10, 5, 4, 1, 6 };
        int data3[3] = { 8, 12, 10 };
        int data4[4] = { 1, 3, 5, 7 };
    
        make_list(data1, 10);
        make_list(data2, 7);
        make_list(data3, 3);
        make_list(data4, 4);
        return 0;
    }
    

    程序输出:

    Array: 17 15  8 12 10  5  4  1  7  6
    List:   8 12 10  4  6 17 15  5  1  7
    
    Array:  8 12 10  5  4  1  6
    List:   8 12 10  4  6  5  1
    
    Array:  8 12 10
    List:   8 12 10
    
    Array:  1  3  5  7
    List:   1  3  5  7
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-20
      • 1970-01-01
      相关资源
      最近更新 更多