题目描述:
插入排序的动画演示如上。从第一个元素开始,该链表可以被认为已经部分排序(用黑色表示)。
每次迭代时,从输入数据中移除一个元素(用红色表示),并原地将其插入到已排好序的链表中。
插入排序算法:
-
插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。
-
每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。
-
重复直到所有输入数据插入完为止。
题目分析:
从链表头部开始遍历,记录当前要插入排序的节点和其上一个节点,对每个节点执行如下操作:
1.从头部开始找到当前节点之前第一个不大于它的节点,记录找到的节点以及它前一个节点;
2.如果它前一个节点为空,说明要插入到头节点之前,若不为空,则插入到该节点之后;
3.继续进行下一次插入排序,直到遍历到链表尾部。
按照题目分析,该算法的时间复杂度是O(n^2)。依次获取链表中的节点进行插入,插入的时候,在已排序的前半部分链表中确定位置,最终完成整个链表的排序过程。
1.特殊情况:空链表和单个节点的直接返回head;
2.为了方便在头节点之前进行插入,我们在头节点之前插入一个无效的节点,并将这个节点的值赋值为INT_MIN;
3.定义指针p指向当前准备插入的节点,当p不等于NULL的时候,执行循环,否则插入完毕,跳出程序。同时定义一个rear指针,指向已经排序部分的最后。每次循环,将p赋值为rear的next。
4.内层循环利用temp指针确定应该插入的位置,当temp的值比P的值大的时候退出内层循环,那么退出后会出现2种情况:
5.待插入的节点值比rear的值小,那么P插入到temp之前,rear指针不移动;
6.待插入的节点值比rear的值大,那么P插入到temp之后,P的next赋值为rear的next,rear指针移动到P;
7.最后返回head的next为排序后的链表。
C++实现:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 11 public: 12 ListNode* insertionSortList(ListNode* head) { 13 14 if(head==NULL||head->next==NULL) return head; 15 ListNode* newhead = new ListNode(INT_MIN); 16 newhead->next = head; 17 head = newhead; 18 ListNode *rear = head->next;//有序链表最后一个节点 19 ListNode *p = rear->next;//待排序插入节点 20 while(p!=NULL){ 21 //将p节点移除 22 rear->next = p->next; 23 p->next = NULL; 24 //确定位置 25 ListNode *pre = head;//保存插入位置的前一个节点 26 ListNode *temp = head->next; 27 while(temp->val <= p->val && temp != rear){ 28 pre = temp; 29 temp = temp->next; 30 } 31 if(temp->val > p->val){ 32 p->next = temp; 33 pre->next = p; 34 }else{ 35 p->next = temp->next; 36 temp->next = p; 37 rear = p; 38 } 39 p = rear->next; 40 } 41 return head->next; 42 43 } 44 };
- 还没有人评论,欢迎说说您的想法!