c++实现快速排序

100 篇文章 8 订阅
20 篇文章 0 订阅

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

2、快排步骤:

①分解: 
    
 在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
 注意:划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]): R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys     其中low≤pivotpos≤high。

②求解: 
     
通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

③组合: 
    
 因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

通俗理解核心步骤:

1.i =L; j = R; 将基准数备份形成第一个可以看成空值的a[i]。

2.j--由后向前找比它小的数,找到后把此数填前一个a[i]中。

3.i++由前向后找比它大的数,找到后也把此数填到前一个坑a[j]中。

4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中

3、算法性能

时间复杂度:O(n*lgn)
最坏:O(n^2)
空间复杂度:O(n*lgn)
不稳定。

实现代码:

//先上递归版

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <stack>
using namespace std;
#define  MAX 101
int Partition(int num[], int low, int high)
{	                                 //int pivotkey;这个枢轴的选取很关键,改进版的可以用三数取中,就九数取中等
	int pivotkey = num[low];         //在这里就取第一个元素
	num[0] = pivotkey;               //备份到num【0】,
	while (low < high)
	{
		while (low < high&&num[high] >= pivotkey)
			high--;
		num[low] = num[high];            //不满足循环条件就执行这个语句,因为备份出【low】,所以可以覆盖他,这也是这个while在                                                 //前面的原因。否则【high】会丢失的。
		while (low < high&&num[low] <= pivotkey)
			low++;
		num[high] = num[low];
		                             //交换low,是因为low=pivotkey,比较了。
	}
	num[low] = num[0];
	return low;                         //最后high和low在某一个位置相遇,就是切分部的值。
}

void Qsort1(int num[], int low, int high)   //对随机产生的无序数组进行快速排序,这也是二分法的缺陷之一。
{                                           //快排对很多数据更有优势,可以设置一个数据个数的阈值,才进行快排,这里也是一个优化的地方
	int pivot;//
	if (low < high)
	{
		pivot = Partition(num, low, high);   //轴值所在的位置
		Qsort1(num, low, pivot - 1);         //递归的深度决定了时间的复杂度。
		Qsort1(num, pivot + 1, high);
	}
}

//非递归版,模拟栈的
inline void push2(stack<int> &s, int l, int r)
{
	s.push(r);
	s.push(l);
}
void Qsort(int num[], int l, int r)
{
	stack<int> s;
	push2(s, l, r);
	int lwalker, rwalker, mid;
	while (!s.empty())
	{
		int left = s.top(); s.pop();
		int right = s.top(); s.pop();
		lwalker = left;
		rwalker = right;
		mid = num[(lwalker + rwalker) / 2];
		while (lwalker < rwalker)
		{
			while (num[lwalker] < mid) lwalker++;
			while (num[rwalker]>mid) rwalker--;
			if (lwalker <= rwalker)
			{
				int tmp = num[lwalker];
				num[lwalker] = num[rwalker]; 
				num[rwalker] = tmp;
				lwalker++;
				rwalker++;
			}
		}
		if (lwalker < right)  push2(s, lwalker,right);
		if (rwalker>left)  push2(s, left, rwalker);
	}
}

void input(int num[])//实参传入的数组的首地址,而不是整个数组
{
	int i;
	srand((unsigned)time(NULL));//产生随机函数的随机数种子
	for (i = 1; i < MAX; i++)
	{
		num[i] = rand() % 100;
	}
}
void  output(int num[])
{
	int i;
	for (i = 1; i <= MAX; i++)
	{
		printf("%5d", num[i]);
		if (i % 100 == 0)
			printf("\n");
	}
}
void main()
{ 
	int num[MAX],num2[MAX];
	time_t start, end;
	time(&start);
	input(num);
	cout << "递归排序前:" << endl;
	output(num);

	Qsort1(num, 0,MAX - 1);
	cout << "递归排序后:" << endl;
	output(num);

	input(num2);
	cout << "开始非递归排序,排序前:"<<endl;
    output(num2);

	cout << "非递归排序后:" << endl;
	Qsort(num2, 0, MAX - 1);
	output(num2);

	time(&end);
	cout << "用时为" << end-start << endl;
	system("pause");
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值