快速排序及五種優化(模板)
阿新 • • 發佈:2018-12-09
1、快速排序的基本思想:
快速排序排序使用分治的思想,通過一趟排序將待排序列分割成兩部分,其中一部分記錄的關鍵字均比另一部分記錄的關鍵字小。之後分別對這兩部分記錄繼續進行排序,遞迴地以達到整個序列有序的目
2、快速排序的三個步驟:
(1)選擇基準:
在待排序列中,按照某種方式挑出一個元素,作為 “基準”
(2)分割操作:
以該基準在序列中的實際位置,把序列分成兩個子序列。此時,在基準左邊的元素都比該基準小,在基準右邊的元素都比基準大
(3)遞迴地對兩個序列進行快速排序,直到序列為空或者只有一個元素。
3、選擇基準的方式
一般取序列的第一個或最後一個元素作為基準基本的快速排序
快排的程式碼實現:
//劃分區間排序 template<typename T> int partition(T arr[], int startindex, int endindex) { T key = arr[startindex]; while (startindex < endindex) { while (startindex < endindex && arr[endindex] >= key)endindex--; arr[startindex] = arr[endindex]; while (startindex < endindex && arr[startindex] <= key) startindex++; arr[endindex] = arr[startindex]; } arr[startindex] = key; return startindex; } template<typename T> void Quick(T arr[], int s, int e) { //遞迴演算法 if (s < e) { int boundindex = partition(arr, s, e); Quick(arr, s, boundindex - 1); Quick(arr, boundindex + 1, e); } } template<typename T> void QuickSort(T arr[], int len) { Quick(arr, 0, len - 1); } template<typename T> void Show(T arr[], int len) { for (int i = 0; i < len; i++) { std::cout << arr[i] << " "; } std::cout << std::endl; } int main() { int arr[30]; for (int i = 0; i < 30; i++) { arr[i] = rand() % 1000; } int len = sizeof(arr) / sizeof(arr[0]); Show(arr, len); std::cout << "---------------------" << std::endl; QuickSort(arr, len); Show(arr, len); return 0; }
4、快速排序的五種優化
(1)隨機取基準點 :
若待排序列是部分有序時,固定選取基準使快排效率底下,取待排序列中任意一個元素作為基準
程式碼實現:
int arr[30];
for (int i = 0; i < 30; i++)
{
arr[i] = rand() % 1000; //隨機取基準值
}
int len = sizeof(arr) / sizeof(arr[0]);
(2)三數取中(優化有序的資料):
對待排序序列中low、mid、high三個位置上資料進行排序,取中間的那個資料作為基準,並用0下標元素儲存基準。
程式碼實現:
template<typename T>
//三數取中
void FindMiddleNumber(T arr[], int left, int mid, int right)
{
if (arr[mid] > arr[right])
{
Swap(arr, mid, right);
}
if (arr[left] > arr[right])
{
Swap(arr, left, right);
}
if (arr[left] < arr[mid])
{
Swap(arr, left, mid);
}
}
(3)小資料的優化 用插入排序 ,最優情況o(n)
對於很小和部分有序的陣列,快排不如插排好。當待排序序列的長度分割到一定大小後,繼續分割的效率比插入排序要差,此時可以使用插排而不是快排
程式碼實現:
template<typename T>
//插入排序
void insertSort(T arr[], int startindex, int endindex)
{
int tmp = 0;
int i = startindex + 1;
int j = i - 1;
for (i; i <= endindex; ++i)
{
tmp = arr[i];
for (j = i - 1; j >= startindex && arr[j] > tmp; --j)
{
arr[j + 1] = arr[j];
}
arr[j + 1] = tmp;
}
}
(4)聚集優化
重複資料的優化(資料量大,數值小,離散程度小)
(5)非遞迴優化
沒有開棧,清棧,開銷小
程式碼實現:
//非遞迴快排
if (s < e)
{
Stack<int> st;
int left = s;
int right = e;
st.push(right);
st.push(left);
while (!st.empty())
{
left = st.top(); st.pop();
right = st.top(); st.pop();
int boundindex = partition(arr, left, right);
//left boundindex - 1 boundindex + 1 right;
if (left < boundindex - 1)
{
st.push(boundindex - 1);
st.push(left);
}
if (boundindex + 1 < right)
{
st.push(right);
st.push(boundindex + 1);
}
}
}
}