`
youthon
  • 浏览: 17604 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

快速排序 快速搞定

 
阅读更多

最近参考MoreWindows的博客学习了一下快速排序,感觉写得太好了,转一下

原文地址:http://blog.csdn.net/morewindows/article/details/6684558

==========================

快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影。

总的说来,要直接默写出快速排序还是有一定难度的,因为本人就自己的理解对快速排序作了下白话解释,希望对大家理解有帮助,达到快速排序,快速搞定

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

该方法的基本思想是:

1.先从数列中取出一个数作为基准数。

2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

3.再对左右区间重复第二步,直到各区间只有一个数。

虽然快速排序称为分治法,但分治法这三个字显然无法很好的概括快速排序的全部步骤。因此我的对快速排序作了进一步的说明:挖坑填数+分治法

先来看实例吧,定义下面再给出(最好能用自己的话来总结定义,这样对实现代码会有帮助)。

以一个数组作为示例,取区间第一个数为基准数。

0

1

2

3

4

5

6

7

8

9

72

6

57

88

60

42

83

73

48

85

初始时,i = 0; j = 9; X = a[i] = 72

由于已经将a[0]中的数保存到X中,可以理解成在数组a[0]上挖了个坑,可以将其它数据填充到这来。

从j开始向前找一个比X小或等于X的数。当j=8,符合条件,将a[8]挖出再填到上一个坑a[0]中。a[0]=a[8]; i++; 这样一个坑a[0]就被搞定了,但又形成了一个新坑a[8],这怎么办了?简单,再找数字来填a[8]这个坑。这次从i开始向后找一个大于X的数,当i=3,符合条件,将a[3]挖出再填到上一个坑中a[8]=a[3]; j--;

数组变为:

0

1

2

3

4

5

6

7

8

9

48

6

57

88

60

42

83

73

88

85

i = 3; j = 7; X=72

再重复上面的步骤,先从后向前找,再从前向后找

从j开始向前找,当j=5,符合条件,将a[5]挖出填到上一个坑中,a[3] = a[5]; i++;

从i开始向后找,当i=5时,由于i==j退出。

此时,i = j = 5,而a[5]刚好又是上次挖的坑,因此将X填入a[5]。

数组变为:

0

1

2

3

4

5

6

7

8

9

48

6

57

42

60

72

83

73

88

85

可以看出a[5]前面的数字都小于它,a[5]后面的数字都大于它。因此再对a[0…4]和a[6…9]这二个子区间重复上述步骤就可以了。

对挖坑填数进行总结

1.i =L; j = R; 将基准数挖出形成第一个坑a[i]。

2.j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。

3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。

4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中。

照着这个总结很容易实现挖坑填数的代码:

int AdjustArray(int s[], int l, int r) //返回调整后基准数的位置
{
	int i = l, j = r;
	int x = s[l]; //s[l]即s[i]就是第一个坑
	while (i < j)
	{
		// 从右向左找小于x的数来填s[i]
		while(i < j && s[j] >= x) 
			j--;  
		if(i < j) 
		{
			s[i] = s[j]; //将s[j]填到s[i]中,s[j]就形成了一个新的坑
			i++;
		}

		// 从左向右找大于或等于x的数来填s[j]
		while(i < j && s[i] < x)
			i++;  
		if(i < j) 
		{
			s[j] = s[i]; //将s[i]填到s[j]中,s[i]就形成了一个新的坑
			j--;
		}
	}
	//退出时,i等于j。将x填到这个坑中。
	s[i] = x;

	return i;
}

再写分治法的代码:

void quick_sort1(int s[], int l, int r)
{
	if (l < r)
    {
		int i = AdjustArray(s, l, r);//先成挖坑填数法调整s[]
		quick_sort1(s, l, i - 1); // 递归调用 
		quick_sort1(s, i + 1, r);
	}
}

这样的代码显然不够简洁,对其组合整理下:

//快速排序
void quick_sort(int s[], int l, int r)
{
    if (l < r)
    {
		//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
        int i = l, j = r, x = s[l];
        while (i < j)
        {
            while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
				j--;  
            if(i < j) 
				s[i++] = s[j];
			
            while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
				i++;  
            if(i < j) 
				s[j--] = s[i];
        }
        s[i] = x;
        quick_sort(s, l, i - 1); // 递归调用 
        quick_sort(s, i + 1, r);
    }
}

快速排序还有很多改进版本,如随机选择基准数,区间内数据较少时直接用另的方法排序以减小递归深度。有兴趣的筒子可以再深入的研究下。

注1,有的书上是以中间的数作为基准数的,要实现这个方便非常方便,直接将中间的数和第一个数进行交换就可以了。

分享到:
评论

相关推荐

    白话经典算法系列之六 快速排序 快速搞定 - MoreWindows - 博客园1

    1.先从数列中取出一个数作为基准数 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边 3.再对左右区间重复第二步,直到各区间只有一个

    c++,排序,快速排序

    总的说来,要直接默写出快速排序还是有一定难度的,因为本人就自己的理解对快速排序作了下白话解释,希望对大家理解有帮助,达到快速排序,快速搞定。 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用...

    Quicksort(ruby 快速排序)

    一个ruby写的简单快速排序程序,一个快排搞定各种类型数据排序,默认的是随机生成随机长度的数组,输出排序后的结果。去掉注释符号“#”,并把随机函数注释掉也可以手动输入数组(注意ruby读取数据是按换行符,手动...

    几十张无水印图完美搞定面试官经常问的十大经典排序算法(含C语言代码.rar

    快速排序 简介 复杂度与稳定性 过程介绍 图示过程 主要代码实现 计数排序 简介 复杂度与稳定性 过程介绍 图示过程 代码实现 桶式排序 简介 复杂度与稳定性 过程介绍 图示过程 代码实现 基数排序 ...

    面试之排序算法

    排序算法是我们面试被问到最多的基础算法,本课程详细介绍了七种排序算法,包括插入排序、选择排序、冒泡排序、谢尔排序、快速排序、堆积排序和二路并归排序。每种算法都详细介绍了核心思想、详细步骤、时间复杂度和...

    模块化多电平变换器MMC在三相不平衡工况下的仿真模型,三种控制目标(抑制交流测负序电流、抑制有功功率二次脉动、抑制无功功率二次脉

    本仿真模型中单桥臂二十子模块(子模块电压1kV),采用最近电平逼近NLM调制,并使用快速排序算法完成子模块均压,仿真中使用二倍频环流抑制,真动稳态性能良好,附带仿真介绍文档,详细讲述仿真搭建过程,并附带参考...

    轻松搞定XML

    XML文件以有效率的结构和卷标来储存其所包含的信息,因此浏览器可以使用较弹性的方式来寻找、撷取、排序、筛选、排列和处理信息。XML提供了一个理想的解决方法来处理快速增加的网站数据量和信息复杂度的问题。

    Spring Data JPA.rar

    在Spring Boot 2.x版本中可以非常轻松、快速搞定持久层的开发动作,配置比SpringBoot+MyBatis还少,偶觉得它除了执行效果不如MyBatis外,在使用效率的情况下,使用Spring Data JPA的开发速度会比较MyBatis还快。...

    Toad 使用快速入门

    Toad 使用快速入门 目录 一.Toad功能综述 二.系统需求 三.安装指南 四.快速入门 1. Schema browser的用法简介 2. SQL Editor的使用介绍 3. Procedure Editor的用法介绍 4. 如何进行PLSQL的debug 5. 如何...

    一款《华创通用信息系统》,各种信息管理,全部搞定!

    可按任意条件进行查询、排序,支持模糊查询,可将常用的查询条件保存起来,再次使用直接调出即可;数据可导入、导出、复制、批量修改。 可设置公式字段,可完全按照自己的计算要求设置公式表达式,运算方式多种多样...

    正则表达式必知必会(sam teach you regex)

    最经典的regex快速入门手册,扫描版,重新整理排序,一天搞定,立即应用!

    word使用技巧大全

    17、轻松搞定单元格数据斜向排 86 18、快速去掉页眉的横线 86 19、为奇偶页制作不同的水印 86 20、快捷绘图 87 21、快速去除超链接 87 22、如何避免标题排在一页的底部 87 23、如何将文档中的某一页改为横向 87 24、...

    FMLayoutKit:自定义CollectionView的布局,可以快速实现瀑布流,标签布局,商品详情,各种电商首页等,悬停,拖拽排序等等功能丰富,可以穿插布局(垂直水平),多种布局样式让你专注业务

    FMLayoutKit简介一个可以让你更快的搞定复杂页面(电商首页,方格+列表多样式布局)的CollectionView自定义布局,目前支持纵向横向布局,可以穿插布局,动态cell高度做一些适配可以做到自动计算高度,也可以手动计算...

    菜鸟啃Excel

    介绍怎样输入数据才是正确的,如何妙用单元格格式,能吹毛成猴、以一变十的复制技巧,快速锁定目标的技巧,排序的玩法,从沙粒中优选小麦——筛选,慧眼识数——便捷查看数据的技巧,轻松搞定打印设置,随心所欲做...

    EuoSoft通用信息管理系统(V3.35简体中文版)

    排序、统计和全屏显示一键搞定,多种替换选择令处理信息更灵活,即时保存功能可避免重要数据丢失事故的发生 几乎无处不在的右击菜单、丰富的帮助系统和众多的快捷键支持,充分体现了专业设计水准 可与Excel和...

    afinal0.5.1框架 支持android下assets文件夹下图片加载

    FinalDb:android中sqlite的orm框架,一行代码搞定增删改查。 此次更新内容如下: 1、finalDb 修复排序查询的bug 2、FinalDB 添加dropDb方法 (感谢 kvgnt 在github上push代码) 3、FinalBitmap 重新设计了 缓存...

    GBBS微论坛 v3.2(新年版).rar

    GBBS微论坛,界面简约,...6、话题排序精确为时间排序 7、修正手机版有时不能发贴   覆盖文件:bbs_admin_hf.asp tb_gl.asp filesc.asp admin_setup.asp 更新文件:bbsview.asp bbslist.asp dbconn.asp conn.asp

    云上铺会员管理系统 v4.18.zip

    管商品:添加商品、管理库存、进货出货、盘点,全部搞定! 消费收银:快速消费、商品消费、记次消费、房台消费、套餐消费一样也不能少! 备注说明:手机端有些设置需要去pc端完成完整的使用。 云上铺会员管理...

    【MySQL面试第二弹】MySQL 服务占用cpu 100%,如何排查问题?

    对于互联网公司,线上CPU飙升的问题很常见(例如某个活动开始,流量突然飙升时),按照本文的步骤排查,基本1分钟即可搞定!特此整理排查方法一篇,供大家参考讨论提高。 二、问题复现 线上系统突然运行缓慢,CPU...

Global site tag (gtag.js) - Google Analytics