快速排序、堆排序、归并排序
2016-03-28 12:50
531 查看
常见排序有7种:冒泡排序、希尔排序、插入排序、选择排序、快速排序、堆排序、归并排序。
此处讨论后三种时间复杂度为O(NlogN)的算法。
1,快速排序
一般情况下,快速排序迭代(或递归)次数为logN,每次恒进行N次比较;最差情况下迭代N次;
Partition部分:
2,归并排序
归并排序和快速排序都是基于分治法(Divide and Conquer);需要注意的是归并排序空间复杂度O(N)。
合并两有序部分MergeArray:
MergeSort部分:
3,堆排序
作为一种数据结构,此处将堆设为一个类,含有的建堆、插入、删除作为方法封装于类中。
(int 类型的最小堆)
Insert操作:将待插入元素x存入heap[CurrentSize], 从CurrentSize向上进行1次FilterUp,时间复杂度O(logN);
Remove操作:删除根元素(最小值),将heap[0]与heap[CurrentSize-1]对调,从根节点向下进行1次FilterDown, 时间复杂度O(logN);
文章内容由http://www.nowamagic.net/librarys/veda/detail/294 、 http://blog.csdn.net/morewindows/article/details/6709644 整理得到!
此处讨论后三种时间复杂度为O(NlogN)的算法。
1,快速排序
一般情况下,快速排序迭代(或递归)次数为logN,每次恒进行N次比较;最差情况下迭代N次;
Partition部分:
int Partion(int a[], int low, int high) { int i = low; int j = high; int val = a[low]; while (i < j) { while (i < j && a[j] >= val) j--; if (i < j) // 可能已经有序; a[i++] = a[j]; while (i < j && a[i] <= val) i++; if (i < j) a[j--] = a[i]; } a[i] = val; return i; }QuickSort部分:(先调用Partition找到pivot对应的实际位置idx,然后分别对左右两部分递归)
void QuickSort(int a[], int low, int high) { if (i < j) { int idx = Partition(a, low, high); QuickSort(a, low, idx-1); QuickSort(a, idx+1, high); } }附上快速排序视觉直观图:
2,归并排序
归并排序和快速排序都是基于分治法(Divide and Conquer);需要注意的是归并排序空间复杂度O(N)。
合并两有序部分MergeArray:
void MergeArray(int a[], int low, int mid, int last, int tmp[]) { int i = low; int j = mid+1; int k = 0; while (i <= mid && j <= high) { if (a[i] <= a[j]) a[k++] = a[i++]; else a[k++] = a[j++]; } while (i <= mid) a[k++] = a[i++]; while (j <= high) a[k++] = a[j++]; for (i = 0; i < k; i++) a[low+i] = tmp[i]; }
MergeSort部分:
void Mergesort(int a[], int low, int high, int tmp[]) { if (low < high) { int mid = (low +high) / 2; MergeSort(a, low, mid, tmp); MergeSort(a, mid+1, high, tmp); MergeArray(a, low, mid, high, tmp); } }main函数调用:
int main() { int n; int a ; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); int *p = (int *)malloc(n * sizeof(int)); if (p == 0) return 1; MergeSort(a, 0, n-1, p); //调用MergeSort排序 free(p); return 0; }继续附上归并排序视觉直观图:
3,堆排序
作为一种数据结构,此处将堆设为一个类,含有的建堆、插入、删除作为方法封装于类中。
(int 类型的最小堆)
class MinHeap { public: MinHeap( int maxSize );//根据最大长度建堆 MinHeap( int arr[], int n); ~MinHeap( ) { delete [] heap; } const MinHeap& operator=( const MinHeap &R );//重载赋值运算符 int Insert(int x ); int RemoveMin(int x );//移除关键码最小的元素,并赋给x bool IsEmpty( ) const { return CurrentSize == 0; } int IsFull( ) const { return CurrentSize == MaxHeapSize; } void MakeEmpty( ) { CurrentSize = 0; }//使堆空 private: enum { DefaultSize = 50 };//默认堆的大小 int *heap; int CurrentSize; int MaxHeapSize; void FilterDown ( int i, int m ); //自上向下调整堆 void FilterUp ( int i ); //自下向上调整堆 }; MinHeap::MinHeap ( int maxSize ) { MaxHeapSize = (DefaultSize < maxSize ) ? maxSize : DefaultSize; heap = new int[MaxHeapSize]; CurrentSize = 0; } MinHeap::MinHeap (int arr[], int n ) { MaxHeapSize = DefaultSize < n ? n : DefaultSize; heap = new int[MaxHeapSize]; if(heap==NULL){cerr <<"fail" <<endl;exit(1);} for(int i =0; i< n; i++) heap[i] = arr[i]; //数组传送 CurrentSize = n; //当前堆大小 int currentPos = (CurrentSize-2)/2; //最后非叶 while ( currentPos >= 0 ) { FilterDown ( currentPos, CurrentSize-1 ); currentPos-- ; } } void MinHeap::FilterDown (int start,int EndOfHeap ) { int i = start, j = 2*i+1; // j 是 i 的左子女 int temp = heap[i]; while ( j <= EndOfHeap ) { if ( j < EndOfHeap && heap[j] > heap[j+1] ) j++; //两子女中选小者 if ( temp<= heap[j] ) break; else { heap[i] = heap[j]; i = j; j = 2*j+1; } } heap[i] = temp; } int MinHeap::Insert (int x ) { if ( CurrentSize == MaxHeapSize ) //堆满 { cout << "堆已满" << endl; return 0; } heap[CurrentSize] = x; FilterUp (CurrentSize); //向上调整为堆 CurrentSize++; return 1; } void MinHeap::FilterUp (int start ) { int j = start; int i = (j-1) / 2; int temp = head[start]; while (i < 0) { if (head[i] < temp) break; else { head[j] = head[i]; j = i; i = (i-1) / 2; } } head[j] = temp; } int MinHeap::RemoveMin(int x) { if(CurrentSize == 0) { cout << "栈已空" << endl; return 1; } x = heap[0]; heap[0] = heap[CurrentSize - 1]; CurrentSize--; FilterDown(0, CurrentSize-1); return 0; }对数组排序即是调用MinHeap的含参构造函数MinHeap(int arr[], int n),过程为arr[]先对heap[]赋值,然后从第一个分支节点(CurrentSize-2)/2 到根节点进行FilterDown,时间复杂度O(NlogN);
Insert操作:将待插入元素x存入heap[CurrentSize], 从CurrentSize向上进行1次FilterUp,时间复杂度O(logN);
Remove操作:删除根元素(最小值),将heap[0]与heap[CurrentSize-1]对调,从根节点向下进行1次FilterDown, 时间复杂度O(logN);
文章内容由http://www.nowamagic.net/librarys/veda/detail/294 、 http://blog.csdn.net/morewindows/article/details/6709644 整理得到!
相关文章推荐
- BestCoder Round #77
- spin_lock、spin_lock_irq、spin_lock_irqsave区别
- RADASM中使用DOSBOX来运行DOS/BIOS程序(16位)
- 多重背包问题
- 竞品分析和产品分析,你究竟搞清楚了么?
- 直方图均衡化的一个关键引理证明
- 为UIImageView设置手势不生效????
- Spring MVC 4常用的那些注解
- phalcon windows 安装
- 用500行Julia代码开始深度学习之旅 Beginning deep learning with 500 lines of Julia
- 【Python】日期模块总结
- linux目录文件管理相关命令
- AbstractMap
- JNI学习一(AndroidStudio NDK环境配置)
- FMDB源码阅读
- 优秀博客列表
- 获取请求ip的工具类
- 飛飛(十二) 求两个数的最大公约数。
- Scala: forSome关键字
- 数据结构 - 求二叉树中结点的最大距离(C++)