147.对链表进行插入排序

1.题目介绍

给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。

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

下面是插入排序算法的一个图形示例。部分排序的列表(黑色)最初只包含列表中的第一个元素。每次迭代时,从输入数据中删除一个元素(红色),并就地插入已排序的列表中。
对链表进行插入排序。

示例 1:

输入: head = [4,2,1,3]
输出: [1,2,3,4]

示例 2:

输入: head = [-1,5,3,4,0]
输出: [-1,0,3,4,5]

2.题解

2.1 插入排序

思路

首先要理解插入排序,冒泡排序,选择排序的区别,这里请移步排序算法
插入排序总之就是维护一个有序数列,每次从数列外部取一个进入数列,同时完成排序。

对于链表也是一样,不过要维护的是指针,来区分有序数列和待排序数列。
这里我们维护一个lastSorted作为有序数列的尾结点,curr指向第一个待排序的数,即lastSorted->next
这里有两种情况:1.待排序的数就是最大的,直接lastSorted=lastSorted->next;即可
2.有序数列中有比待排序数更大的,这时候就要遍历有序链表,查看插入位置
遍历途中使用一个指针pre,通过判断pre->next->val是否大于curr->val,判断具体插入位置,链表插入就是三指针插入法即可
这里dummyHead很好的维护了头节点的位置,因为由于不断地插入排序,实际的头节点是在不断地变化的,有着dummyHead这个虚拟头结点,能帮我们很快定位头结点。

代码

/**
 * 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:
    ListNode* insertionSortList(ListNode* head) {
        if (head == nullptr)
            return head;
        ListNode* dummyHead = new ListNode(0,head);
        ListNode* lastNode = head;
        ListNode* curr = head->next; 
        while(curr != nullptr){
        	if (lastNode->val <= curr->val) lastNode = lastNode->next;
        	else{
        		ListNode* pre= dummyhead;
        		while(pre->next->val <= curr->val) pre = pre->next;
        		lastNode->next = curr->next;
        		curr->next = pre->next;
        		pre->next = curr;
			}
			curr = lastNode->next;
		}	
		ListNode* ans = dummyHead->next;
		delete dummyHead;
		return ans;
    }
};
posted @ 2024-01-18 20:21  DawnTraveler  阅读(30)  评论(0编辑  收藏  举报