快速(quick)排序算法

快速排序是不稳定的排序。

1、快速排序的基本思想

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常撑起为分治法。分治法的基本思想是:将原问题分解为若规模更小但结构与原问题相似的子问题。递归地解决这些子问题,然后将这些子问题的解组合为原问题的解。

快速排序的基本思想:设当前的待排序的无序区为A[low..high],利用分治可描述为:

(1) 分解:

在A[low...high]中任选一个记录作为基准(pivot也叫中轴或者枢纽),依此基准将当前无序区划分为左、右两个较小的自取件A[low...pivot[pos-1]]和A[pivot[pos+1]...high]

并使左边子区间中所有记录的关键字均小于基准记录(pivot),右边的子区间中所有记录的关键字均大于等于pivot,而基准的记录pivot则位于正确的位置上,它无需在参加后续的排序。注意,划分的关键是要求出基准记录所在的位置pivot[pos]。划分的结果可以简单的表示为:A[low...pivot[pos-1]]<=A[pivot[pos]]<=A[pivot[pos+1]...high],其中low<=pivot[pos]<=high。

(2) 求解:

通过递归调用快速排序对左右子区间A[low...pivot[pos-1]]和A[pivot[pos-1]+1...high]排序。

(3) 组合:

当“求解”步骤中的两个递归调用结束时,子左右两个子区间已有序。对排序排序而言,“组合”步骤无需做什么,可以看做空操作。

2、思想

它是由冒泡排序改进而来的。在待排序的n个记录中任取一个记录(通常取第一个记录),把该记录放入适当位置后,数据序列被此记录划分成两部分。所有关键字比该记录关键字小的记录放置在前一部分,所有比它大的记录放置在后一部分,并把该记录排在这两部分的中间(称为该记录归位),这个过程称作一趟快速排序。

说明:最核心的思想是将小的部分放在左边,大的部分放到右边,实现分割。

3、算法复杂度

最好的情况下:因为每次都将序列分为两个部分(一般二分都复杂度都和logN相关),故为 O(N*logN)

最坏的情况下:基本有序时,退化为冒泡排序,几乎要比较N*N次,故为O(N*N)

4、稳定性

由于每次都需要和中轴元素交换,因此原来的顺序就可能被打乱。如序列为 5 3 3 4 3 8 9 10 11会将3的顺序打乱。所以说,快速排序是不稳定的!

5、代码实现

<pre name="code" class="cpp">//编程实现快速排序
//1.快速排序是比较复杂的排序,其中需要知道数组的下标,低位下标要是大于高位下标的话,不进行排序
//2.其中每次取第一个数当做分割点pivot=a[low],循环到低位下标大于高位下标终止循环,这样就确定了pivot的位置。
//3.遍历pivot右边的元素(a[j]>=pivot),若小于pivot将元素放到pivot的左边(a[i++]=a[j]),第一次放的位置为low.
//4.之后遍历low右侧的元素,若大于pivot将元素放到pivot的右边(a[j--]=a[i]),第一次放的位置为high.
//5.3、4步的大前提是低位下标小于高位下标.
//6.终止循环之后,将pivot放到中间位置(a[i]=pivot).
//7.再将low到i-1,也就是pivot的左侧进行同样排序,i+1到high,pivot的右侧进行同样排序。

#include<iostream>
using namespace std;

void quick_sort(int a[], int low, int high)		//low和high均为数组的下标
{
	//因为在递归的时候需要low和high的位置,所以需要拷贝low和high
	int i;	//第一个元素下标
	int j;	//最后一个元素下标
	int pivot;   //pivot是区间的第一个元素,也是快速排序的枢纽(以他为中间元素,在他的左边元素都是小于他的,右边的元素都是大于他的)
	if (low < high)		//递归的终止条件是,区间完全重合
	{
		pivot = a[low];
		i = low;
		j = high;
		while (i < j)		//找到中间位置(快速排序的终止条件)
		{
			while (i < j && a[j] >= pivot)		//筛选比pivot小的元素
				j--;
			if (i < j)				//中间位置大前提
				a[i++] = a[j];			//将比pivot小的元素赋给区间的第一个元素

			while (i < j && a[i] <= pivot)		//筛选比pivot大的元素
				i++;
			if (i < j)				//中间位置大前提
				a[j--] = a[i];			//将比pivot大的元素赋给比pivot小的元素位置
		}
		a[i] = pivot;					//pivot移到最终位置,枢纽中间位置
		quick_sort(a, low, i - 1);			//对左侧递归排序
		quick_sort(a, i + 1, high);			//对右侧递归排序
	}
}

static void print_sort(int a[], int len)
{
	for (int i = 0; i < len; i++)			<span style="white-space:pre">	</span>//打印数组
		cout << a[i] << " ";
}
void main9mianshiti4()
{
	int a[] = { 83, 38, 96, 23, 15, 72, 60, 45, 54 };
	cout << "before quick sort:";
	print_sort(a, 9);					//打印数组
	quick_sort(a, 0, 8);					//快速排序
	cout << "\nafter quick sort:";
	print_sort(a, 9);
	system("pause");
}


 6、测试结果 

before quick sort:83 38 96 23 15 72 60 45 54

after quick sort:15 23 38 45 54 60 72 83 96

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值