LeetCode中等题:147. 对链表进行插入排序(使用C语言)

对链表进行插入排序。
图源LeetCode147. 对链表进行插入排序

插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。

插入排序算法:

插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
重复直到所有输入数据插入完为止。

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4
示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* insertionSortList(struct ListNode* head){
    
    
        //系统会很贼地输入空的head,然后就会报错,很烦,以防这种情况
    if (head==NULL) return head;
        //可能有插入头结点之前的情况,有虚拟头结点dummyhead作为前驱节点,可以更方便进行插入
    struct ListNode* dummyhead=(struct ListNode *)malloc(sizeof(struct ListNode));
        //赋值,防止内存泄露,反正接下来也用不到
    dummyhead->val=0;
        //dummyhead的下一节点指向head
    dummyhead->next=head;
        //创建指向已排序链表尾部的指针节点tail,默认指向头节点
        //就像选择排序要先定义个用来比较的参照物一样
    struct ListNode* tail=head;//获取head所有元素
        //node指向待排序的节点,tail所指的head就当做排好了,看下一个就行了
    struct ListNode* node=head->next;
        //当node指向空.就结束循环,这里省略了"=NULL"
    while(node)
    {
    
    
            //如果待排序的节点正好大于尾节点tail,天助我也,这不就正好排完序了嘛
        if(node->val>tail->val)
        {
    
    
                //既然算排完序了,尾指针tail也就指向下一个节点了
            tail=tail->next;
                //待排序节点node也指向下一个
            node=node->next;
                //下面的语句是待排序节点小于尾节点的情况,无需再执行,进入下一循环
            continue;
        }
            //定义一个用来比较的节点指针compare
            //每次比完都会返回头部
        struct ListNode* compare=dummyhead;
            //因为dummyhead->next=head,dummyhead的next才是head
            //这里用compare->next,这样就指向首位的节点了
            //如果指针所指的值比待排序的值小,那就继续往下走
            //直到compare->next的值比node的的值大
        while(compare->next->val<node->val) compare=compare->next;
            //下面就是接线操作了
            //尾节点tail的本来是指node的
            //为了把node挪出来,tail指向node的下一节点node->next,防止丢失
        tail->next=node->next;
            //node->next不用指向原本的下一节点了
            //此时compare->next指向的是比node大的数,所以node开始认compare->next做老大哥
            //node->next接上了老大哥compare->next,和原本的位置撇清了关系
        node->next=compare->next;
            //比node小的compare地位迅速降低,泪目
            //只能乖乖接上老二哥node,也只敢通过node和原本的大哥compare->next联系
            //如此一来,node就成功混进两者之间
        compare->next=node;

            //node掌握别的值,又开始新一轮的接线操作,一场腥风血雨又在酝酿(可以出本书了)
        node=tail->next;
    }
        //dummyHead链表的表头,dummyHead->next会指向链表的第一个节点
    return dummyhead->next;
}


如有错误,还望指正,十分感谢!


    走了点弯路,看了一些大佬的代码,就很很顺了,最大的收获是对链表更熟悉了,有空写个链表相关的项目巩固一下

题目来源:
力扣(LeetCode)
题目链接:
https://leetcode-cn.com/problems/insertion-sort-list

猜你喜欢

转载自blog.csdn.net/qq_49868778/article/details/113527107