java算法系列之一:快速排序算法

1、算法概念。

快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。

2、算法思想。

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

3、实现思路。

①以第一个关键字 K 1 为控制字,将 [K 1 ,K 2 ,…,K n ] 分成两个子区,使左区所有关键字小于等于 K 1 ,右区所有关键字大于等于 K 1 ,最后控制字居两个子区中间的适当位置。在子区内数据尚处于无序状态。

②把左区作为一个整体,用①的步骤进行处理,右区进行相同的处理。(即递归)

③重复第①、②步,直到左区处理完毕。

快速排序的时间主要耗费在划分操作上,对长度为 k 的区间进行划分,共需 k-1 次关键字的比较。

最坏时间复杂度:最坏情况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。因此,快速排序必须做 n-1 次划分,第 i 次划分开始时区间长度为 n-i-1, 所需的比较次数为 n-i(1<=i<=n-1), 故总的比较次数达到最大值 Cmax
=n(n-1)/2=O(n^2) 。如果按上面给出的划分算法,每次取当前无序区的第 1 个记录为基准,那么当文件的记录已按递增序(或递减序)排列时,每次划分所取的基准就是当前无序区中关键字最小(或最大)的记录,则快速排序所需的比较次数反而最多。

最好时间复杂度:在最好情况下,每次划分所取的基准都是当前无序区的“中值”记录,划分的结果与基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数为 O(n×lgn)。

用递归树来分析最好情况下的比较次数更简单。因为每次划分后左、右子区间长度大致相等,故递归树的高度为 O(lgn), 而递归树每一层上各结点所对应的划分过程中所需要的关键字比较次数总和不超过 n,故整个排序过程所需要的关键字比较总次数 C(n)=O(n×lgn) 。因为快速排序的记录移动次数不大于比较的次数,所以快速排序的最坏时间复杂度应为 O(n^2 ),最好时间复杂度为O(n×lgn)。

基准关键字的选取:在当前无序区中选取划分的基准关键字是决定算法性能的关键。

① “三者取中”的规则,即在当前区间里,将该区间首、尾和中间位置上的关键字比较,以三者之中值所对应的记录作为基准,在划分开始前将该基准记录和该区的第 1 个记录进行交换,此后的划分过程与上面所给的 Partition 算法完全相同。

② 取位于 low 和 high 之间的随机数 k(low<=k<=high),用 R[k] 作为基准;选取基准最好的方法是用一个随机函数产生一个位于 low 和 high 之间的随机数 k(low<=k<=high), 用 R[k] 作为基准 , 这相当于强迫 R[low..high] 中的记录是随机分布的。用此方法所得到的快速排序一般称为随机的快速排序。随机的快速排序与一般的快速排序算法差别很小。但随机化后,算法的性能大大提高了,尤其是对初始有序的文件,一般不可能导致最坏情况的发生。算法的随机化不仅仅适用于快速排序,也适用于其他需要数据随机分布的算法。

平均时间复杂度:尽管快速排序的最坏时间为 O(n^2 ), 但就平均性能而言,它是基于关键字比较的内部排序算法中速度最快的,快速排序亦因此而得名。它的平均时间复杂度为 O(n×lgn)。

空间复杂度:快速排序在系统内部需要一个栈来实现递归。若每次划分较为均匀,则其递归树的高度为 O(lgn), 故递归后所需栈空间为 O(lgn) 。最坏情况下,递归树的高度为 O(n), 所需的栈空间为 O(n) 。

稳定性:快速排序是非稳定的。

代码:

	public static void quickSort(int sort[],int left,int right){
		int l=left;
		int r=right;
		int pivot =sort[left];
		if(l <r){
			while(l<r){
				while(l<r&&sort[r]>=pivot){
					r--;
				}

				if(l<r){
					int temp =sort[r];
					sort[r] = sort[l];
					sort[l]=temp;
					l++;
				}

				while(l<r && sort[l]<=pivot){
					l++;
				}

				if(l<r){
					int temp =sort[r];
					sort[r] = sort[l];
					sort[l]=temp;
					r--;
				}
			}
			SortMethod.printSort(sort);
			quickSort(sort,left,l-1);
			quickSort(sort,l+1,right);
		}
	}

实现方法:

	public static void quickSort(int sort[],int left,int right){
		int dp;
		if(left <right){
			dp =partition(sort,left,right);
			SortMethod.printSort(sort);
			quickSort(sort,left,dp-1);
			quickSort(sort,dp+1,right);
		}

	}

	private static int partition(int[] sort, int left, int right) {
		// TODO Auto-generated method stub
		int pivot =sort[left];
		while(left<right){
			while(left<right&& sort[right] >=pivot){
				right--;
			}

			if(left<right){
				sort[left++] =sort[right];
			}

			while(left <right && sort[left] <=pivot){
				left++;
			}

			if(left <right){
				sort[right--] =sort[left];
			}

		}

		sort[left] =pivot;

		return left;
	}

排序调用代码:

public class InsertSort {

