【编程4】插入排序+快速排序+LeetCode.148(排序链表)
文章目錄
- 一、排序鏈表
- 1、題目描述——LeetCode.148
- 2、分析
- (1)一般的快排
- (2)解題思路
- 3、實現(xiàn)
- 二、排序算法
- 三、插入排序
- 1、基本思想
- (1)過程概述
- (2)具體算法描述:
- 2、示例
- 3、實現(xiàn)
- 4、分析
- (1)原地排序算法
- (2)穩(wěn)定排序算法
- (3)時間復雜度
- 四、快速排序
- 1、基本思想
- (1)快速排序的流程
- 2、實現(xiàn)
- 3、性能分析
一、排序鏈表
1、題目描述——LeetCode.148
在 O(n logn) 時間復雜度和常數(shù)級空間復雜度下,對鏈表進行排序。
示例 1:
輸入: 4->2->1->3
輸出: 1->2->3->4
示例 2:
輸入: -1->5->3->4->0
輸出: -1->0->3->4->5
2、分析
本實現(xiàn)采用快速排序算法實現(xiàn)
(1)一般的快排
需要一個指針指向頭,一個指針指向尾,然后兩個指針相向運動并按一定規(guī)律交換值,最后找到一個支點使得支點左邊小于支點,支點右邊大于支點
==》如果是這樣的話,對于單鏈表我們沒有前驅指針,怎么能使得后面的那個指針往前移動呢?
==》使兩個指針都往next方向移動并且能找到支點那就好了。
(2)解題思路
只需要兩個指針p和q,這兩個指針均往next方向移動,移動的過程中保持p之前的key都小于選定的key,p和q之間的key都大于選定的key,那么當q走到末尾的時候便完成了一次支點的尋找。
3、實現(xiàn)
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:ListNode* sortList(ListNode* head) {if(head == NULL)return NULL;ListNode *right = head;while(right->next)right = right->next;QuickSort(head, right);return head;} private:void QuickSort(ListNode *left, ListNode *right){if(left != right){ListNode *partion = GetPartion(left, right);QuickSort(left, partion);if(partion->next)QuickSort(partion->next, right);}}ListNode *GetPartion(ListNode *left, ListNode *right){int key = left->val;ListNode *p = left;ListNode *q = p->next;while(q != right->next){if(q->val < key){p = p->next;swap(p->val, q->val);}q = q->next;}swap(p->val, left->val);return p;} };二、排序算法
| 1 | 冒泡、插入、選擇 | O(n2) | √ | 適合小規(guī)模數(shù)據(jù)排序 |
| 2 | 快排、歸并 | O(nlogn) | √ | 適合大規(guī)模的數(shù)據(jù)排序 |
| 3 | 桶、計數(shù)、基數(shù) | O(n) | × |
三、插入排序
1、基本思想
將一個記錄插入到已經(jīng)排好序的有序表中,從而得到一個新的、記錄數(shù)增1的有序表。
(1)過程概述
插入排序在實現(xiàn)上,通常采用in-place排序(即只需用到O(1)的額外空間的排序),因而在從后向前掃描過程中,需要反復把已排序元素逐步向后挪位,為最新元素提供插入空間。
(2)具體算法描述:
① 從第一個元素開始,該元素可以認為已經(jīng)被排序;
② 取出下一個元素,在已經(jīng)排序的元素序列中從后向前掃描;
③ 如果該元素(已排序)大于新元素,將該元素移到下一位置;
④ 重復步驟 ③,直到找到已排序的元素小于或者等于新元素的位置;
⑤ 將新元素插入到該位置后
⑥ 重復步驟②~⑤
2、示例
原數(shù)據(jù):{4,5,6,1,3,2}
排序過程:其中左側是已排序區(qū)間,右側是未排序區(qū)間。
3、實現(xiàn)
void insertSort(int a[], int len){int tmp, j;for(int i = 1; i < len; i++){tmp = a[i];int j = i - 1;while(tmp < a[j]){a[j + 1] = a[j];j--;}a[j + 1] = tmp;} }4、分析
(1)原地排序算法
- 空間復雜度為 O(1)
==》原地排序算法
(2)穩(wěn)定排序算法
- 對于值相同的元素,可以選擇將后面出現(xiàn)的元素,插入到前面出現(xiàn)元素的后面。
==》保持原有前后順序,也就是穩(wěn)定的排序算法
(3)時間復雜度
- 最好情況時間復雜度(數(shù)據(jù)已經(jīng)有序):O(n)
- 最壞情況時間復雜度:O(n2)
- 平均時間復雜度:O(n2)
- 對于插入排序來說,每次插入操作(時間復雜度為O(n))都相當于在數(shù)組中插入一個數(shù)據(jù),循環(huán)執(zhí)行 n 次插入操作
四、快速排序
1、基本思想
基于分治思想,快速排序算法:選擇一個基準數(shù),通過一趟排序將要排序的數(shù)據(jù)分割成獨立的兩部分;其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小。然后,再按此方法對這兩部分數(shù)據(jù)分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數(shù)據(jù)變成有序序列。
(1)快速排序的流程
① 從數(shù)列中挑出一個基準值(樞軸,pivot)。
② 將數(shù)組進行劃分(partition),將比基準數(shù)大的元素都移至樞軸右邊,將小于等于基準數(shù)的元素都移至樞軸左邊。在這個分區(qū)退出之后,該基準就處于數(shù)列的中間位置。
③ 遞歸地把"基準值前面的子數(shù)列"和"基準值后面的子數(shù)列"進行排序。
2、實現(xiàn)
- 實現(xiàn)一
將第一個元素設置為基準值來劃分區(qū)間,基準值的位置始終不變,最后交換使得基準值的位置。
- 實現(xiàn)二
將第一個元素設置為基準值來劃分區(qū)間,將基準值不斷與沖突值進行換位。
3、性能分析
- 不穩(wěn)定
- 原地排序——空間復雜度為O(1)
- 時間復雜度:大部分情況下的時間復雜度都可以做到 O(nlogn),只有在極端情況下,才會退化到 O(n2)。
總結
以上是生活随笔為你收集整理的【编程4】插入排序+快速排序+LeetCode.148(排序链表)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【编程3】二叉树遍历(LeetCode.
- 下一篇: C++笔记1