C语言 单链表的升序排序

14ifxucb  于 2023-06-28  发布在  其他
关注(0)|答案(4)|浏览(91)

我正在做一个排序列表的程序。但问题是head中的元素将在第二次递归调用中被忽略。es:

input: 7->1->8->0->NULL OUTPUT: 1->0->7->8->NULL.

为什么1被忽略了?
这是一个node struct:

struct nodo {
    int elem;
    struct nodo *next;
};

和功能:

struct nodo *ordinaLista(struct nodo *head) {
    //in ordine crescente

    if (!head)
        return NULL;
    else {
        if ((head->next) && (head->elem >= head->next->elem)) {
            int tmp = head->elem;
            head->elem = head->next->elem;
            head->next->elem = tmp;
        }
        //printList(head);
        
        head->next = ordinaLista(head->next); 
        head->next = ordinaLista(head->next);
    }
    return head;
}
fae0ux8s

fae0ux8s1#

您的函数没有正确排序列表:你只对前两个元素进行排序,然后继续对列表的其余部分进行排序:唯一保证在适当位置结束的元素是将成为最后一个元素的最大元素。
递归地调用函数两次可能会解决这个问题,但是你需要改变操作的顺序:对于具有指数复杂度的简单实现O(n!),你应该首先对列表的其余部分进行排序,然后测试第一个元素是否需要与第二个元素交换,确保第一个元素是最小的元素,最后如果元素被交换,重新排序列表的其余部分。
以下是修改后的版本:

struct nodo *ordinaLista(struct nodo *head) {
    //in ordine crescente

    if (head && head->next) {
        head->next = ordinaLista(head->next); 
        if (head->elem > head->next->elem) {
            int tmp = head->elem;
            head->elem = head->next->elem;
            head->next->elem = tmp;
            head->next = ordinaLista(head->next);
        }
    }
    return head;
}

这种方法非常低效,但似乎与您在问题中提交的代码相对应。更有效的方法是对链表进行排序,如合并排序。

iyr7buue

iyr7buue2#

让我们模拟排序过程:
7->1->8->0->NULL
1->7->8->0->NULL
实际上,模拟第一步就足够了。如您所见,“1”节点被交换到第一个位置,然后程序继续向后执行,“1”被忽略。事实上,你的排序算法是不正确的。你的排序算法实际上是一个“泡沫”。要完成排序,需要多次冒泡。具体算法可以参考“冒泡排序”。

dohp0rv5

dohp0rv53#

你的函数的问题是你并没有真正执行排序。你的函数只是将整数的值与下一个更大的值交换。
这样,在单个迭代中,可以保证列表中的最后一项是最大的。
为什么要递归调用函数两次?这个动作对我来说很奇怪。

  • PS:避免使用意大利语的代码注解,英语始终是首选 *
vtwuwzda

vtwuwzda4#

OP的排序代码已损坏
与其对这种固有的缓慢方法进行小的修复,不如考虑一种更有效的方法。
示例:

// Pseudo code
struct nodo *ordinaLista(struct nodo *head) {
  // Walk list to find length N                     O(n)
  // Allocate N `elem` array A[]                    O(1)
  // Walk list and assign A[]                       O(n)
  // Sort array: qsort(A)                           O(n * log(n))
  // Walk list & re-assign list elements from A[]   O(n)
  // Free A[]                                       O(1)
}

相关问题