排序算法的C语言实现-快速排序

快速排序是在实践中最快的已知排序算法,它的平均运行时间是O(NlogN),该算法之所以特别的快,主要是由于非常精炼和高度优化的内部循环。它的最坏情形的性能为N^2.

快速排序由下列简单的四步组成:

1.如果S中元素个数是0或1,则返回。

2.取S中任以元素V,称之为枢纽元

3.将S分成俩个不相交的集合,前一个元素都小于V,后一个元素都大于V。

4.返回quicksort(S1)后,加上V,再加上quicksort(S2);

如何选取枢纽元?

有一种安全的方法是随机选取枢纽元,但是产生随机数的代价是很昂贵的,减少不了算法其余部分的平均运行时间。

这里有种方法叫三数中值分割法,枢纽元最好的值是数组的中值,也就是第N/2个最大的数,但是这很难算出,而且严重减慢了算法的速度。那么退而求其次,我们用数组左端,中心,右端位置的中值来做枢纽元。

快速排序的交换策略是这样的:在开始之前将枢纽元和最后一个元素交换,让枢纽元离开要被排序的数组,因为数组排序完后,枢纽元的位置是一定的。i从第一个元素开始,j从倒数第二个元素开始,当i在j左边时,我们将i右移,移过那些小于枢纽元的元素,将j右移,移过那些大于枢纽元的元素。当i,j停止时,i指向一个大于枢纽元的元素,而j指向一个小于枢纽元的元素,这样做的效果最终是所有小于枢纽元的元素都在枢纽元左边,大于枢纽元的元素都在它的右边。从而达到了排序的意愿。

void quickSort(int a[],int length)
{
	Qsort(a,0,length-1);
}

int median3(int a[],int left,int right)	//获得枢纽元,使用三数中值法
{
	int center=(left+right)/2;

	if(a[left]>a[center])
		swap(&a[left],&a[center]);
	if(a[left]>a[right])
		swap(&a[left],&a[right]);
	if(a[center]>a[right])
		swap(&a[center],&a[right]);
	swap(&a[center],&a[right-1]);	//将枢纽元放到数组最后
	return a[right-1];
}

void Qsort(int a[],int left,int right)
{
	int i,j;
	int pivot;

	if((left+3)<=right)
	{
		pivot=median3(a,left,right);
		i=left,j=right-1;
		for(;;)
		{
			while(a[++i]<pivot){}	//因为第一次是a[i]小于pivot,a[j]是大于pivot,所以用++i
			while(a[--j]>pivot){}
			if(i<j)
				swap(&a[i],&a[j]);	//出现等于的情况,交换,平均分配到子数组中
			else
				break;
		}
		swap(&a[i],&a[right-1]);
		Qsort(a,left,i-1);	//在i的位置之前,所有的元素都小于它,在i之后,所有的元素都大于它,所以A[i]的位置不需要变
		Qsort(a,i+1,right);
	}
	else	//当数组很小的时候,只做插入排序,从而退出递归,不需要等到数组长度等于1的时候,因为对于小数组来说,插入排序好过快速排序
		insertionSort(a+left,right-left+1);	//插入排序例程在前面的文章中已经实现了
}

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

时间: 2024-07-31 17:13:16

排序算法的C语言实现-快速排序的相关文章

排序算法总结(C语言版)

1.    插入排序 1.1     直接插入排序 1.2     Shell排序 2.    交换排序 2.1     冒泡排序 2.2     快速排序 3.    选择排序 3.1     直接选择排序 3.2     堆排序 4.    归并排序 4.1     二路归并排序 4.2     自然合并排序 5.    分布排序 5.1     基数排序 1.插入排序 1.1      直接插入排序 将已排好序的部分num[0]~num[i]后的一个元素num[i+1]插入到之前已排好序的

深入排序算法的多语言实现

深入浅出排序算法的多语言实现 作者:白宁超 2015年10月8日20:08:11 摘要:十一假期于实验室无趣,逐研究起数据结构之排序.起初觉得就那么几种排序,两三天就搞定了,后来随着研究的深入,发觉里面有不少东西.本文介绍常用的排序算法,主要从以下几个方面:算法的介绍.算法思想.算法步骤.算法优缺点.算法实现.运行结果.算法优化等.最后对本文进行总结.本文为作者原创,程序经测试无误.部分资料引用论文和网络材料以及博客,后续参见参考文献.(本文原创,转载注明出处) 1 排序的基本概念 排序: 所谓

