排序5-快速排序
来源:互联网 发布:linux ubuntu gcc 编辑:程序博客网 时间:2024/05/18 22:12
基本思想
快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
算法步骤
算法步骤简述如下:
- 选择一个基准值(pivot)(选择方法很多,可以固体选某个值,比如第一个或最后一个或中间值,或者是三数取中法等);
- 将比基准值(pivot)小的数值划分到基准值左边,构成左子串列,将比基准值(pivot)大的数值划分到基准值右边,构成右子串列;
- 分别对左子串列和右子串列递归地作上述两个步骤;
- 直到左子串列或右子串列只剩一个值或者为空。
基准值的选取
上面的第一步基准值的选择对快速排序的效率有很大关系。基准值(pivot)的选择办法有下面几种:
- 固定位置:第一个,最后一个或中间值;
- 随机选取:用随机函数随机选取一个;
- 三数取中:去第一个,中间值和最后一个数的平均值。
固定位置和随机选取的方法容易造成一种极端,如果选取的那个数刚好是最小值或最大值,比如数组是有序的,就会导致一个很差的分割,是左子串或右子串列为0,而且随机选取过程还会有额外的时间开销。所以都是不可取的。三数取中的办法就避免了上面的情况。
时间空间复杂度
快速排序的时间性能跟递归的深度有关,而空间复杂度跟递归造成的栈空间使用有关。最好的情况是,选取的基准值刚好是中位数,刚好将数据等分成2个子串,递归树也就是平衡的。递归调用需要
代码实现
#define MAX_LENGTH_INSERT_SORT 7 // 数组长度阈值int Partition(int arr[], int Left, int Right){ /* 三数取中*/ int mid = Left + (Right - Left) / 2; if(arr[Left] > arr[Right]) swap(arr[Left],arr[Right]); if(arr[mid] > arr[Right]) swap(arr[mid], arr[Right]); if(arr[mid] > arr[Left]) swap(arr[mid], arr[Left]); int pivot_key = arr[Left]; while(Left < Right) { while(Left < Right && arr[Right] >= pivot_key ) Right --; arr[Left] = arr[Right]; while(Left < Right && arr[Left] <= pivot_key) Left ++; arr[Right] = arr[Left]; } arr[Left] = pivot_key; return Left;}void QSort(int arr[], int Left, int Right){ int pivot_index; /*当Right - Left 大于 MAX_LENGTH_INSERT_SORT 采用 快排,否则使用直接插入*/ if(Right - Left > MAX_LENGTH_INSERT_SORT) { pivot_index = Partition(arr, Left, Right); QSort(arr, Left, pivot_index - 1); QSort(arr, pivot_index + 1, Right); } else Insert_sort(arr, Right - Left + 1); // 直接插入法是简单排序当中性能最好的}void Quick_sort(int arr[], int len){ QSort(arr, 0, len - 1);}
测试程序
#include <iostream>#include <cstring>#include <ctime>#include <cmath>using namespace std;#define ArraySize 100000void swap(int *x, int *y){ int temp; temp = *x; *x = *y; *y = temp;}void Bubble_sort(int arr[], int len){ for(int i = 0; i < len; i ++) { for(int j = i + 1; j < len; j ++) if(arr[i] > arr[j]) swap(arr[i], arr[j]); }}void Bubble_sort1(int arr[], int len){ for(int i = 0; i < len; i ++) { for(int j = len - 1; j >= i; j --) { if(arr[i] > arr[j]) swap(arr[i], arr[j]); } }}void Bubble_sort2(int arr[], int len){ bool flag = true; while(flag) { flag = false; for(int i = 0; i < len; i ++) for(int j = len - 1; j >= i; j --) if(arr[i] > arr[j]) swap(arr[i], arr[j]); }}void Slect_sort(int arr[], int len){ for(int i = 0; i < len; i ++) { int min_index = i ; for(int j = i + 1; j < len; j ++) { if(arr[min_index] > arr[j]) min_index = j; } if(i != min_index) swap(arr[i],arr[min_index]); }}void Insert_sort(int arr[], int len){ for(int i= 1; i < len; i ++) { int key = arr[i]; int j = i; while(j && arr[j - 1] > key) { arr[j] = arr[j - 1]; j --; } arr[j] = key; }}void Shell_sort(int arr[], int len){ int increment = len / 2; while(increment) { for(int i = increment; i < len; i ++) { int key = arr[i]; /*int j ; for(j = i; j >= increment; j -= increment) { if(arr[j-increment] > key ) arr[j] = arr[j-increment]; else break; }*/ int j = i; while(j >= increment && arr[j-increment] > key) { arr[j] = arr[j-increment]; j -= increment; } arr[j] = key; } increment /= 2; }}void Shell_sort1(int arr[], int len){ int increment = 0; for(increment = len/2; increment > 0; increment /=2) { for(int i = increment; i < len; i++) { int key = arr[i]; int j = 0; for(j = i; j >= increment; j -=increment) { if(arr[j-increment] > key) arr[j] = arr[j-increment]; else break; } arr[j] = key; } }}void Shell_sort2(int arr[], int len){ int index = log( 2*len + 1) / log(3.0); //cout << index << endl; int increment = ( pow(3.0, index) - 1 ) / 2; //cout << increment << endl; while(increment) { for(int i = increment; i < len; i ++) { int key = arr[i]; /*int j ; for(j = i; j >= increment; j -= increment) { if(arr[j-increment] > key ) arr[j] = arr[j-increment]; else break; }*/ int j = i; while(j >= increment && arr[j-increment] > key) { arr[j] = arr[j-increment]; j -= increment; } arr[j] = key; } index -= 1; increment = ( pow(3.0, index) - 1 ) / 2; }}void Heap_adjust(int arr[], int index, int len){ while(true) { int iMax = index; int iLeft = 2 * index + 1; int iRight = 2 * index + 2; if(iLeft < len && arr[index] < arr[iLeft]) iMax = iLeft; if(iRight < len && arr[index] < arr[iRight]) iMax = iRight; if(iMax != index) { swap(arr[index], arr[iMax]); index = iMax; } else break; }}void Heap_adjust2(int arr[], int index, int len){ int iMax = index; int iLeft = 2 * index + 1; int iRight = 2 * index + 2; if(iLeft < len && arr[index] < arr[iLeft]) iMax = iLeft; if(iRight < len && arr[index] < arr[iRight]) iMax = iRight; if(iMax != index) { swap(arr[index], arr[iMax]); Heap_adjust2(arr, iMax, len); }}void Build_maxheap(int arr[], int len){ for(int i = len / 2; i >= 0; i --) { Heap_adjust(arr, i , len); }}void Heap_Sort(int arr[], int len){ Build_maxheap(arr, len); for(int i = len - 1; i > 0; i --) { swap(arr[0], arr[i]); Heap_adjust(arr, 0, i); }}void Print_array(int arr[], int len){ for(int i = 0; i < len; i++) { cout << arr[i] << " "; } cout << endl;}void merge_array(int arr[], int tmp[], int Left, int mid, int Right){ assert(arr && Left >= 0 && Left <= mid && mid <= Right); int i = Left; int j = mid + 1; int index = 0; while(i <= mid && j <= Right) { if(arr[i] <= arr[j]) tmp[index++] = arr[i++]; else tmp[index++] = arr[j++]; } while(i <= mid) tmp[index++] = arr[i++]; while(j <= Right) tmp[index++] = arr[j++]; memcpy(arr + Left, tmp, (Right - Left + 1) * sizeof(int)); }void merge_sort(int arr[], int tmp[], int Left, int Right){ assert(arr && Left >= 0); int mid; if(Left < Right) { mid = (Left + Right) / 2; merge_sort(arr, tmp, Left, mid); merge_sort(arr, tmp, mid + 1, Right); merge_array(arr, tmp, Left, mid, Right); }}void Merge_Sort(int arr[], int len){ assert(arr && len); int *tmp_arr; //tmp_arr = (int *)malloc(len * sizeof(int)); tmp_arr = new int[len]; merge_sort(arr, tmp_arr, 0, len - 1); delete[] tmp_arr;}#define MAX_LENGTH_INSERT_SORT 7 // 数组长度阈值int Partition(int arr[], int Left, int Right){ /* 三数取中*/ int mid = Left + (Right - Left) / 2; if(arr[Left] > arr[Right]) swap(arr[Left],arr[Right]); if(arr[mid] > arr[Right]) swap(arr[mid], arr[Right]); if(arr[mid] > arr[Left]) swap(arr[mid], arr[Left]); int pivot_key = arr[Left]; while(Left < Right) { while(Left < Right && arr[Right] >= pivot_key ) Right --; arr[Left] = arr[Right]; while(Left < Right && arr[Left] <= pivot_key) Left ++; arr[Right] = arr[Left]; } arr[Left] = pivot_key; return Left;}void QSort(int arr[], int Left, int Right){ int pivot_index; /*当Right - Left 大于 MAX_LENGTH_INSERT_SORT 采用 快排,否则使用直接插入*/ if(Right - Left > MAX_LENGTH_INSERT_SORT) { pivot_index = Partition(arr, Left, Right); QSort(arr, Left, pivot_index - 1); QSort(arr, pivot_index + 1, Right); } else Insert_sort(arr, Right - Left + 1); // 直接插入法是简单排序当中性能最好的}void Quick_sort(int arr[], int len){ QSort(arr, 0, len - 1);}int main(int argc, char const *argv[]){ /* code */ int Array[ArraySize]; int Array1[ArraySize]; int Array2[ArraySize]; int Array3[ArraySize]; time_t begin , end; srand(time(NULL)); for(int i = 0; i < ArraySize; i ++) { Array[i] = rand()%ArraySize; //cout << Array[i] << " "; } memcpy(Array1, Array, ArraySize * sizeof(Array1[0])); memcpy(Array2, Array, ArraySize * sizeof(Array2[0])); memcpy(Array3, Array, ArraySize * sizeof(Array2[0]));// Print_array(Array, ArraySize);/* begin = clock(); Bubble_sort2(Array, ArraySize); end = clock(); cout << "Bubble_sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; begin = clock(); Slect_sort(Array1, ArraySize); end = clock(); cout << "Slect_sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; begin = clock(); Insert_sort(Array2, ArraySize); end = clock(); cout << "Insert_sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl;*/ begin = clock(); Shell_sort2(Array, ArraySize); end = clock(); cout << "Shell_sort2 runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; begin = clock(); Heap_Sort(Array1, ArraySize); end = clock(); cout << "Heap_Sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; begin = clock(); Merge_Sort(Array2, ArraySize); end = clock(); cout << "Merge_Sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; //Print_array(Array2, ArraySize); begin = clock(); Quick_sort(Array3, ArraySize); end = clock(); cout << "Quick_sort runtime: " << double(end - begin) / CLOCKS_PER_SEC << "s" << endl; //Print_array(Array3, ArraySize); return 0;}
运行结果如下:
Shell_sort2 runtime: 0.028sHeap_Sort runtime: 0.005sMerge_Sort runtime: 0.013sQuick_sort runtime: 0.011s
参考文献
知无涯之std::sort源码剖析
http://feihu.me/blog/2014/sgi-std-sort/
0 0
- 排序5-快速排序
- 排序5:快速排序
- 排序(5)快速排序
- (5)快速排序
- 排序算法5--快速排序
- 数据结构算法----排序(5)----快速排序
- 【数据结构之排序5】快速排序
- Java排序算法5:快速排序
- 排序算法5——快速排序
- 排序(5)---------快速排序(C语言实现)
- 算法学习之排序(5)--快速排序
- 排序算法5之快速排序
- 排序算法(5)--快速排序
- 排序5——快速排序
- 数据结构之排序5--快速排序
- 排序之快速排序
- 排序算法--快速排序
- 插入排序,快速排序
- TransactionScope的使用
- 四、文件的上传
- S5p4418 启动配制分析
- 实习面试经验谈
- MiniTwitter记住密码等功能实现
- 排序5-快速排序
- 在网页中获取天气信息方式介绍
- 任意输入两个数,输入这两个数之间的所有素数
- 面向对象上总结
- 超实用的PHP代码片段(一)
- Linux之文件系统和根文件系统
- Quartz2D绘图简介
- The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory的解决方法 最近又开始
- 类和接口(三)