	public static void main(String arg[]){

		int a[]={79,32,23,67,28,3,36,76,98,19};
		SortMethod.quickSort(a, 0, a.length-1);
		SortMethod.printSort(a);

	}

}

排序过程:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 08:38:18

java算法系列之一:快速排序算法的相关文章

排序算法系列:快速排序算法

概述 在前面说到了两个关于交换排序的算法:冒泡排序与奇偶排序. 本文就来说说交换排序的最后一拍:快速排序算法.之所以说它是快速的原因,不是因为它比其他的排序算法都要快.而是从实践中证明了快速排序在平均性能上的确是比其他算法要快一些,不然快速一说岂不是在乱说? 本文就其原理.过程及实现几个方面讲解一下快速排序算法. 版权声明 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:Coding-Naga 发表日期:2016年3月1日 链接:http://blog.csdn.n

【数据结构&amp;&amp;算法系列】KMP算法介绍及实现(c++ &amp;&amp; java)

KMP算法如果理解原理的话,其实很简单. KMP算法简介 这里根据自己的理解简单介绍下. KMP算法的名称由三位发明者(Knuth.Morris.Pratt)的首字母组成,又称字符串查找算法. 个人觉得可以理解为最小回溯算法,即匹配失效的时候,尽量少回溯,从而缩短时间复杂度. KMP算法有两个关键的地方,1)求解next数组,2)利用next数组进行最小回溯. 1)求解next数组 next数组的取值只与模式串有关,next数组用于失配时回溯使用. 在简单版本的KMP算法中,每个位置 j 的 n

Javascript算法系列之快速排序(Quicksort)

Javascript算法系列之快速排序(Quicksort) 原文出自: http://www.nczonline.net/blog/2012/11/27/computer-science-in-javascript-quicksort/ https://gist.github.com/paullewis/1981455#file-gistfile1-js 快速排序(Quicksort)是对冒泡排序的一种改进,是一种分而治之算法归并排序的风格 核心的思想就是通过一趟排序将要排序的数据分割成独立的

趣写算法系列之--匈牙利算法(真的很好理解)

[书本上的算法往往讲得非常复杂,我和我的朋友计划用一些简单通俗的例子来描述算法的流程] 匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. -------等等,看得头大?那么请看下面的版本: 通过数代人的努力,你终于赶上了剩男剩女的大潮,假设你是一位光荣的新世纪媒人,在你的手上有N个剩男,M个剩女,每个人都可能对多名异性有好感(-_-

经典算法系列一-快速排序

写一个系列的经典算法,共同学习! 1.快速排序 基本思想: 1.先从数列中取出一个数作为基准数. 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边. 3.再对左右区间重复第二步,直到各区间只有一个数. 在网上看到一篇博客,把快速排序命名为 挖坑填数+分治法,感觉很有道理,所以等会程序就按这两部来写. 先说说挖坑填数的思想: 1.i=L;j=R; 将基数挖出形成第一个坑a[i]. 2.j--由后向前找出比它的小的数,找到后挖出此数填前一个坑a[i]. 3.i++由前向后

底层算法系列:Paxos算法

关于算法,面太广.本系列只研究实际应用中遇到的核心算法.了解这些算法和应用,对java码农进阶是很有必要的. 对于Paxos学习论证过程中,证实一句话:有史以来学习paxos最好的地方wiki:Paxos (computer science) 目录 1.背景 2.Paxos算法 3.Muti-Paxos算法 4.Muti-Paxos在google chubby中的应用 ===============正文分割线============================ 一.背景 Paxos 协议是一

iOS算法(一)置快速排序算法

快速排序是当遇到较大数据时,排序快,高效的方法(公司面试时,基本上会被问到...) 该方法的基本思想是: 1.先从数列中取出一个数作为基准数. 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边. 3.再对左右区间重复第二步,直到各区间只有一个数. 简单地理解就是,找一个基准数(待排序的任意数,一般都是选定首元素),把比小于等于基准数的元素放到基准数的左边,把大于基准数的元素放在基准数的右边.排完之后,在把基准数的左边和右边各看成一个整体, 左边:继续选择基准数把小于等

算法系列之常用算法之一----分治算法

一.基本概念 在计算机科学中,分治法是一种很重要的算法.分治算法,字面上的解释是"分而治之",分治算法主要是三点: 1.将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题----"分" 2.将最后子问题可以简单的直接求解----"治" 3.将所有子问题的解合并起来就是原问题打得解----"合" 这三点是分治算法的主要特点,只要是符合这三个特点的问题都可以使用分治算法进行解决(注意用词,是"

白话经典算法系列之六 快速排序 快速搞定 【转】

快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影. 总的说来,要直接默写出快速排序还是有一定难度的,因为本人就自己的理解对快速排序作了下白话解释,希望对大家理解有帮助,达到快速排序,快速搞定. 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策

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

快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影. 总的说来,要直接默写出快速排序还是有一定难度的,因为本人就自己的理解对快速排序作了下白话解释,希望对大家理解有帮助,达到快速排序,快速搞定. 快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策