【问题标题】:Infinite Loop Linked List C无限循环链表 C
【发布时间】:2015-08-30 16:55:55
【问题描述】:

我正在做一个练习题以提高我的 C。这是问题:

编写一个函数对整数链表进行排序,如下所示:

a) 找出列表中的最大值。

b) 将其从其位置删除并插入到列表的头部。

c) 从现在的第二个元素开始,重复 (a) 和 (b)。

d) 从现在的第三个元素开始,重复 (a) 和 (b)。

继续直到列表排序。

我的排序功能:

NodePtr sortList(NodePtr np) {
  NodePtr makeNode(int), head, temp;

  head = temp = np;

  if (np != NULL) {
    // Determine linked list length
    int len = 0;
    while (temp != NULL) {
        len++;
        temp = temp -> next;
    }

    int i;
    for (i = 0; i < len; i++) {
        temp = head;
        int j;
        // Traverse to spot j in linked list
        for (j = 0; j < i; j++) {
            temp = temp -> next;
        }

        // Find largest
        NodePtr largest, prev, prevToLargest;
        largest = prev = prevToLargest = temp;
        while (temp != NULL) {
            if (temp -> num > largest -> num) {
                largest = temp;
                prevToLargest = prev;
            }

            if (temp != prev) prev = prev -> next;
            temp = temp -> next;
        }

        prevToLargest -> next = largest -> next;
        largest -> next = head;
        head = largest;
    }
  }

  return head;
}

使用调试器我发现我的列表已排序但它是无限的。我相信我已经创建了一个循环链表,但我不知道如何解决这个问题。

感谢您的帮助!

【问题讨论】:

  • 请不要在-&gt; 前后放置空格。这使您的代码难以阅读,并且几乎在所有地方都不鼓励使用。
  • 所有以注释开头的代码部分都可以(应该?)被提取到它们自己的函数中。这将使调试(和编写单元测试)变得更加容易......
  • 如果列表是空终止的,为什么还要预先计算列表?您应该能够使用终止 null 来中断 for() 或 while() 循环进行排序而无需预先计数。如果没有别的,通过在列表中添加一个额外的不必要的循环,这是非最优的低效代码。
  • 评论说“遍历以在列表中发现j”,但您实际上是在遍历以在列表中发现i 并将该位置保存在j 中。正确命名并准确指定问题非常重要,否则您会遇到维护问题。另外,@idmean 是绝对正确的,不要在-&gt; 周围加空格@
  • 这大约是基本 O(N^2) 链表排序所需代码的 3 倍。单个指针对指针消除了 ton (see it live here)。除非有 非常 特定条件,否则应避免使用hiding pointer types in typedef aliases。拥抱你的 C 再现并拥抱一个星号。

标签: c linked-list


【解决方案1】:

有几件事。首先,当要求人们调试代码时,请尝试包含行号,这使我们更容易引用问题。好的,现在解决实际问题。

  1. if (temp != prev) prev = prev -&gt; next; 在那一行代码上只是说 prev = temp,而不是 prev -> next 因为 temp 总是下一个,这不是什么大问题,但我认为它更容易跟随。

  2. 好的,所以你通过 largest-&gt;next = head 在头部之前插入最大的。但是,您插入的位置之前的索引仍然指向头部而不是最大,所以您的链接列表中有一个断开的链接。 *** 我说的是prevToLargest -&gt; next = largest -&gt; next;接近尾声之后的代码。

  3. 当您返回头部时,头部被移动了多次。因此,当您遍历整个列表时,您的代码将移动到列表中的最后一个元素,因为您有 head = largest; 并且最后一个最大元素将是列表末尾的最小元素.因此,在返回 head 之前,请尝试将其指向列表中的第一个元素。

看看这是否可以解决您的问题。可能有更多的错误,但这些是我最突出的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 2018-04-04
    相关资源
    最近更新 更多