快速排序基本操作的优化(完整代码)
来源:互联网 发布:dafa888信誉第一js 编辑:程序博客网 时间:2024/06/03 21:53
这里是快速排序的优化版,在其中的几个部分进行了优化。
1、设置某一常数,当(high-low)大于某个数时,用快排递归,小于时,用直接插入排序。
当待排数组比较小时,用快速排序递归操作,反而不如用直接插入排序来的快。直接插入排序是简单排序中性能最好的。
2、用L->r【0】存储枢轴数据,等到low和high汇合后,确定了枢轴位置,再将L->r【0】赋值给L->r【low】。
经典的快排,是将枢轴数据pivot,通过与表中其他元素比较,逐次换到合适的位置。为了减少这其中不必要的交换,我们用L->r【0】备份枢轴数据。最后一步再赋值给L->r【low】。
3、选取三个元素,取其中的中间值作为枢轴。
经典的快速排序中,是选取左端第一个数据作为枢轴,如果第一个数据比较大或比较小,会很大程度上影响快排的速度。三数取中,则以极大的概率避免了这种情况。这里我们分别选取了左端、中间和右端三个数据。
4、用迭代替换部分递归(尾递归)
经典快速排序,是排好当前表后,递归排序其低子表和高子表,这里,在递归完低子表后,用pivot替换low的值,继续循环,就可以排序高子表了。
//快速排序(优化版)#include<stdio.h>#include<stdlib.h>#define MAXSIZE 20 //待排序数据个数 #define MAX_LENGTH 7 //大于MAX_LENGTH用快排递归,小于,用直接插入排序typedef struct { int r[MAXSIZE+1]; int length;}SqList;//交换函数void swap(SqList *L,int i,int j){ int temp=L->r[i]; L->r[i]=L->r[j]; L->r[j]=temp;}//将比枢轴pivotkey小的元素放到左边,大的放到右面,然后将pivotkey放入合适的位置int Partition(SqList *L,int low,int high){ int pivotkey; int m=low+(high-low)/2; if(L->r[low]>L->r[high]) swap(L,low,high); if(L->r[m]>L->r[high]) swap(L,high,m); if(L->r[m]>L->r[low]) swap(L,low,m); //这一段意思是,选左端、中间、右端三个数,然后三数取中作为枢轴 //避免了直接去左端作为枢轴时,左端恰好是很小或很大的情况 pivotkey=L->r[low]; //将第一个元素作为枢轴pivotkey L->r[0]=pivotkey; //将枢轴关键字存入L->r【0】 while(low<high) //从表的两端交替向中间扫描 { while(low<high && L->r[high]>=pivotkey) //从右边起,将比pivotkey小的换到左边 high--; L->r[low]=L->r[high]; //采用替换而不是交换的方式,避免了多余的交换操作 while(low<high && L->r[low]<=pivotkey) //从左边起,将比pivotkey大的换到右边 low++; L->r[high]=L->r[low]; //采用替换而不是交换的方式,避免了多余的交换操作 } L->r[low]=L->r[0]; //将枢轴值替换回L->r【low】 return low; //low与high相等时,即为枢轴位置}//直接插入排序//直插的经典代码void InsertSort(SqList *L){ int i,j; for(i=2;i<=L->length;i++) { if(L->r[i]<L->r[i-1]) { L->r[0]=L->r[i]; for(j=i-1;L->r[j]>L->r[0];j--) L->r[j+1]=L->r[j]; L->r[j+1]=L->r[0]; } }}//递归函数void QSort(SqList *L,int low,int high){ int pivot; if((high-low)>MAX_LENGTH) //大于MAX_LENGTH用快排递归,小于,用直接插入排序 { while(low<high) //用while替换if //一次循环后,low没用了,将pivot替换low,再循环一次,就去排序高子表了 //这是用迭代替换了部分递归 { pivot=Partition(L,low,high); //将表一分为二 QSort(L,low,pivot-1); //低子表继续递归 low=pivot+1; } } else InsertSort(L);}//初始化函数int Init(SqList ** L){ *L=NULL; *L=(SqList *)malloc(sizeof(SqList)); if(*L==NULL) { return 0; } (*L)->length=0; return 1;}//插入函数void Insert(SqList **L,int data){ (*L)->length++; (*L)->r[(*L)->length]=data;} //输出函数void Printf(SqList *L){ int i; for(i=1;i<=L->length;i++) { printf("%d ",L->r[i]); }}//主函数void main(){ SqList *L; int i; Init(&L); int a[]={55,44,11,22,33,77,45,68,95,61, 89,632,114,236,895,145,71,33,54,147}; for(i=0;i<20;i++) { Insert(&L,a[i]); } QSort(L,1,L->length); InsertSort(L); Printf(L);}
0 0
- 快速排序基本操作的优化(完整代码)
- 二叉排序树的基本操作(完整代码)
- 快速排序的基本实现(完整源代码)
- 单链表的基本操作(代码优化)
- 二叉平衡树的基本操作(完整代码)
- 顺序队的基本操作(C++完整代码)
- 快速排序代码及实现(优化)
- 代码练习:基本快速排序
- 散列表查找(哈希表)的基本操作 (完整代码)
- 快速排序的优化
- 快速排序的优化
- 优化的快速排序
- 快速排序的优化
- 快速排序的优化
- 快速排序的优化
- 快速排序的优化
- 快速排序的优化
- 优化的快速排序
- 架构设计:负载均衡层设计方案(1)——负载场景和解决方式
- 找工作节奏和准备
- SVN的使用(Android Studio)
- Tomcat学习总结
- 负数的带符号和不带符号的右移运算
- 快速排序基本操作的优化(完整代码)
- Linux进程间通信(IPC)编程实践(三) 详解System V消息队列(1)
- 基于gulp+webpack的"约定大于配置"的构建方案探讨
- 欢迎使用CSDN-markdown编辑器
- IE6 中 window.open() 函数的超级大坑
- flexbox Flex 布局教程
- Sitemesh 3 的使用及配置
- rbenv配置ruby on rails 编程环境(Linux系统)
- 使用非 GUI 模式运行 JMeter 压力测试