按照数组插入排序的思路,需要把数组分成以排序和未排序的两部分:
每次从未排序的数组中拿出一个插入已排序的数组中,指到未排序数组未空。在插入的过程中涉及到数组的遍历查找,而数组是可以按下标从后向前遍历的:
void InsertSort(int a[], int n)
{
for(int i=1;i<n;i++)
{
int value=a[i];
int index=i-1;
while(index>=0&&a[index]>value)
{
a[index+1]=a[index];
index--;
}
a[index+1]=value;
}
}
但单链表只能单向顺序遍历,因此必须用两个指针来分别遍历有序链表和未排序链表,因此必须先构建一个新链表作为有序链表最终返回:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if(head==NULL || head->next == NULL)
return head;
//创造一个新的链表头部
ListNode* pre = new ListNode(-1);
//用一个临时变量保存头节点
ListNode* ans = pre;
//cur是原链表上的指针
ListNode* cur = head;
while (cur != NULL) {
//每次循环前重置pre为头结点,这样保证每次都从头往后遍历
pre = ans;
//当pre.next.val大于cur.val时停止循环
while (pre->next != NULL && pre->next->val < cur->val) {
pre = pre->next;
}
//pre->next->val 大于 cur->val,此时应该把cur插入到pre后
//保存原链表当前节点的下一节点
ListNode* tmp = cur->next;
//把cur插入到pre之后
cur->next = pre->next;
pre->next = cur;
//cur指针后移一位
cur = tmp;
}
return ans->next;
}
};
发现上面的head赋值给cur 之后就再也没用用过,所以干脆直接用head来遍历未排序数组:
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if(head==NULL || head->next == NULL)
return head;
ListNode* ans = new ListNode(-1);
while (head != NULL) {
ListNode* tmp= head->next;
ListNode* cur= ans;
while (cur->next != NULL && cur->next->val < head->val) {
cur = cur->next;
}
head->next = cur->next;
cur->next = head;
head = tmp;
}
return ans->next;
}
};