对链表进行插入排序。
插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。
插入排序算法:
- 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
- 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
- 重复直到所有输入数据插入完为止。
示例 1:
输入: 4->2->1->3 输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0 输出: -1->0->3->4->5
思路:
这道题要求用插入排序的思想对单向链表进行排序,则我们可以构建一个新链表,每次从新链表头结点向后判断应该插入哪个节点,新链表的每个节点插入后都保证有序,如图所示:
红色表示带插入节点,我们首先初始化静态头结点pre_new_head,并且new_head_tmp=pre_new_head,然后比较:
while (new_head_tmp->next && new_head_tmp->next->val <= cur->val)
不断更新new_head_tmp,则最后带插入节点便在new_head_tmp和new_head_tmp->next之间。
这里有个小技巧:不用每次判断都把new_head_tmp=pre_new_head,因为每次节点插入,new_head_tmp总是指向最后一个元素,如下图所示:
若此时带插入的节点是6,则直接插在new_head_tmp后面即可,即我们只有在new_head_tmp->next->val>cur->val时才把new_head_tmp赋值为pre_new_head
if (new_head_tmp->next && new_head_tmp->next->val > cur->val) {
new_head_tmp = pre_new_head;
}
代码如下:
ListNode* insertionSortList(ListNode* head) {
ListNode* pre_new_head = new ListNode(-1);
ListNode* new_head_tmp = pre_new_head;
ListNode* cur = head;
ListNode* pre_cur = cur;
while (cur) {
pre_cur = cur->next;
if (new_head_tmp->next && new_head_tmp->next->val > cur->val) {
new_head_tmp = pre_new_head;
}
while (new_head_tmp->next && new_head_tmp->next->val <= cur->val) {
new_head_tmp = new_head_tmp->next;
}
cur->next = new_head_tmp->next;
new_head_tmp->next = cur;
//new_head_tmp = pre_new_head;
cur = pre_cur;
}
return pre_new_head->next;
}