【算法】C++快速排序算法

本文介绍了快速排序的基本概念,包括其工作原理、分治策略、选择基准元素的方法(如首元素或随机选取),以及单边循环法的元素交换过程。提供了C++代码示例,展示了如何通过递归实现升序快速排序。
摘要由CSDN通过智能技术生成

一、快速排序简介

       快速排序是一种交换排序,通过元素之间的比较和交换位置来达到排序的目的。

       常见的冒泡排序在每一轮中只把1个元素冒泡到数列的一端,而快速排序则在每一轮挑选一个基准元素(pivot),并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成两个部分。 这种思路就叫作分治法,如下图所示。

       如图所示,在分治法的思想下,原数列在每一轮都被拆分成两部分,每一部分在下一轮又分别被拆分成两部分,直到不可再分为止。 每一轮的比较和交换,需要把数组全部元素都遍历一遍,时间复杂度是O(n)。 假如元素个数是n,平均情况下需要遍历logn轮,因此快速排序算法总体的平均时间复杂度是O(nlogn)

       但如果每次选取的基准元素都是数列未排序部分的最大值或最小值,每轮就只能确定基准元素这一个元素的位置,无法发挥分治法的优势,因此快速排序的最差时间复杂度是O(^{n^{2}})。

       常见的基准元素选取方法有两种:每次选取数组的首元素,或者每次随机选取元素。


二、元素交换方法

       选定了基准元素以后,下一步要做的就是把其他元素中小于基准元素的都交换到基准元素一边,大于基准元素的都交换到基准元素另一边。

       主要有两种方法:双边循环法单边循环法

       双边循环法的代码实现有些繁琐,这里就只介绍单边循环法。

       单边循环法只从数组的一边对元素进行遍历和交换,使用了一种双指针法,下面的详细过程出自魏梦舒的《漫画算法:小灰的算法之旅》:

       在把pivot元素交换到mark指针所在位置后,返回mark值,以便从mark左右两边继续进行二分。


三、完整实现代码

完整快速排序代码如下:

//升序快排

#include <iostream>
using namespace std;

//分治(单边循环法)
int partition(int* arr, int startIndex, int endIndex) {
	int pivot = arr[startIndex];	//取第1个位置的元素为基准元素
	int mark = startIndex;
	for (int i = startIndex + 1; i <= endIndex; i++) {
		if (arr[i] < pivot) {
			mark++;
			int temp = arr[mark];
			arr[mark] = arr[i];
			arr[i] = temp;
		}
	}
	arr[startIndex] = arr[mark];
	arr[mark] = pivot;
	return mark;
}

void quickSort(int* arr, int startIndex, int endIndex) {
	if (startIndex >= endIndex) {	//递归结束条件
		return;
	}
	int pivotIndex = partition(arr, startIndex, endIndex);	//得到基准元素位置
	quickSort(arr, startIndex, pivotIndex - 1);	//根据基准元素,分成两部分进行递归排序
	quickSort(arr, pivotIndex + 1, endIndex);
}

void test() {
	int arr[] = { 3, 2, 1, 6, 5, 4, 9, 8, 7 };
	int len = sizeof(arr) / sizeof(arr[0]);

	cout << "排序前:" << endl;
	for (int i = 0; i < len; i++) {
		cout << arr[i] << " ";
	}
	cout << endl;

	quickSort(arr, 0, len - 1);

	cout << "排序后:" << endl;
	for (int i = 0; i < len; i++) {
		cout << arr[i] << " ";
	}
	cout << endl;
}

int main() {

	test();

	system("pause");
	return 0;
}

运行结果如下:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值