---
tags: Coding
---
# 分治
## qsort (快速排序) 原理
### [參考文章出處](http://alrightchiu.github.io/SecondRound/comparison-sort-quick-sortkuai-su-pai-xu-fa.html)
**分治的精神: 把大問題拆成小問題**
要排序我們可以隨便選一個數字,然後把陣列左右分成小於這個數的部分放左邊,與大於這個數的不分放右邊。我們再從左部分做同樣的事,右部分也做同樣的事。
**分堆的方法:**
為了方便我們取最後一個數當作基準點。然後設立兩個變數i、j。j負責查看第一個到倒數第二個數有沒有小於最後一個數(基準點)。i先設成第一個數-1(front-1)。j從第一個看,每當有數字小於基準點就i++然後array[i]與array[j]交換。最後j都看完全部數後array[i]與array[end](基準點)交換數值。此時i就是基準點的位置。
**因此我們可以歸納出:**
分堆(partition)=>1.比中數小的左堆分堆 2.比中數大的右堆分堆
直到剩下一個數不能分就停止回去執行別的遞迴
![](https://raw.githubusercontent.com/alrightchiu/SecondRound/master/content/Algorithms%20and%20Data%20Structures/Sorting%20series/ComparisonSort_fig/QuickSort/f13.png =400x)
```cpp=
#include<bits/stdc++.h>
using namespace std;
void PrintArray(int *a,int n){
for(int i=0;i<n;i++)cout<<a[i]<<" ";
cout<<endl;
}
int Partition(int *a,int f,int e){//front and end
int i=f-1;
for(int j=f;j<e;j++){
if(a[j]<a[e]){
i++;
swap(a[j],a[i]);
}
}
i++;
swap(a[e],a[i]);
PrintArray(a,8);/
return i;
}
/*
int last;
int Partition(int *a,int f,int e){//front and end
last = a[e];
partition(a+f,a+e,[](int k){ return k<last;});
int i=partition_point(a+f,a+e,[](int k){ return k<last;})-a;
swap(a[e],a[i]);
return p;
}*/
//用c++的partition函示一樣可以達到同樣效果
void Quick_sort(int *a,int f,int e){//front and end
if(f<e){
int pivot=Partition(a,f,e);
Quick_sort(a,f,pivot-1);
Quick_sort(a,pivot+1,e);
}
}
signed main () {
int arr[]={8,4,5,6,3,7,2,1};
int n=sizeof(arr)/sizeof(int);
cout<<"before: ";
PrintArray(arr,n);
Quick_sort(arr,0,n-1);
cout<<"after: ";
PrintArray(arr,n);
return 0;
}
```
## Merge Sort 原理
### [參考文章出處](http://alrightchiu.github.io/SecondRound/comparison-sort-merge-sorthe-bing-pai-xu-fa.html)
**分治:**
我們把陣列一直對半分開直到不能續切為止。接著我們再把每一小堆依照順序大小組合,從最小堆的慢慢組合到本的長度。
**組合 Merge:**
主要目地把左推(left)與右推(right)組合在一起,但要注意的是左堆與右堆都要已經被排序好了。這部分用vector實做比較方便,首先先在複製一個左右堆,並在最後都放入無限大的數字保證不會有數字超過無限大,像是INT_MAX。接著i代表左堆中的位置,j代表右堆中的位置,兩個初始值都是0。然後我們比較left[i]與right[j]的大小。誰比較小就放入陣列中,小的那個i或j就+1,表示看到下一個數,最後比到left[i]跟right[j]都是最後一個數INT_MAX。
**簡單來說:**
就是分分分分分到不能分 再合合合合合到原本的大小
![](https://github.com/alrightchiu/SecondRound/blob/master/content/Algorithms%20and%20Data%20Structures/Sorting%20series/ComparisonSort_fig/MergeSort/f1.png?raw=true =400x)
```cpp=
#include<bits/stdc++.h>
using namespace std;
void PrintArray(int *a,int n){
for(int i=0;i<n;i++)cout<<a[i]<<" ";
cout<<endl;
return;
}
void Merge(int *a,int f,int e,int mid){
vector<int>Left(a+f,a+mid+1);
vector<int>Right(a+mid+1,a+e+1);
Left.push_back(INT_MAX);
Right.push_back(INT_MAX);
int left_idx=0,right_idx=0;
for(int i=f;i<=e;i++){
if(Left[left_idx]<=Right[right_idx]){
a[i]=Left[left_idx];
left_idx++;
}else if(Left[left_idx]>Right[right_idx]){
a[i]=Right[right_idx];
right_idx++;
}
}
//PrintArray(a,8);看看過程(除錯用)
return;
}
void Merge_sort(int *a,int f,int e){
int mid=(f+e)/2;
if(f<e){
Merge_sort(a,f,mid);
Merge_sort(a,mid+1,e);
Merge(a,f,e,mid);
}
return;
}
signed main () {
int arr[]={8,2,5,1,3,7,6,4};
int n=sizeof(arr)/sizeof(int);
cout<<"before: ";
PrintArray(arr,n);
Merge_sort(arr,0,n-1);
cout<<"after: ";
PrintArray(arr,n);
return 0;
}
```