算法 基于比较的排序
来源:互联网 发布:卡尔曼滤波算法视频 编辑:程序博客网 时间:2024/05/21 07:11
插入排序
void insert_sort(int *ary,int n){int temp; int i,j;for(i=1;i<n;i++)// 从第二个数开始{temp=ary[i];for(j=i;j>0&&temp<ary[j-1];j--){ary[j]=ary[j-1];}ary[j]=temp;}}
生活中可以用来模拟插入排序的事件,例如打牌中的将牌排序,十分形象具体
通常情况下插入排序O(N^2),基本有序(最好情况下)时是O(N),是稳定排序
折半插入排序可以在比较次数上进行优化,但移动次数未改变,复杂度仍然是O(N^2)
2-路插入排序
表插入排序
希尔SHELL排序
int shell_sort(int *ary,int size){int op=0;int temp;int incs[5]={1,5,19,41,109};for(int t=4;t>=0;t--){int h=incs[t];for(int i=h;i<size;i++){temp=ary[i];for(j=i;j>0&&temp<ary[j-h];j=j-h){ary[j]=ary[j-h];op++;}ary[j]=temp;op++;}}return op;]
SHELL排序是不稳定的排序,
通常情况下性能优于插入排序
快速排序
// 从左遍历版本,以结尾为主元,返回的轴位置为i+1,因为这里i是从-1开始移动的int partition(int *ary,int left,int right){int i=left-1;int j=left;int pivot=ary[right];for(;j<right;j++){if(ary[j]<=pivot){i++;swap(i,j);}}swap(i+1,right);return i+1;}void quick_sort(int *ary,int left,int right){if(left<right){int index=partition(ary,left,right);quick_sort(ary,left,index-1);quick_sort(ary,index+1,right);}}// HOARE版本,可以任意位置为主元,这里返回的轴位置是j+1,最后j在i前,可能j+1=i也可能j+2=ivoid quicksort(int *ary,int left,int right){ if(left<right){ int i=left,j=right; int pivot=ary[left]; while(i<=j){ while(ary[j]>pivot)j--; while(ary[i]<pivot)i++; if(i<=j){ int temp=ary[i]; ary[i]=ary[j]; ary[j]=temp; i++;j--; } } if(left<j) quicksort(ary,left,j); if(i<right) quicksort(ary,i,right); }}// 替换版本,非交换版本,这里返回的轴位置是ivoid quicksort(int *ary,int left,int right){if(left<right){int i=left;int j=right;int key=ary[i];while(i<j){while(i<j&&ary[j]>=key)j--;ary[i]=ary[j];while(i<j&&ary[i]<=key)i++;ary[j]=ary[i];}ary[i]=key;if(left<i-1)quicksort(ary,left,i-1);// 这里可以用i-1,因为ary[i]已经在有序的位置上了if(i+1<right)quicksort(ary,i+1,right);}}
快速排序基于分治法的排序算法,
时间复杂度为O(n*logn),基本有序的情况下(也就是最坏情况下)是O(n^2),但通常情况下性能是最佳的,常数因子较小
不稳定排序
为了避免基本有序的情况,通过引入随机化技术,使得在等概率的情况下获得期望性能,所作的操作只需要随机一个位置与每次作pivot的位置元素交换;
另外一种改进随机是三数取中划分,随机三个位置,然后取中位数为pivot
堆排序
void swap(int *a,int *b){ int temp=*a; *a=*b; *b=temp; }// 调整堆 siftdownvoid heapify(int *ary,int i,int size){int left,right,max;while(i<size){ left=2*i+1; right=left+1;max=i;if(left<size&&ary[i]<ary[left])i=left;if(right<size&&ary[i]<ary[right])i=right;if(i!=max)swap(&ary[i],&ary[max]);elsebreak;}}// 建堆 siftupvoid buildHeap(int *ary,int size){for(int i=(size-2)/2;i>=0;i--)// 利用siftdown实现siftup,FOR 每个结点的父母结点 TO 根结点{heapify(ary,i,size);}}// 堆排序过程 ,先建堆,然后交换顶点与末尾,交换一次再调整一次,当前代码是大根堆,所以最后顺序是从小到大 void heapSort(int *ary,int size){buildHeap(ary,size);for(int i=size-1;i>0;i--){swap(&ary[0],&ary[i]);heapify(ary,0,i);}}
堆排序的前身:树形选择排序,又称锦标赛排序(类似比赛分组树结构)
堆的定义是:一个完全二叉树,每个结点大于等于其两个孩子结点(大根堆)
堆排序的过程,首先建堆,然后将堆顶与末尾元素交换,紧接着调整堆使其继续保持定义,循环交换n次,形成最终有序排列
时间复杂度O(n*logn),其中调整堆的复杂度为O(logn),排序O(n),不稳定排序
堆排序的应用:
优先队列
归并排序
// 归并排序,不过new和delete写在子函数中,效率可能不高,可以直接在排序前申请O(n)的空间void mergeArray(int *ary,int left,int mid,int right,int *temp){int i=left,j=mid+1,k=0;int temp[]=new int[right-left+1];while(i<mid&&j<right){if(ary[i]<ary[j])temp[k++]=ary[i++];elsetemp[k++]=ary[j++];}while(i<=mid)temp[k++]=ary[i++];while(j<=right)temp[k++]=ary[j++];// 复制回原数组for(int i=0;i<k;i++){ary[left+i]=temp[i];}// 考虑是否删除额外空间delete[] temp;}void mergeSort(int *ary,int left,int right,int *temp){int mid=((right-left)>>1)+left;if(left<right){mergeSort(ary,left,mid);//注意这里不是 mid-1,之前写错了mergeSort(ary,mid+1,right);mergeArray(ary,left,mid,right,temp);}}
归并排序的时间复杂度最好最坏下均是O(n*logn),但空间复杂度是O(n)
是稳定排序
利用递归树可以清晰地分析归并排序的过程
0 0
- 基于比较的排序算法
- 算法 基于比较的排序
- 基于比较的排序算法集
- 基于比较的常用排序算法总结
- 线性时间排序: 三种非基于比较的内部排序算法
- 基于比较的各种排序算法的实现
- 四种常见的基于比较的排序算法C++
- 基于比较的排序算法的最优下界---NlogN
- 基于比较的内排序算法(一)
- 基于比较的内排序算法(二)
- 基于比较的内排序算法(三)
- 排序算法的比较~~
- 排序算法的比较
- 排序算法的比较
- 排序算法的比较
- 排序算法的比较
- 排序算法的比较
- 排序算法的比较
- fatal error C1853: 'Debug\test.pch' precompiled header file is from a previous version of the compil
- UPC——2226——Contest Print Server
- Servlet 3.0 新特性详解
- python 科学计算学习一:numpy文件存取,内存映射
- 传统企业软件商必死
- 算法 基于比较的排序
- WPF常用控件资源汇集
- 无头单链表删除一个节点
- uint8_t数据类型
- Macos svn命令行工具
- 博客收集
- mule 异步方式是一种单向调用,调用者不需要获得响应。
- WebClient上传文件Jsp接受文件流数据
- a4j:jsFunction不会执行oncomplete方法的原因