插入排序 & 快速排序
2.1 插入排序:
接口定义:
int insert_sort(void* data, int size, int esize,
int (*compare)(const void* key1, const void* key2));
返回值:成功 0;失败 -1。
算法描述:
每次从待排序数据集中取出第一个元素,将其插入到有序数据集中,两个数据集共用一块存储空间。两个数据集都存放在data中,data包含size个无序元素,每个元素的大小为esize,函数指针compare指向一个比较元素大小的用户自定义函数。最初,data指向size个无序元素,但是在执行insert_sort时,data所指的空间逐渐被有序元素所取代。
算法分析:
插入排序使用嵌套循环来实现,外循环用于控制循环次数,同时也代表了当前待排序的元素;内循环用于找出当前元素的正确插入位置。插入排序从第二个元素开始插入,因此,外循环需要执行n-1次。在寻找插入位置时,考虑最坏的情况(即逆序数据集中:每次插入的元素刚好是有序数据集中的最小值),则在第num次循环中,需要num次比较操作,如此,整个嵌套循环的执行时间:T(n) = [1 + 2 + 3 + ... + (n - 1)] / 2 = n(n - 1) / 2 ---> O(n2)。对于正序数据集而言,其时间复杂度为O(n)。插入算法不需要额外的存储空间。
算法实现:
/*
insert_sort():
返回值:成功0;失败 -1
*/
int insert_sort(void* data, int size, int esize,
int (*compare)(const void* key1, const void* key2))
{
char* pd = (char*)data;
void* pcur;
int num, ipos; /* 分配一块元素大小的内存 */
if((pcur = (char*)malloc(esize)) == NULL)
return -; /* 在有序数据集中循环插入待排元素 */
for(num = ; num < size; num++)
{
/* 将待排元素复制到pcur中,第一个元素默认有序,从第二个元素开始 */
memcpy(pcur, &pd[num * esize], esize); /* 寻找插入位置ipos */
ipos = num - ;
while((ipos >=) && (compare(&pd[ipos * esize], pcur) > ))
{
/* 如果*pcur < pd[ipos],则pd[ipos]后移 */
memcpy(&pd[(ipos + ) * esize], &pd[ipos * esize], esize);
ipos--;
}
memcpy(&pd[(ipos + ) * esize], pcur, esize); }
/* 释放内存 */
free(pcur); return ;
2.2 快速排序:
接口定义:
int partition(void* data, int esize, int lpos, int rpos,
int (*compare)(const void* key1, const void* key2));
返回值:成功 ppos;失败 -1
int quick_sort(void* data, int size, int esize,
int lpos, int rpos, int (*compare)(const void* key1, const void* key2));
返回值:成功 0;失败 -1
算法描述:
快速排序利用分治法的思想,首先设定一个分割值pval将数据集分为左右两个分区,然后分别对左右两个分区使用快速排序,如此递归直至区间中只有一个元素为止。数据集data包含size个无序元素,每个元素的大小为esize,函数指针compare指向一个比较元素大小的用户自定义函数。lpos和rpos分别为与当前分割值pval进行比较的位置。首次调用quick_sort()时,lpos设为0,rpos设为size – 1,相当于对全部元素进行排序(也可以自己设定感兴趣区间进行排序)。以partition()函数返回的ppos作为分割界限将数据集分为左右两个区间。分别对两个分区递归地进行快排,直至传入quick_sort()的分区只包含一个元素为止,此时排序完成。
算法分析:
影响快速排序算法性能的关键是分割值的选取,也就是partition()函数如何分割数据集。分割值一般不能太极端,这样会使得大部分数据被分到一个分区中,此时,快排的性能非常差,为O(n2)。一个比较好的方法是在区间中随机选择三个元素,然后选择三个元素中的中间值,就是通常的中位数法,实验表明该方法可以使得快排接近平均性能O(nlgn)。另外快速排序不需要额外的存储空间。
算法实现:
/*
partition():
return: success ppos; fail -1
*/
int partition(void* data, int esize, int lpos, int rpos,
int (*compare)(const void* key1, const void* key2))
{
char* pd = (char*)data;
void* pval; /* partition value */
void* ptemp;
int r[]; /* 为partition value和swapping分配空间 */
if((pval = malloc(esize)) == NULL)
return -;
if((ptemp = malloc(esize)) == NULL)
{
free(pval);
return -;
} /* 计算partition value */
r[] = (rand() % (rpos - lpos + )) + lpos;
r[] = (rand() % (rpos - lpos + )) + lpos;
r[] = (rand() % (rpos - lpos + )) + lpos;
insert_sort(r, , sizeof(int), compare_int);
memcpy(pval, &pd[r[] * esize], esize); /* 根据pval进行partition */
lpos--;
rpos++;
while()
{
/* 如果pd[rpos * esize] > *pval, 将rpos左移 */
do{
rpos--;
}while(compare(&pd[rpos * esize], pval) > ); /* 如果pd[lpos * esize] < *pval, 将lpos右移 */
do{
lpos++;
}while(compare(&pd[lpos * esize], pval) < ); if(lpos >= rpos)
break; /* 停止partition */
else
{
/* 交换lpos和rpos处的元素 */
memcpy(ptemp, &pd[lpos * esize], esize);
memcpy(&pd[lpos * esize], &pd[rpos * esize], esize);
memcpy(&pd[rpos * esize], ptemp, esize);
}
} /* 释放空间 */
free(ptemp);
free(pval); return rpos;
}
/*
quick_sort():
return: success 0;
*/
int quick_sort(void* data, int size, int esize,
int lpos, int rpos, int (*compare)(const void* key1, const void* key2))
{ int ppos;
if(lpos < rpos)
{
if((ppos = partition(data, esize, lpos, rpos, compare)) < )
return -; /* 递归地对左分区进行排序 */
if(quick_sort(data, size, esize, lpos, ppos, compare) < )
return -; /* 递归地对右分区进行排序 */
if(quick_sort(data, size, esize, ppos + , rpos, compare) < )
return -;
} return ;
}
插入排序 & 快速排序的更多相关文章
- 冒泡排序&直接插入排序&快速排序
一.冒泡排序 0 1 2 3 4 5 假设有一个6个数的数组,0,1,2,3,4,5是索引,冒泡排序就是相邻两个对比,比如5和4比,如果满足条件就互 ...
- 冒泡排序、选择排序、直接插入排序、快速排序、折半查找>从零开始学JAVA系列
目录 冒泡排序.选择排序.直接插入排序 冒泡排序 选择排序 选择排序与冒泡排序的注意事项 小案例,使用选择排序完成对对象的排序 直接插入排序(插入排序) 快速排序(比较排序中效率最高的一种排序) 折半 ...
- 前端js面试中的常见的算法问题
虽说我们很多时候前端很少有机会接触到算法.大多都交互性的操作,然而从各大公司面试来看,算法依旧是考察的一方面.实际上学习数据结构与算法对于工程师去理解和分析问题都是有帮助的.如果将来当我们面对较为复杂 ...
- 算法与设计模式系列1之Python实现常见算法
preface 常见的算法包括: 递归算法 二分法查找算法 冒泡算法 插入排序 快速排序 二叉树排序 下面就开始挨个挨个的说说原理,然后用Python去实现: 递归算法 一个函数(或者程序)直接或者间 ...
- 几个排序算法的python实现
几个排序算法 几个排序算法 几个排序算法 冒泡排序 选择排序 插入排序 快速排序 quick sort 冒泡排序 冒泡排序是比较简单的排序方法,它的思路是重复的走过要排序的序列,一次比较两个元 ...
- 归并排序 & 计数排序 & 基数排序 & 冒泡排序 & 选择排序 ----> 内部排序性能比较
2.3 归并排序 接口定义: int merge(void* data, int esize, int lpos, int dpos, int rpos, int (*compare)(const v ...
- 数据结构算法集---C++语言实现
//数据结构算法集---C++语言实现 //各种类都使用模版设计,可以对各种数据类型操作(整形,字符,浮点) /////////////////////////// // // // 堆栈数据结构 s ...
- (转)java 排序算法
排序算法汇总(java实现,附源代码) 整理系统的时候发现了原来写的各种算法的总结,看了一下,大吃一惊,那时候的我还如此用心,具体的算法,有的已经模糊甚至忘记了,看的时候就把内容整理出来,顺便在熟 ...
- JavaScript实现常见排序算法
列表 冒泡排序 选择排序 插入排序 快速排序 希尔排序 归并排序 冒泡排序 // 输入:[5, 6, 3, 4, 8, 0, 1, 4, 7] // 输出:[0, 1, 3, 4, 4, 5, 6, ...
随机推荐
- phpexcel 导入导出
导出excel /** * 以下是使用示例,对于以 //// 开头的行是不同的可选方式,请根据实际需要 * 打开对应行的注释. * 如果使用 Excel5 ,输出的内容应该是GBK编码. */ //r ...
- Android 之 下拉框(Spinner)的使用
下拉列表 Spinner. Spinner的使用,可以极大提高用户的体验性.当需要用户选择的时候,可以提供一个下拉列表将所有可选的项列出来.供用户选择. Demo如下,可以留作参考 一.使用数组作为数 ...
- ASP.NET运行机制原理 ---浏览器与IIS的交互过程 自己学习 网上查了下别人写的总结的很好 就转过来了 和自己写的还好里嘻嘻
一.浏览器和服务器的交互原理 (一).浏览器和服务器交互的简单描述: 1.通俗描述:我们平时通过浏览器来访问网站,其实就相当于你通过浏览器去访问一台电脑上访问文件一样,只不过浏览器的访问请求是由被访问 ...
- java map缓存
/** * 缓存池 * @author xiaoquan * @create 2015年3月13日 上午10:32:13 * @see */ public class CachePool { ...
- 开源项目:网页实时通信WebRTC
参考资料 [博客系列] Android WebRTC 音视频开发总结 [环境编译] WebRTC入门指南 各平台WebRTC源码网盘下载 Ubuntu14.04编译WebRTC For Android ...
- curl返回常见错误码
转自:http://blog.csdn.net/cwj649956781/article/details/8086337 CURLE_OK() 所有罚款.继续像往常一样. CURLE_UNSUPPOR ...
- asp.net 在线人数
很网站都有在线人数,这一功能无处不在.现在,我们就介绍在.NET中一个简单明了的方法来统计在线用户的多少,该方法的特点就是充分的利用了ASP.NET的特点,结合global.asax文件,用Appli ...
- ASP.NET验证控件二
RequiredFieldValidator 验证控件 页面布局: <div> <h1>RequiredFieldValidator 验证控件</h1> 用户名 ...
- PHP版实现友好的时间显示方式(例如:2小时前)
完整php类,通常我会配合smary使用,快捷使用 (plugins/function.rdate.php),更多php技术开发就去php教程网,http://php.662p.com <?PH ...
- php final static const成员属性用法
http://www.111cn.net/phper/php/38976.htm 首先来说说final 1.final不能用来修饰成员属性 2.final只能修饰类和方法 作用:被修饰的类不能被子类所 ...