当前位置: 首页 > article >正文

C++数据结构X篇_23_快速排序(最快、不稳定的排序)

文章参考十大经典排序算法-快速排序算法详解进行整理补充。快速排序是最快的排序方法。
排序思路:分治法-挖坑填数大问题分解为各个小问题,对小问题求解,使得大问题得以解决

文章目录

  • 1. 什么是快速排序
    • 1.1 概念
    • 1.2 算法原理
    • 1.3 算法实现
      • 1.3.1 核心代码
      • 1.3.2 整体代码
  • 2. 快速排序算法特点
    • 2.1 时间复杂度
    • 2.2 空间复杂度
    • 2.3 稳定性

1. 什么是快速排序

1.1 概念

快速排序(Quick Sort)是从冒泡排序算法演变而来的,实际上是在冒泡排序基础上的递归分治法。快速排序在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成了两个部分。

1.2 算法原理

这是一个无序数列:4、5、8、1、7、2、6、3,我们要将它按从小到大排序。按照快速排序的思想,我们先选择一个基准元素,进行排序。
在这里插入图片描述
我们选取4为我们的基准元素,并设置基准元素的位置为index(可以看做一个坑位,比较后满足条件的就填进去),设置两个指针left和right,分别指向最左和最右两个元素
在这里插入图片描述
接着,从right指针开始,把指针所指向的元素和基准元素做比较,如果比基准元素大,则right指针向左移动,如果比基准元素小,则把right所指向的元素填入index中

3和4比较,3比4小,将3填入index中,原来3的位置成为了新的index,同时left右移一位
在这里插入图片描述
然后,我们切换left指针进行比较,如果left指向的元素小于基准元素,则left指针向右移动,如果元素大于基准元素,则把left指向的元素填入index中

5和4比较,5比4大,将5填入index中,原来5的位置成为了新的index,同时right左移一位
在这里插入图片描述
接下来,我们再切换到right指针进行比较,6和4比较,6比4大,right指针左移一位
在这里插入图片描述
2和4比较,2比4小,将2填入index中,原来2的位置成为新的index,left右移一位
在这里插入图片描述
随着left右移,right左移,最终left和right重合
在这里插入图片描述
此时,我们将基准元素填入index中,这时,基准元素左边的都比基准元素小,右边的都比基准元素大,这一轮交换结束
在这里插入图片描述
第一轮,基准元素4将序列分成了两部分,左边小于4,右边大于4,第二轮则是对拆分后的两部分进行比较

此时,我们有两个序列需要比较,分别是3、2、1和7、8、6、5,重新选择左边序列的基准元素为3,右边序列的基准元素为7
在这里插入图片描述
第二轮排序结束后,结果如下所示
在这里插入图片描述
此时,3、4、7为前两轮的基准元素,是有序的,7的右边只有8一个元素也是有序的,因此,第三轮,我们只需要对1、2和5、6这两个序列进行排序
在这里插入图片描述
第三轮排序结果如下所示
在这里插入图片描述
至此所有的元素都是有序的.

1.3 算法实现

1.3.1 核心代码

//快速排序  升序
void quick_sort(int arr[], int start, int end)
{
	int i = start;
	int j = end;
	int temp = arr[start];//基准数
	if (i < j)
	{
		while (i < j)
		{
			//从右往左找比基准数小的
			while (i < j && arr[j] >= temp)
			{
				j--;
			}
			//填坑
			if (i < j)
			{
				arr[i] = arr[j];
				i++;
			}
			//从左向右找比基准数大的数
			while (i < j && arr[i] < temp)
			{
				i++;
			}
			//填坑
			if (i < j)
			{
				arr[j] = arr[i];
				j--;
			}
		}
		//基准数放入i=j中
		arr[i] = temp;
		//对基准数左半部分快速排序
		quick_sort(arr, start, i - 1);
		//对基准数右半部分快速排序
		quick_sort(arr, j + 1, end);
	}

}

1.3.2 整体代码

#include <iostream>
using namespace std;

void swap(int* a, int* b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}

//打印数组
void printArr(int arr[])
{
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << endl;
	}
}

//快速排序  升序
void quick_sort(int arr[], int start, int end)
{
	int i = start;
	int j = end;
	int temp = arr[start];//基准数
	if (i < j)
	{
		while (i < j)
		{
			//从右往左找比基准数小的
			while (i < j && arr[j] >= temp)
			{
				j--;
			}
			//填坑
			if (i < j)
			{
				arr[i] = arr[j];
				i++;
			}
			//从左向右找比基准数大的数
			while (i < j && arr[i] < temp)
			{
				i++;
			}
			//填坑
			if (i < j)
			{
				arr[j] = arr[i];
				j--;
			}
		}
		//基准数放入i=j中
		arr[i] = temp;
		//对基准数左半部分快速排序
		quick_sort(arr, start, i - 1);
		//对基准数右半部分快速排序
		quick_sort(arr, j + 1, end);
	}

}

int main()
{
	int arr[] = { 8,2,3,9,6,4,7,1,5,10 };
	quick_sort(arr,0,9);
	printArr(arr);
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

2. 快速排序算法特点

2.1 时间复杂度

快速排序算法在分治法的思想下,原数列在每一轮被拆分成两部分,每一部分在下一轮又分别被拆分成两部分,直到不可再分为止,平均情况下需要logn轮,因此快速排序算法的平均时间复杂度是O(nlogn)

在极端情况下,快速排序算法每一轮只确定基准元素的位置,时间复杂度为O(N^2)

2.2 空间复杂度

快速排序算法排序过程中只是使用数组原本的空间进行排序,因此空间复杂度为O(1)

2.3 稳定性

快速排序算法在排序过程中,可能使相同元素的前后顺序发生改变,所以快速排序是一种不稳定排序算法

  1. 快速排序1,快速排序2,参考博文:常见的几种排序(C++)

http://www.kler.cn/a/105658.html

相关文章:

  • 高级java每日一道面试题-2024年11月07日-Redis篇-Redis有哪些功能?
  • Dart:字符串
  • 华为云租户网络-用的是隧道技术
  • 如何合理设计一套springcloud+springboot项目中的各个微服务模块之间的继承关系的最优方案
  • JavaWeb——JS、Vue
  • 【51单片机】LCD1602液晶显示屏
  • 用 Rust 和 cURL 库制作一个有趣的爬虫
  • MYSQL8-sql语句使用集合。MYCAT-sql语法使用集合
  • Java后端开发——实现登录验证程序
  • 计算机网络——理论知识总结(下)
  • 个人记账理财软件 Money Pro mac中文版软件介绍
  • Fabric.js 讲解官方demo:Stickman
  • 单链表新增删除节点操作
  • COSCon'23媒体和社区合作伙伴正式公布!百川相聚,潮汇大海,邀您天府之城共话开源!...
  • 私有云:【1】ESXI的安装
  • vue项目中定制化音频展示,wavesurfer.js基本使用
  • CTF-Web(3)文件上传漏洞
  • Leetcode—2520.统计能整除数字的位数【简单】
  • 【每日一题】切割后面积最大的蛋糕
  • Hyperledger Fabric搭建测试网络
  • Go 的连接池、重试和超时
  • 2011-2021年“第四期”数字普惠金融指数与上市公司匹配(根据省份匹配)/上市公司数字金融指数匹配
  • Python 继承和子类示例:从 Person 到 Student 的演示
  • Python遍历删除列表元素的一个奇怪bug
  • k8s部署kafka,并使用zookeeper做注册中心
  • 探索JavaScript ES6+新特性