二、 歸併排序
遞迴+分治的思維
(分治)
確定分界點 (我們下面以中間值q[l+r >> 1] 為分界點, 理論上任何點作為分界點都可)
調整區間: <= x 的在左邊, >= x的在右邊(兩個區間)
遞迴: 遞迴處理左右兩段
原題鏈結
題目描述
給定你乙個長度為n的整數數列。
請你使用快速排序對這個數列按照從小到大進行排序。
並將排好序的數列按順序輸出。
輸入格式
輸入共兩行,第一行包含整數 n。
第二行包含 n 個整數(所有整數均在1~109範圍內),表示整個數列。
輸出格式
輸出共一行,包含 n 個整數,表示排好序的數列。
資料範圍
1≤n≤100000
#include
#include
using namespace std;
const
int n =
100010
;int n;
int a[n]
;void
quick_sort
(int l,
int r)
quick_sort
(l, j)
;quick_sort
(j +
1, r);}
intmain
(void
)
題目鏈結
題目描述:
給定乙個長度為n的整數數列,以及乙個整數k,請用快速選擇演算法求出數列從小到大排序後的第k個數。
輸入格式
第一行包含兩個整數 n 和 k。
第二行包含 n 個整數(所有整數均在1~109範圍內),表示整數數列。
輸出格式
輸出乙個整數,表示數列的第k小數。
#include
#include
using namespace std;
const
int n =
100010
;int n, k;
int a[n]
;void
quick_sort
(int l ,
int r)
if(j >= k)
quick_sort
(l, j)
;else
quick_sort
(j +
1, r);}
intmain
(void
)
補充: 若陣列並非全域性變數,快排函式需要傳入引數+1
//不是全域性變數時
void
quick
(int arr,
int l,
int r)
//有遞迴的終點,沒有其他特殊需求的情況下不需要有條件的遞迴。
quick
(arr, l, j)
;//排左
quick
(arr, j +
1, r)
;//排右
}
確定分界點,以整個陣列的中間為分界點(下標中間值),分為左邊,右邊mid = (l + r) / 2
兩區間
遞迴排序[l, mid] [mid + 1, r]
兩區間
歸併—合二為一,兩個有序的序列合成乙個有序序列
題目鏈結
題目描述:
給定你乙個長度為n的整數數列。
請你使用歸併排序對這個數列按照從小到大進行排序。
並將排好序的數列按順序輸出。
輸入格式
輸入共兩行,第一行包含整數 n。
第二行包含 n 個整數(所有整數均在1~109範圍內),表示整個數列。
輸出格式
輸出共一行,包含 n 個整數,表示排好序的數列。
#include
#include
using namespace std;
const
int n =
100010
;int n;
int a[n]
, tmp[n]
;void
merge_sort
(int l,
int r)
while
(i <= mid) tmp[k ++
]= a[i ++];
while
(j <= r) tmp[k ++
]= a[j ++];
//把輔助陣列中的值複製回到原陣列中
for(
int i = l, j =
0; i <= r; i ++
, j ++
) a[i]
= tmp[j];}
intmain
(void
)
題目鏈結
題目描述:
給定乙個長度為n的整數數列,請你計算數列中的逆序對的數量。
逆序對的定義如下:對於數列的第 i 個和第 j 個元素,如果滿足 i < j 且 a[i] > a[j],則其為乙個逆序對;否則不是。
輸入格式
第一行包含整數n,表示數列的長度。
第二行包含 n 個整數,表示整個數列。
輸出格式
輸出乙個整數,表示逆序對的個數。
1≤n≤100000
講所有逆序對分為三大類:
兩數同時出現在左半邊: merge_sort(l, mid);
兩數同時出現在右半邊: merge_sort(mid + 1, r);
一左一右:sj = r - mid + 1
可以思考歸併過程,第二個序列的下標為j 的值填充時, 第乙個序列此時指向的下標為 i, 那麼 第乙個序列中 i – mid 一定大於 第二個序列中下標為 j 的數 ,
當我們不斷劃分成小區間時,我們就把1,2兩種情況化成第三種情況了。
乙個小細節
當原陣列為降序時,此時逆序對數量最多
第乙個數: n - 1個 逆序對
第二個數: n - 2個
…… 1 個
相加時,n(n - 1) / 2
個 大概 n ^ 2 / 2; 5 * 10 ^ 9 > int
#include
#include
using namespace std;
typedef
long
long ll;
ll sum;
const
int n =
100010
;int n;
int a[n]
, tmp[n]
;long
long
merge_sort
(int l,
int r)
}while
(i <= mid) tmp[k ++
]= a[i ++];
while
(j <= r) tmp[k ++
]= a[j ++];
for(
int i = l, j =
0; i <= r; i ++
, j ++
) a[i]
= tmp[j]
;return res;
}int
main()
快排和歸併排序講解
快速排序 歸併排序 找陣列的最後乙個數字,假設為number,然後number為標準,調整陣列 陣列左邊是小於number的數,中間是等於number的數,右邊是大於number的數,然後對小於number的部分繼續進行上述操作,對大於number的部分繼續進行上述操作。這是普通的快速排序,和資料的...
演算法 歸併排序與快排
歸併排序是另一種不同的排序方法,因為歸併排序使用了遞迴分治的思想,所以理解起來比較容易。其基本思想是,先遞迴劃分子問題,然後合併結果。把待排序列看成由兩個有序的子串行,然後合併兩個子串行,然後把子序列看成由兩個有序序列。倒著來看,其實就是先兩兩合併,然後四四合併。最終形成有序序列。空間複雜度為o n...
單鏈表排序 快排 歸併排序
題目描述 給定乙個亂序的單鏈表的頭節點,對該鍊錶中的節點進行排序 要求時間複雜度為o nlgn 空間複雜度為o 1 分析 由於題目要求時間複雜度我o nlgn 因此選擇排序和插入排序可以排除。在排序演算法中,時間複雜度為o nlgn 的主要有 歸併排序 快速排序 堆排序。其中堆排序的空間複雜度為 n...