看了劉宇波的**,講雙路快速排序的,原理講的很直觀,程式講解也一看就懂。這裡寫一下自己的理解過程,也加深一下自己的理解。
首先說一下為什麼需要雙路排序,在有些帶有許多重複資料的陣列裡,使用隨機快速排序或者最簡單的快速排序演算法時,由於重複的資料會放在原來的索引位置不動,就回導致劃分陣列時劃分的某一部分太長,起不到分段排序的效果,這樣就導致演算法退化成o(n^2)的複雜度。就像下圖:
為了解決這個問題,雙路快速排序採用的方法是對等於v的數也進行交換,原理如下所述:
首先選擇乙個數作為標誌,放在陣列的最左側,下標為l,在陣列左邊放小於v的數,右側放大於v的數。
之後,先從l+1開始遍歷陣列,當資料小於v時,該資料屬於左側橙色部分,保持其位置不動,i++,繼續向後遍歷,當找到某個數大於或者等於(注意,這裡等於很重要)v時,停止遍歷。轉而開始根據j來遍歷陣列,j不斷減小,索引陣列的資料,當索引到某個數小於或者等於v時,停止遍歷。如下圖所示:
這時兩個綠色的區域就是分別屬於
之後,將i,j分別向後向前移動一位,繼續開始新的索引,直到i和j重合或者i>j位置,就完成了partition的過程。
下面貼出**:
主函式 main.cpp
// quicksort2.cpp : 雙路快速排序,適用於解決有很多重複資料的陣列。
//#include "stdafx.h"
#include "e:/學習/c++/資料結構和演算法/code/演算法/排序演算法/common/sorttesthelper.h"
#include "quicksort.h"
#include "radomquicksort.h"
#include "quicksort2.h"
using namespace std;
int main()
雙路快速排序演算法 quicksort2.h
#ifndef quicksort2_h
#define quicksort2_h
#include
#include 程式設計客棧iostream>
using namespace std;
template
int __partition3(t *arr, int l, int r)
swap(arr[i], arr[j]);
i++;
j--;
} swap(arr[l], arr[j]);
return j;
}template
void __quicksort2(t *arr,int l,int r)
int p = __partition3(arr, l, r);
__quicksort2(arr, l, p - 1);
__quicksort2(arr, p + 1, r);
}template
void quicksort2(t *arr, int n)
#endif
隨機快速排序 radomquicksort.h
#ifndef radomquicksort_h
#define radomquicksort_h
#include
#include
using namespace std;
template
int __randpartition(t *arr, int l, int r)
int p = __randpartition(arr, l, r);
__radomquicksort(arr, l, p - 1);
__radomquicksort(arr, p + 1, r);
}template
void radomquicksort(t *arr, int n)
#endif
快速排序 quicksort.h
#ifndef quicksort_h
#define quicksort_h
using namespace std;
template
int __partition(t *arr, int l, int r)
int p = __partition(arr, l, r);
__quicksort(arr, l, p - 1);
__quicksort(arr, p + 1, r);
}template
void quicksort(t *arr, int n)
#endif
sorttesthelper 函式
#ifndef sorttesthelper_h
#define sorttesthelper_h
#include
#include
#include
#include
using namespace std;
namespace sorttesthelper
return arr;
}//產生近乎有序的隨機數
int *generatenearlyorderedarray(int n, int swapnum)
for (size_t i = 0; i < swapnum; i++)
return arr;
}//列印陣列:輸入陣列,陣列元素的個數
template
void printarr(t *arr,int n)
std::cout << std::endl;
}//判斷是否已經排序
template
bool ifsort(t *arr,int n) }
return true;
}//計算程式執行時間
template
//函式輸入引數是:所需要計算的執行gyzgcte的函式的名稱,函式的指標,函式的輸入陣列,輸入陣列的個數
void sorttime(string funname,void(*sort)(t*arr, int), t* arr,int n)
{ clock_t startime = clock();
sort(arr,n);
clock_t endtime = clock();
assert(ifsort(arr, n));
std::cout <
最終結果三種演算法對10萬個具有重複的資料的排序時間如下:
本文標題: c/c++實現雙路快速排序演算法原理
本文位址:
Java雙路快速排序演算法
針對序列中重複元素出現頻率非常高,隨機化快速排序演算法退化成o n 2 的問題 雙向開始遍歷 當arr i arr l arr j arr l 時暫停 進行歸併 arr i 與arr j 交換元素 當i j時遍歷完畢 雙路快速排序演算法,對解決重複性高的元素集合效率高 public static s...
C 實現快速排序 雙路快速排序 三路快速排序
從左向右依次遞迴 如果 陣列中的元素都相等,就會變成 n 級別的複雜度演算法 public class quicksort public static void sort t arr where t system.icomparable public static void sort2 t arr ...
雙路快速排序
雙路快速排序的時間複雜度為o nlog2n 空間複雜度為o n 雙路快速排序的核心思想 單路快排會將等於v的元素分配在左側或者右側,當陣列中有大量重複元素時,這將會導致左右兩側的元素數量極度不均衡,時間複雜度退化到o n 2 如下圖所示 雙路快排是將等於v的部分近乎平均的分配在左右兩側,避免了該問題...