16.链表的插入排序(链表头插+中间插入+尾部插入)

对链表进行插入排序 试试这题

插入排序算法:

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

示例 1:

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

示例 2:

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

整体思路:我们就按照插入排序的基本思想,先拿出一个结点当做头结点,然后后面每次都拿出一个结点跟前面的结点的val比较,如果val更大则进行尾插,若val较小,则进行中间插入或者头插,但是每种插入方式都有所不同,头插要注意head头指针的改变,中间插入要注意用三个指针配合使用,尾插要注意最后尾指针要指向NULL。

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    typedef ListNode Node;
    ListNode* insertionSortList(ListNode* head) {
        if(head == NULL || head->next == NULL)
            return head;
        //取下第一个结点当做新链表的头结点
        Node* newhead = head;
        head = head->next;
        newhead->next = NULL;//记得要置空

        //1.将每个节点取下比对val大小
        Node* cur = head;
        while(cur)
        {
            Node* next = cur->next;
            if(newhead->val >= cur->val)
            {
                //头插
                cur->next = newhead;
                newhead = cur;
            }
            else
            {
                //尾插或者中间插入
                //用连个指针遍历链表,比较链表元素的大小
                //如果>sortcur的val,sortcur就向后移动,如果<=sortcur的val(中间插入)或者NULL(尾插)就在sortcur前面插入该元素
                Node* sortcur = newhead->next;
                Node* sortprev = newhead;
                if(sortcur == NULL)
                {
                    sortprev->next = cur;
                    cur->next = NULL;
                    cur = next;
                    continue;
                }
                while(sortcur->val < cur->val)
                {
                    if(sortcur->next == NULL)//尾插
                    {
                        sortcur->next = cur;
                        cur->next = NULL;
                        break;
                    }
                    sortcur = sortcur->next;
                    sortprev = sortprev->next;
                }
                //中间插入
                if(sortcur->val >= cur->val )
                {
                    sortprev->next = cur;
                    cur->next = sortcur; 
                }
            }
            cur = next;
        }
        return newhead;
    }
};

这种方法是头插然后尾插最后中间插

还有一种:可以头插然后中间插最后尾插
新加的注释会用###标注

 /**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode Node;
struct ListNode* insertionSortList(struct ListNode* head){
        if(head == NULL || head->next == NULL)
            return head;
        //取下第一个结点当做新链表的头结点
        Node* newhead = head;
        Node* cur = head->next;//###从第二个结点取下来接在链表的后面
        newhead->next = NULL;//记得要置空

        //1.将每个节点取下比对val大小
        while(cur)
        {
            Node* next = cur->next;//###/先保留next后面的指针
            if(newhead->val >= cur->val)
            {
                //头插
                cur->next = newhead;
                newhead = cur;
            }
            else
            {
                //尾插或者中间插入
                //用连个指针遍历链表,比较链表元素的大小
                //如果>sortcur的val,sortcur就向后移动,
                //如果<=sortcur的val(中间插入)或者NULL(尾插)就在sortcur前面插入该元素
                Node* sortcur = newhead->next;
                Node* sortprev = newhead;

				//###让sortcur指针遍历链表一遍,一一比大小
                while(sortcur)//###中间插入
                {
                    if(cur->val <= sortcur->val)
                    {
                        sortprev->next = cur;
                        cur->next = sortcur;
                        break;
                    }
                    else
                    {
                        sortprev = sortcur;
                        sortcur = sortcur->next;
                    }
                }
                //###如果跳出来了,则就除了break掉的情况外,就是尾插的情况了,
                //###这样就比上面一种方法少一次判断
                //###尾插
                if(sortcur == NULL)
                {
                    sortprev->next = cur;
                    cur->next = NULL;
                }
            }
            cur = next;//###循环迭代回去
        }
        return newhead;
}

其实第二种更符合清晰的思维逻辑,头插,中间插,尾插,一种一种情况的考虑

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hyzhang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值