歸併排序與快速排序的一個實現與理解
自己實現的一個快速排序和歸併排序,並且用註釋的方式寫下了自己的理解。算是做一個筆記
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
//先寫歸併排序,下面這兩個函式都可以可以通過傳入回撥函式來定製排序規則
//歸併這個過程裡面兩個陣列的索引起始位置和終止位置很重要,要有正確理解
//放在temp的時候也是從low開始的,因為在排序就是對[low,high]這個閉區間
//來排序的,用到的就是兩個陣列的這個區間的位置
//下面這個merge過程看起來更簡潔,可是理解起來可能有一點難度
void merge(int *nums, int low, int mid, int high, int *temp)
{
//假設[low, mid]和[mid+1, high]兩個閉區間分別是有序的
int s = low, t = mid + 1;
for(int i = low; i <= high; ++i)
{
if(s > mid) //假設這個分支為真,那麼說明i未越界,也即兩部分沒有歸併完,但是前一半沒資料了
//那就能說明只有後半部分是還有資料的,對應於下面那個複雜的歸併過程的第三個迴圈
temp[i] = nums[t++];
else if(t > high)
temp[i] = nums[s++];
else if(nums[s] <= nums[t])
temp[i] = nums[s++];
else
temp[i] = nums[t++];
}
//理解了前兩個判斷分支,那麼上面這個歸併過程就沒有那麼難理解了。
for(int i = low; i <= high; ++i)
{
nums[i] = temp[i];
}
}
void mergeTemp(int *nums, int low, int mid, int high, int *temp)
{
//假設[low, mid]和[mid+1, high]兩個閉區間分別是有序的
int s = low, t = mid + 1, k = low;//這裡一定要注意k是從low開始的就行了
while(s <= mid && t <= high)
{
if(nums[s] <= nums[t])
{
temp[k++] = nums[s++];
}
else
{
temp[k++] = nums[t++];
}
}
while(s <= mid)
{
temp[k++] = nums[s++];
}
while(t <= high)
{
temp[k++] = nums[t++];
}
for(int i = low; i <= high; ++i)
{
nums[i] = temp[i];
}
}
//temp陣列在整個排序過程中每一個個位置僅僅在一次歸併過程中使用過
void mergeSort(int *nums, int low, int high, int *temp)
{
if(low >= high) //這裡可以寫一個插入排序或者其他的排序方法來加快速度
return;
int mid = low + (high - low) / 2;
mergeSort(nums, low, mid, temp);
mergeSort(nums, mid+1, high, temp);
merge(nums, low, mid, high, temp);
}
/****************************************************
* 上面是歸併排序,那麼這裡來實現一下快速排序
* 每一次僅僅只確定一個元素的位置,先對陣列做一個劃分,然後再
* 對陣列前一半排序,對前一半排序之後再對後一半做一個排序
*
****************************************************/
//這裡假設在使用快排之前已經對陣列做過隨機的打亂
//最好情況是每一次劃分的時候劃分結束時劃分元素都位於
//被劃分的那一部分的最中間部分
void Swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
void quickSort(int *nums, int low, int high)
{
if(low >= high) //當陣列只有一個元素的時候已經是有序的了,不需要再排序了。
return;
//先對陣列做一個劃分,使用第一個元素
int v = nums[low]; //v代表劃分元素
int i = low, j = high;//使用的是閉區間
while(i < j) //正是因為下面的這個已經很明白的原因,這裡的判斷條件不等取=,以為i==j的時候就該退出迴圈了
{ //這個迴圈的終止條件也是很好理解的,i左邊的全部都是小於等於nums[i]的,j
//右邊的全部都是大於等於nums[j]的,那麼當i==j,說明了上述兩個條件剛好全部
//都滿足,說明已經達到了預期的劃分效果了
while(nums[j] >= v && j > i) //內迴圈的後一個條件不能取等號,因為當取等號的時候還滿足的話,有可能會把v與前面比它小的元素交換
--j;
swap(nums[i], nums[j]); //把v換到j當前所在的位置,j原來指向的元素也到了它合適的位置
while(nums[i] <= v && i < j) //這裡第二個同樣不能取等號,
++i;
swap(nums[i], nums[j]);
}
//然後開始遞迴排序,這裡認為k這個位置的元素已經到達了它最終的位置。
quickSort(nums, low, i-1);
quickSort(nums, i+1, high);
}
/****************************************************
*
* 對上面兩個排序函式做一個測試,測試好就好
*
*
****************************************************/
int main()
{
srand((unsigned)time(NULL));
int test[20], temp[20];
for(int i = 0; i < 20; ++i)
{
test[i] = rand() % 200;
}
//mergeSort(test, 0, 19, temp);
quickSort(test, 0, 19);
for(int i = 0; i < 20; ++i)
{
cout << test[i] << " ";
}
cout << endl << endl;
return 0;
}
相關文章
- C++快速排序與歸併排序的實現(LeetCode 912)C++排序LeetCode
- php實現 歸併排序,快速排序PHP排序
- 氣泡排序、歸併排序與快速排序比較排序
- 快速排序&&歸併排序排序
- 四、歸併排序 && 快速排序排序
- 七、排序,選擇、冒泡、希爾、歸併、快速排序實現排序
- 直播系統原始碼,實現快速排序和歸併排序原始碼排序
- php插入排序,快速排序,歸併排序,堆排序PHP排序
- go 實現歸併排序Go排序
- 歸併排序的簡單理解排序
- 歸併排序MergeSort的C實現排序
- 使用 Swift 實現歸併排序Swift排序
- 利用遞迴實現連結串列的排序(歸併排序)遞迴排序
- ForkJoin和氣泡排序組合實現的歸併排序排序
- 歸併排序的非遞迴實現排序遞迴
- 利用java實現插入排序、歸併排序、快排和堆排序Java排序
- Python八大演算法的實現,插入排序、希爾排序、氣泡排序、快速排序、直接選擇排序、堆排序、歸併排序、基數排序。Python演算法排序
- 歸併排序排序
- Sort排序專題(7)歸併排序(MergeSort)(C++實現)排序C++
- 【Java資料結構與演算法】第八章 快速排序、歸併排序和基數排序Java資料結構演算法排序
- 演算法之常見排序演算法-氣泡排序、歸併排序、快速排序演算法排序
- 說說你對歸併排序的理解?如何實現?應用場景?排序
- 排序演算法__歸併排序排序演算法
- 排序演算法:歸併排序排序演算法
- 排序演算法 - 歸併排序排序演算法
- 排序演算法(歸併排序)排序演算法
- 歸併排序--排序演算法排序演算法
- 歸併排序--二路排序排序
- 歸併排序和基數排序排序
- 【資料結構與演算法】高階排序(希爾排序、歸併排序、快速排序)完整思路,並用程式碼封裝排序函式資料結構演算法排序封裝函式
- 資料結構與演算法——排序演算法-歸併排序資料結構演算法排序
- java歸併排序Java排序
- 【資料結構與演算法】歸併排序資料結構演算法排序
- 排序演算法之 '歸併排序'排序演算法
- 進階指南--超快速排序(歸併+逆序對)排序
- 歸併排序 js demo排序JS
- 排序演算法之快速排序的實現排序演算法
- Python實現的快速排序Python排序