1.描述
用插入排序对链表排序
样例
Given 1->3->2->0->null
, return 0->1->2->3->null
2.分析
插入排序是十分常见的排序方式之一,类似于数组的插入排序,此题是关于链表的插入排序。
原题给定一个以head为头节点的链表,下面再新建一个有序的dummy链表,通过把head链表
中的节点分别插入到dummy链表中完成对head链表的排序。思路为在有序链表中依次向下查找
和原链表中的值比较,当有序链表的值比原链表的值大时,把该值插入到有序链表中。举个例子如
有序链表中有1、3,原链表中为2。1和2先做比较,1小于2,继续向下查找,3比2大,此时把原链表
中的2插入到1、3之间最终得到有序链表1、2、3。
在有序链表中依次向下查找通过node=node->next完成指针向后移,之后的具体分析我在重要代码
后面都加了注释。下面的dummy链表为新建的有序链表,head链表为原链表。为了能够返回有序链表,
dummy链表的头节点dummy我没有动,而另外定义了一个node指针,而head链表中不需要返回原链表,
故直接用head作为指针依次往下移动(若还想要返回head指针需把头节点保存下来),node指针为
dummy链表里不断向下移动的指针,head指针为head链表里不断向下移动的指针。
3.代码
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The first node of linked list.
* @return: The head of linked list.
*/
ListNode *insertionSortList(ListNode *head) {
// write your code here
ListNode *dummy=new ListNode(0);
while(head!=NULL)
{
ListNode *node=dummy;
while(node->next!=NULL && node->next->val<head->val)
{
node=node->next;/*node指针后移一位,直到找到一个比head链表里的数大的,
把这个数添加到dummy链表里*/
}
ListNode *temp=head->next;/*以head为原链表里的指针依次向下查找,跳出while循环时
查到的这个head比node.next大*/
head->next=node->next;//把head插入node.next前
node->next=head;//把head插入到node后,完成head插入到node和node.next之间
head=temp;//原head.next成为新的head继续循环查找
}
return dummy->next;
}
};
4.总结
在对链表做操作时有一个很大的特点,就是head->next的变化一定要最后做。因为给定head节点时
head->next随机确定下来,head->next就是下一个节点,然而如果过早改变这个节点就找不到了,如
红字部分代码也是先把head->next存到temp中,之后做过一系列操作后head->next的地址已经改变,
但temp把原来head的下一个节点保留了下来。
同时,单链表是有next支撑的,当插入新元素时,如把2插入到1和3之中,原有的关系是1->next=3;
插入后变为1->next=2,2->next=3,是斩断之前两个节点之间关系的基础上建立新的两个关系。