常用排序算法的C语言实现

最近看数据结构,把常用的排序算法用C语言写了一下. 没有按数据结构上的定义SqList结构体,只是用数组的形式实现. 有的算法并没有完全按书上给出的算法,但思路一致. #include<stdio.h> void InsertSort(int[], int); //直接插入排序 无哨兵 void BInsertSort(int[], int); //折半插入排序 void BubbleSort(int[], int); //起泡排序 void QSort(int[], int, int); /

【最全】经典排序算法(C语言)

本文章包括所有基本排序算法(和其中一些算法的改进算法): 直接插入排序.希尔排序.直接选择排序.堆排序.冒泡排序.快速排序.归并排序.基数排序. 算法复杂度比较: 算法分类 一.直接插入排序 一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中. 它的算法步骤可以大致归纳如下: 从未排好的序列中拿出首元素,并把它赋值给temp变量: 从排好的序列中,依次与temp进行比较,如果元素比temp大,则将元素后移(实际上放置temp的元素位置已经空出) 直到

排序算法的C语言实现(上 比较类排序:插入排序、快速排序与归并排序)

总述:排序是指将元素集合按规定的顺序排列.通常有两种排序方法:升序排列和降序排列.例如,如整数集{6,8,9,5}进行升序排列,结果为{5,6,8,9},对其进行降序排列结果为{9,8,6,5}.虽然排序的显著目的是排列数据以显示它,但它往往可以用来解决其他的问题,特别是作为某些成型算法的一部分. 总的来说,排序算法分为两大类:比较排序 和 线性时间排序. 比较排序依赖于比较和交换来将元素移动到正确的位置上.它们的运行时间往往不可能小于O(nlgn). 对于线性时间排序,它的运行时间往往与它处理

几种经典排序算法的R语言描述

1.数据准备 # 测试数组 vector = c(5,34,65,36,67,3,6,43,69,59,25,785,10,11,14) vector ## [1] 5 34 65 36 67 3 6 43 69 59 25 785 10 11 14 2.R语言内置排序函数 在R中和排序相关的函数主要有三个:sort(),rank(),order(). sort(x)是对向量x进行排序,返回值排序后的数值向量; rank()是求秩的函数,它的返回值是这个向量中对应元素的“排名”; order()

排序算法(Java语言)——归并排序

归并排序mergesort中基本的操作是合并两个已排序的表.因为这两个表已排序,所以若将输出放到第三个表中,则该算法可以通过对输入数据一趟排序完成.基本的合并算法是取两个输入数组A和B,一个输出数组C,以及3个计数器Actr.Bctr.Cctr,他们初始置于对应数组的开始端.A[Actr]和B[Bctr]中的较小者被拷贝到C的下一个位置,相关的计数器向前推进一步.当两个输入表有一个用完的时候,则将另一个表中剩余部分拷贝到C中. 合并另个已排序的表的时间显然是线性的,因为最多进行N-1次比较,其中

经典排序算法学习笔记之二——快速排序

一.快速排序 数据结构 不定 最差时间复杂度 O(n^2) 最优时间复杂度 O (n*log n) 平均时间复杂度 O (n*log n) 最差空间复杂度 根据实现的方式不同而不同 https://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F 1.算法思想: 从数列中挑出一个元素,称为"基准"(pivot), 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边

排序算法之三路划分的快速排序

当待排序元素序列中有大量的重复排序码时,简单的快速排序算法的效率将会降到非常之低.一种直接的想法就是将待排序列分成三个子序列:一部分是排序码比基准元素排序码小的:一部分是与基准元素排序码等值的:一部分是比基准元素排序码大的,如下图所示: 但是,如果我们直接据此思想去编写实现算法的话,会让我们面临很大的困难.与基准元素等值的元素到底有多少?以及如何最快速有效地确定划分的边界?所以,完成这样的三路划分是非常困难的,甚至比两路划分过程更加复杂. 我们可以基于以下的思想实现三路划分:在划分的过程中,扫描