147.对链表进行插入排序

题目:见下图

答案:见下图

typedef struct ListNode ListNode;
 struct ListNode {
     int val;
     struct ListNode *next;
 };
 
struct ListNode* insertionSortList(struct ListNode* head) {
    //链表为空或者链表长度为一时不用排序,直接返回head
    if (head == NULL || head->next == NULL)
    {
        return head;
    }
    ListNode* cur = head->next;
    ListNode* sortNode = head;
    sortNode->next = NULL; 
    while (cur)
    {
        ListNode* next = cur->next;

        if (cur->val <= sortNode->val)
        {
            //仅适用于头插
            //head  1 3 5 4 3   tail
            cur->next = sortNode;
            sortNode = cur;

        }
        else//中间插入
        {
            ListNode* sortPrve = sortNode;
            ListNode* sortCur = sortNode->next;
            while (sortCur)
            {
                if (cur->val <= sortCur->val)
                {
                    sortPrve->next = cur;
                    cur->next = sortCur; 
                    break;
                }
                else
                {
                    sortPrve = sortCur;
                    sortCur = sortCur->next;                   
                }
            }  
            //此时一定是尾插
            if (sortCur == NULL)
            {
                sortPrve->next = cur;
                cur->next = NULL;
            }
        }
        cur = next;
        
    }

    return sortNode;
}

解析:

(1)判断链表长度


    由题目我们可以简便得知链表为空或者链表长度为一时不用排序,直接返回head,那么有
    if (head == NULL || head->next == NULL)
    {
        return head;
    }

(2)目标值小于等于排序值时我们可以进行头插

这里我们定义cur和sortNode来分别表示当前值与排序值,下图代码适用判断目标值小于等于排序链表的情况,若成立那么便将目标链表链到排序链表的前面(头上),若不满足判断条件那么不执行该条语句

注:一旦进行头插那么排序链表的头系欸但就改变了,这里不要忘记将cur赋予sortNode,以便更好的找到排序链表的头节点并且返回


    ListNode* cur = head->next;
    ListNode* sortNode = head;
    sortNode->next = NULL; 
    while (cur)
    {
        ListNode* next = cur->next;

        if (cur->val <= sortNode->val)
        {
            //仅适用于头插
            //head  1 3 5 4 3   tail
            cur->next = sortNode;
            sortNode = cur;

        }

(3)目标值小于等于排序链表的头结点的next值的val可以进行中间插

由于(2)已经进行判断了头插情况那么仅余下中间插或则尾插,中间插的优先级大部分情况要大于尾插,那么这里我们优先书写中间插

这里我们可以定义两个变量分别表示排序链表的头节点与第二个结点,以便中间结点的插入

1.如果满足目标值小于排序链表的头结点的next的val那么则进行中间插,一旦中间插入成功那么我们为了防止继续进行循环进而导致数值混乱,可以采用break语句跳出循环

2.代码如下,如果不满足则采用将排序链表中的两个指针分别向后移一位,来继续进行判断,直到sortCur指针为空


        else//中间插入
        {
            ListNode* sortPrve = sortNode;
            ListNode* sortCur = sortNode->next;
            while (sortCur)
            {
                if (cur->val <= sortCur->val)
                {
                    sortPrve->next = cur;
                    cur->next = sortCur; 
                    break;
                }
                else
                {
                    sortPrve = sortCur;
                    sortCur = sortCur->next;                   
                }
            }  

(4)目标值大于排序值时我们可以进行尾插

当进行此步if语句仍未结束,那么就证明还有尾插或则不执行尚未执行,如下图,由图得知此时sortCur的值为NULL,那么我们恰好可以利用这个条件来进行判断是否需要进行尾插


            //此时一定是尾插
            if (sortCur == NULL)
            {
                sortPrve->next = cur;
                cur->next = NULL;
            }
        }
        cur = next;
        
    }

(5)返回排序链表的头节点

    return sortNode;

到这里我们解题完毕

如果对您有帮助的话点一个免费的赞和收藏叭!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值