快速排序

一 概述

快速排序也是交换排序中的一种,它基于分治的思想:在待排序表L[1 ... n]中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的两部分L[1 ... k-1]和L[k ... n],使得L[1 ... k-1]中的所有元素小于privot,同时L[k+1 ... n]中的所有元素大于等于pivot,则pivot放在了其最终位置上,这个过程称为一趟快速排序(或一次划分)。然后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止。即所有元素放在了其最终位置上。

二 快速排序的过程

一趟快速排序的过程是一个交替搜索和交换的过程,如序列49 38 65 97 76 13 27 49,设置两个指针分别指向头部和尾部。取第一个元素49为基准值并将其赋值给pivot。

 

三 代码实现快速排序

#include<stdio.h>

int Partitions(int a[], int low, int high){
	
	int pivot = a[low]; //将当前表中的第一个元素设置为基准值,对表进行划分
	while(low < high) { //循环跳出条件
		
		while(low < high && a[high] >= pivot) --high;
		a[low] = a[high]; //将小于基准值的元素移动到左端
		
		while(low < high && a[low] <= pivot) ++low;
		a[high] = a[low]; //将大于基准值的元素移动到右端
	}
	
	a[low] = pivot;
	
	return low; //返回存放基准值的最终位置
}

void QuickSort(int a[], int low, int high){
	
	if(low < high){ //递归跳出的条件
		
		int partition = Partitions(a,low,high);
		QuickSort(a,low,partition-1); //递归小的部分
		QuickSort(a,partition+1,high);//递归大的部分
	} 
}

int main() {
	
	int b[] = {-1,49,38,65,97,76,13,27,49};
	QuickSort(b,1,8);
	for(int i = 1; i < 9; i++) {
		printf("%d ",b[i]);
	}
	return 0;
}

异常:

原因:将Partitions(int a[],int low,int high)函数放在QuickSort(int a[],int low,int high)之后声明于实现。

结果展示:

四 算法性能分析

算法最好时间最坏时间平均时间额外空间/空间复杂度稳定性
快速插入排序O(nlog2^n)O(n^2)O(nlog2^n)O(log2^n)不稳定

空间效率:由于快速排序是递归的,需要借助一个递归工作栈来保存每层递归调用的必要信息,其容量应与递归调用的最大深度一致,最好情况下为O(log2^n);最坏情况下,因为要进行n-1此递归调用,所以栈的深度为O(n);在平均情况下,栈的深度为O(log2^n)。

时间效率:快速排序的运行时间与划分是否对称有关,快速排序的最坏情况发生在两个区域分别包含n-1个元素和0个元素,这种最大程度上的不对称若发生在每层递归上,即对应于初始排序表基本有序或基本逆序时,就得到了最坏情况下的时间复杂度为O(n^2)。

提高算法效率的方法:尽量选取一个可以将数据中分的基准元素,如从序列的头尾及中间选取三个元素,再取这三个元素的中间值作为最终的基准值,或者是随机地从当前表中选取基准元素,这样作可以使得最坏情况在实际排序中几乎不会发生。

稳定性:在划分算法中,若右端区间有两个相同的关键字,且均小于基准值的记录,则在交换的左端区间后,它们的相对位置会发生变化,即快速排序算法不是一种稳定的排序算法。如表L = {3,2,2},经过一趟排序后L = {2,2,3},显然,2与2的相对次序已经发生了变化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值