白话经典算法系列之六 高速排序 高速搞定

白话经典算法系列之六 高速排序 高速搞定

 
高速排序因为排序效率在同为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]中。

照着这个总结非常easy实现挖坑填数的代码:

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,有的书上是以中间的数作为基准数的,要实现这个方便非常方便,直接将中间的数和第一个数进行交换就能够了。

 

 转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/6684558

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109540.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 工业大数据的价值体现_如何分析转型带来的价值

    工业大数据的价值体现_如何分析转型带来的价值工业视角的转变        如果说前三次工业革命分别从机械化、规模化、标准化、和自动化等方向大幅度地提高了生产力,那么第四次工业革命与前面三次最大的区别在于:不再以制造端的生产力需求为出发点,而是将客户端价值作为整个产业链的核心,改变以往的工业价值链从生产端向消费端、上游向下游推动的模式,从客户端的价值需求出发提供客制化的产品和服务,并以此作为整个产业链的共同目标使整个产业链的各个环节实现协同优…

    2022年9月27日
    4
  • 易语言画板组件实现自绘圆形进度条源码

    易语言画板组件实现自绘圆形进度条源码进度条是易语言常用的一个组件,有时候我们想让进度有个性,比如绘制一个圆形进度条,下面封装了子程序,直接调用就可以了。窗口用到三个编辑框,一个时钟,一个标签,一个画板,三个颜色选择器,效果如下图,我们可以灵活调整双环椭圆大小,颜色等等。一、源码:.版本2.子程序画圆进度条,整数型.参数画板,画板,,画板名称.参数最小位置,双精度小数型,,进度条的最小初始值.参数当前位置,双精度小数型,,返回当前的位置.参数最大位置,双精度小数型,,进度条的最大位置

    2022年7月26日
    3
  • javascript(js)小数精度丢失的解决方案

    原因:js按照2进制来处理小数的加减乘除,在arg1的基础上将arg2的精度进行扩展或逆扩展匹配,所以会出现如下情况.javascript(js)的小数点加减乘除问题,是一个js的bug如0.3*

    2021年12月25日
    39
  • C#中File和FileStream的用法

    C#中File和FileStream的用法在近期的工作过程中发现自己的基础比较薄弱,所以最近在恶补基础知识。下面就对我所学习的File类和FileStream进行简单的总结。1.首先先介绍File类和FileStream文件流1.1File类,是一个静态类,支持对文件的基本操作,包括创建,拷贝,移动,删除和打开一个文件。File类方法的参量很多时候都是路径path。主要提供有关文件的各种操作,在使用时需要引用System.IO命名…

    2022年7月24日
    19
  • AIRFLow_overflow百度百科

    AIRFLow_overflow百度百科1、什么是AirflowAirflow是一个Airbnb的Workflow开源项目,使用Python编写实现的任务管理、调度、监控工作流平台。Airflow是基于DAG(有向无环图)的任务管理系统,可以简单理解为是高级版的crontab,但是它解决了crontab无法解决的任务依赖问题。与crontab相比Airflow可以方便查看任务的执行状况(执行是否成功、执行时间、执行依赖等),可追踪任务历史执行情况,任务执行失败时可以收到邮件通知,查看错误日志。2、Airflow与同类产品的

    2025年8月6日
    3
  • awk详解「建议收藏」

    awk详解「建议收藏」awk是linux中处理文本的强大工具,或者说是一种专门处理字符串的语言,它有自己的编码格式。awk的强大之处还在于能生成强大的格式化报告。awk的命令格式如下:其中常用选项有-F、-f等选项,后面会介绍。例如&amp;gt;awk-F:'{print$1}’file表示把file文件中每行数据以“:”分割后,打印出第一个字段。下面详细介绍使用方式。以下示例如不做…

    2022年7月11日
    14

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号