c语言对链表的数据排序的问题,分不是问题!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言对链表的数据排序的问题,分不是问题!相关的知识,希望对你有一定的参考价值。

要求是输入一串不定长度的正整数串,然后仅修改链表的指针部分(就是不修改链表的数据)来进行排序
我建立链表的时候将第一个节点数据固定为-2,链表的建立已经没有问题
#define LEN sizeof(struct Num)
struct Num

int num;
struct Num *next;
;
问题出在选出链表中的最小值的函数
struct Num *px(struct Num *a) //选择最小值

struct Num *p,*min,*head;
head = p = a;min = p->next;
while(1)

if(p->next == NULL || p->next->next == NULL) <-----------问题出在这里
break;
if(p->next->num < min->num)

min = p->next;
p->next = min -> next;

p = p->next;

if(head->next == min)

if(min != NULL)

head->next = min->next;
min->next = NULL;

else
head->next = NULL;

return min;

思路就是将最小值的节点剥离出来,通过循环调用连接起来
但是就在我标注的那里,如果删除任何一个条件都会报错,而保持这样的话,不会对链表的最后一个数字进行排序。
现在就是前面的数字都能正常排序,就是无法操作最后一个数字
我在链表后面固定增加一个-1之后,能够对10以上的数正常排序了,但是一遇到10以内的数排序会出错

单链表的选择排序,不是你的这种写法,应该是在定位最小值结点的同时定位其前驱结点。写个选择排序你试试看看。
void px(struct num *a) //a是带头结点的单链表

struct num *curptr, *preptr, *min, *premin, *last, *h;//curptr:当前结点,preptr:当前的前驱结点
h = a->next; //h是未排序区的表头
last = a; //last是已排序区的表尾,a是已排序区的表头头结点
last->next = NULL;
while(h) //当未排序区不空时

min = h; //先假定第一个结点就是最小值结点
premin = NULL; //premin用于跟踪最小值结点的前驱
preptr = min;
curptr = preptr->next;
while(curptr) //该while循环用于定位最小值结点,同时跟踪其前驱结点。
if(curptr->num < min->num) min = curptr, premin = preptr;
preptr = curptr, curptr = preptr->next;

if(min == h) h = min->next; //最小值在表头
else premin->next = min->next; //最小值在表中或表尾
min->next = last->next; //将最小值插入到已排序区的末尾
last = min;

参考技术A p 本身可能是一个 NULL 值,引用它可能会报错
p->next 也可能是一个 NULL 值,引用他可能会报错
正确的用法,应该像下面这样 :

if( NULL == p ) break;
if( NULL == p->next ) break;
if( NULL == p->next->next ) break;

上面代码,条里清晰,逻辑正确 。追问

帮我看看为何不能排序成功吧= =

追答

逻辑出错了吧
你一开始的时候,min 就指向 p->next
然后你用 p->next->num 和 min->num 进行比较
这不就是让 num 和自身进行比较么
先把这一个地方改正过来看看

参考技术B 没缘由,为什么删除掉p->next->next == NULL会报错?
这个函数的任务是摘出并返回最小值的节点是吧。在while循环中,查找过程中临时被摘出的节点挂在min指针,但当找到更小的节点p->next时,挂在min指针的节点无法放回,被直接丢掉了。因此这个思路逻辑上是错误的。

链表的冒泡排序算法

【中文标题】链表的冒泡排序算法【英文标题】:Bubble sort algorithm for a linked list 【发布时间】:2012-02-17 09:41:45 【问题描述】:

我编写了一个冒泡排序算法来对链表进行排序。我是一名 Java 初学者,正在尝试学习数据结构。我很困惑为什么我的第二个元素没有正确排序。

class SListNode 
    Object item;
    SListNode next;

    SListNode(Object obj) 
        item = obj;
        next = null;
    

    SListNode(Object obj, SListNode next) 
        item = obj;
        this.next = next;
    

public class SList 
    private SListNode head;
    private SListNode temp;

    public void sortList() 
        SListNode node = head, i, j;
        head = node;
        i = node;
        j = node.next;
        while (i.next != null) 
            while (j.next != null) 
                if ((Integer) i.item < (Integer) j.item) 
                    temp = i.next;
                    i.next = j.next;
                    j.next = temp;
                
                j = j.next;
            
            i = i.next;
        
    

这是我得到的输出

List after construction: [  3  6  9  4  12  15  ]
After sorting: [  3  4  9  12  6  15  ]

此外,我知道冒泡排序的最坏情况是 O(n2)。我可以在链表上使用归并排序来获得更好的时间复杂度吗?

【问题讨论】:

【参考方案1】:

有许多排序算法适用于链表,合并排序在这种情况下效果很好。我写的 an earlier answer to a question about sorting linked lists 探讨了链表上的许多经典排序算法,以及它们的时间和空间复杂性。您可以对链表使用插入排序、选择排序、归并排序和快速排序。稍加修改,你也可以让 heapsort 工作。我较旧的答案详细说明了如何执行此操作。

关于您的代码,请注意,在您的内部循环中,您将j 向前推进,直到next 指针变为null。此时,您永远不会将j 重置为其他任何东西,因此在外部循环的每次未来迭代中,内部循环都不会执行。您可能应该在每次迭代开始时设置j = i.next。此外,您可能不希望在j.next 为空时停止循环,而是在j 为空时停止循环,否则会跳过数组的最后一个元素。

此外,您在此处编写的排序算法是 selection sort 而不是冒泡排序,因为您在链表上进行了多次遍历,以寻找您没有找到的最小元素定位呢。我不知道这是否是一个问题,但我不确定你是否意识到这一点。也就是说,我认为这可能是一件好事,因为在大多数情况下,冒泡排序的效率低于选择排序(除非列表已经接近排序)。

希望这会有所帮助!

【讨论】:

【参考方案2】:

如果您有ListComparable 项,那么您可以使用Collections.sort 方法,该方法使用一种合并排序 算法,最坏情况时间复杂度为O(n log n)。无论如何,它比使用O(n²) 冒泡排序更快。

如果你想使用冒泡排序算法,你可以这样做:

public static void bubbleSort(List<Integer> list) 
    boolean swapped;
    // repeat the passes through the list until
    // all the elements are in the correct order
    do 
        swapped = false;
        // pass through the list and
        // compare adjacent elements
        for (int i = 0; i < list.size() - 1; i++) 
            // if this element is greater than
            // the next one, then swap them
            if (list.get(i) > list.get(i + 1)) 
                Collections.swap(list, i, i + 1);
                swapped = true;
            
        
        // if there are no swapped elements at the
        // current pass, then this is the last pass
     while (swapped);

public static void main(String[] args) 
    LinkedList<Integer> list = new LinkedList<>();
    Collections.addAll(list, 6, 1, 5, 8, 4, 3, 9, 2, 0, 7);
    bubbleSort(list);
    System.out.println(list); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


另见: • Bubble sort output is incorrect • Bubble sort with step-by-step output Java 8

【讨论】:

以上是关于c语言对链表的数据排序的问题,分不是问题!的主要内容,如果未能解决你的问题,请参考以下文章

链表的基本操作

关于C语言链表的问题,一个排序的问题,按num排序,求大佬帮助,在线等~!有点急~!

单链表C语言实现附加力扣题

数据结构c语言篇 《二》带头双向循环链表实现以及链表相关面试题(下)

数据结构c语言篇 《二》带头双向循环链表实现以及链表相关面试题(下)

四种语言刷算法之对链表进行插入排序