算法 - 快速排序(Quick_sort)
目录
什么是快速排序?
快速排序的使用场景:
演示快速排序的过程:
第一趟排序:
第二趟排序:
通过代码来实现:
对快速排序的总结:
什么是快速排序?
在写快速排序的代码之前,我们先对快速排序的排序原理以及定义进行梳理:
快速排序(Quick_sort)是对冒泡排序的一种改进,它也是属于冒泡类的方法。它的基本思想是通过一趟排序将待排序列分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后对这两部分的分割后的序列再次进行排序,直到达到整个序列有序的目的。
快速排序相当于是冒泡排序升级版本,排序特点就是越乱越快,所以也是一种高效的算法。快速排序就是一个给基准数据并找到其正确索引位置的过程。
快速排序的使用场景:
对于数据量大,数据分布高度随机的场景,使用快速排序算法的效率是非常高的,甚至高于堆排序。
演示快速排序的过程:
我在这里给出来一个随机数组:
int ar[11] = {12,21,6,3,23,2,3,2,1,14,3};
我们用一个总图来描绘快速排序的过程:
在这里我重新给出一个数组我们分步来分析:
int ar[10] = {4,7,9,6,5,3,10,2,8,1};
第一趟排序:
接下来我们在画板上演示快速排序的过程:
在这里我们首先选定基准元素,基准元素的选择是随机的,我们为了方便起见直接选择序列的第一个元素4作为基准元素,然后我们定义两个指针变量分别指向序列的开始和序列的末尾。我们把基准元素拿出来,此时第一个元素的位置就相当于是一个坑。
我们从右边的指针开始,把指针指向的元素和基准元素做比较,如果指针所指向的元素比基准元素大则把指针向左移动,如果指针所指向的元素是小于基准元素的我们则把指针所指向的元素填入坑中。我们发现此时的1是小于4的,则把1填入至坑中。
这时1原本的位置成为了新的坑,同时p指针向后移动一位,此时我们发现p所指向的元素7是大于基准元素4的,于是我们把7填入坑的位置。
此时7原本的位置又成为了新的坑,我们现在将q指针向左移动,碰到了元素8大于基准元素,不动,直到碰到比基准元素小的数停下,此时q停到了2的位置,2 < 4我们这时将2填入坑的位置。
此时2原本的位置成为了新的坑,p指针向右移动,我们碰到了元素9,元素9是大于基准元素的,此时将元素9填入到坑的位置。
继续上述操作,原本9的位置变为了新的坑,q指针继续向左移动,我们发现当q指向元素3的时候,3小于基准元素,于是将3填入坑的位置。
原本3的位置变为了新坑,p指针向后移动我们发现元素6大于基准元素,于是将6填入坑中。
此时原本6的位置变为了新坑,q指针继续向左移动,移动一位发现元素5是大于基准元素的,所以5元素不动,继续向左移动,此时p指针和q指针相撞,这时我们将基准元素填回现在的坑中,此时第一趟排序完成。
我们更改元素的颜色,此时原基准元素4 左侧的蓝色方框的元素代表小于基准元素的区域,右侧黄色方格的元素代表大于基准元素的区域,
第二趟排序:
现在相当于我们在基准元素的两侧又重新分为了两列,左边的都小于基准元素,右边的都大于基准元素。然后这两列数列使用刚才的方法进行第二趟排序,这也是分治法的思想。
此时我们先对4左侧的元素进行快速排序:
此时我们将2元素拿出来当作基准元素,从右侧q指针所指向的元素进行比较,我们发现3大于1,继续将q指针向左侧移动,我们发现2大于1,q向左移动与p指针对撞,排序结束,将基准元素放回坑的位置。继续将2作为基准元素,从右侧指针q开始比较,我们发现3大于2,位置不动,q指针向左侧移动与p指针相撞排序结束。
现在我们对4右侧的元素进行快速排序:
此时我们将5元素拿出来当作基准元素,5的位置为坑,q指针指向的元素开始和基准元素做比较,q指针每一次向左移动所指向的元素均是大于5的,位置不动,直到q指针和p指针相撞,排序结束。
第二趟我们用6作为基准元素,q现在向左边移动我们发现q每一次的移动所指向的元素均是大于6的,所以他们的位置不动。p指针所指向的5元素是小于6元素的,位置不动,现在重新将6元素置于坑中。
左子序列现在的长度仅为1,所以无需再做比较。此时我们将元素10作为基准元素拿出来,10原来的位置为坑,从右侧q指针所指向的元素7开始比较,我们发现7是小于10元素的,所以我们将7填入坑中(原来10的位置)。现在移动左侧p指针,p指针向后移动的每一个元素都是小于基准元素的,我们将10元素填入坑中,此时序列为:
指针对撞,第三趟排序结束。现在我们开始第四趟排序,将9作为基准元素拿出来,p指针指向9所在的位置:
现在从右侧q指针开始比较,10是大于9的位置不动,q向左迁移一位,8是小于9的,我们将8填入坑中,此时指针p向后迁移一位与指针q对撞,将9置于新的坑中,第四趟排序结束。
我们现在进行第五趟排序,右自序列的长度为 1,已经不需要再比较,排序完成。
通过代码来实现:
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
#define MAXSIZE 11
void initar(int *ar,int len)
{assert(ar != nullptr);for(int i = 0;i < len;i++){ar[i] = rand() % 30;}
}
void showar(int *ar,int len)
{assert(ar != nullptr);for(int i = 0;i < len;i++){printf("%d ",ar[i]);}printf("\n--------------------------\n");
}
void Quick_sort(int *ar,int left,int right)
{assert(ar != nullptr);if(left >= right){return;}int i = left;//使用i下标代表左边界int j = right;//使用j下标代表右边界int pivot = ar[i];//pivot代表的就是基准元素,将i下标对应的元素取出当作基准元素while(i < j){//循环条件为左边界小于右边界while(i < j && ar[j] >= pivot)//循环条件为当右侧j下标对应的元素大于基准元素时j--;//j下标向左迁移一位ar[i] = ar[j];//将j下标对应的值挪到坑的位置,这里可以理解为将值赋给i下标对应的元素位置,也就是大的往前挪while(i < j && ar[i] <= pivot)//循环条件为当右侧下标j对应的值小于基准元素时i++;//i下标向右侧迁移一位ar[j] = ar[i];//就是把小值往后挪,进行赋值操作}ar[i] = pivot;//基准元素更新Quick_sort(ar,left,i - 1);//递归,基准元素的左半部分Quick_sort(ar,i + 1,right);//递归,基准元素的右半部分
}
int main()
{srand((unsigned int)time(NULL));int ar[MAXSIZE];initar(ar,MAXSIZE);printf("原始数据为:\n");showar(ar,MAXSIZE);printf("\n经过快速排序后的数据为:\n");Quick_sort(ar,0,MAXSIZE - 1);showar(ar,MAXSIZE);return 0;
}
运行结果:
排序完成
对快速排序的总结:
快速排序(Quick_sort)的特点就是:序列越乱越快,越有序越慢。
时间复杂度:
最优情况:O(nlogn)每趟排序数据元素都能被平均分配成两个部分,形成一个完美的二叉树。
最坏情况:O()也就是原序列相对最有序的情况,形成的树只有左子树和右子树,比较次数为:(n - 1) + (n - 2) + (n - 3)+……+ 1 = n * (n - 1)/2
空间复杂度:
O(1)
和希尔排序类似,序列元素的比较与交换是跳跃进行的,会改变元素的相对位置,所以快速排序依旧是一个不稳定算法,但这也不妨碍它是所有排序算法中平均效率最高的算法。
算法 - 快速排序(Quick_sort)相关推荐
- 读《c#与算法--快速排序》随笔
<c#与算法--快速排序>地址: http://www.cnblogs.com/isun/archive/2009/04/25/1443603.html 随手写的测试DEMO,web程序不 ...
- 排序算法 | 快速排序,算法的图解、实现、复杂度和稳定性分析与优化
今天讲解一下快速排序算法的原理以及实现.复杂度和稳定性分析与优化 目录 1 快速排序的原理 2 快速排序代码实现 3 复杂度和稳定性分析.优化 4 习题练习 1 快速排序的原理 快速排序是所有内部排序 ...
- 快速排序 java导包_排序算法-快速排序(Java实现)
上篇我们讲了冒泡排序,这次我们讲它的升级版快速排序,"快速",一看就是个好算法~ 快速排序(QuickSort)是啥? 我们先看下百度百科的介绍快速排序(Quicksort)是对冒 ...
- 排序算法 快速排序 python 0913
排序算法 快速排序 python 0913 快速排序 思路 定义快排方法 接收参数:原始列表,起始位置,终止位置 判断是否符合快排条件,当起始下标与终止下标相等时,代表只有一个元素,无法排序,退出 一 ...
- 排序算法 快速排序【详细步骤图解】
排序算法 快速排序[详细步骤图解] 快速排序 主要思想 图解 第一轮分割序列 第二轮分割序列 --- 左子序列 小结 第三轮分割序列 --- 右子序列 C++实现 总结 快速排序 给定一个序列:22 ...
- 【图解算法】排序算法——快速排序
简介 首先还是得简单的介绍一下快速排序这个算法. 快速排序(Quicksort),又称划分交换排序(partition-exchange sort),一种排序算法,最早由东尼·霍尔提出.在平均状况下, ...
- JavaScript的排序算法——快速排序
排序算法(Sorting algorithm)是计算机科学最古老.最基本的课题之一.要想成为合格的程序员,就必须理解和掌握各种排序算法. 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排 ...
- 十大经典排序算法-快速排序算法详解
十大经典排序算法 十大经典排序算法-冒泡排序算法详解 十大经典排序算法-选择排序算法详解 十大经典排序算法-插入排序算法详解 十大经典排序算法-希尔排序算法详解 十大经典排序算法-快速排序算法详解 十 ...
- 算法:快速排序实现 定制比较函数
1. 快速排序基本算法 1 #include<stdio.h> 2 const static int NUM = 47; 3 4 int quick_sort(int *a, int st ...
最新文章
- Injection of @Reference dependencies failed;
- 解读Java8中ConcurrentHashMap是如何保证线程安全的
- 数据库acid简介(一)
- android的NDK和java进行本地socket通信
- SQL中删除重复的行(重复数据),只保留一行 转
- POJ 3518 Prime Gap(素数题)
- RTMP协议从入门到放弃
- Selection change event Issue is fixed handleListItemPress,SingleSelectMaster
- C语言 select
- MYSQL IFNULL函数的使用
- 关系数据库、NoSQL和NewSQL数据库产品分类
- Ubuntu操作系统
- AD格式生产文件Gerber文件的制作
- 华为手机最大屏是几英寸的_华为有史以来最大屏幕的手机,屏幕尺寸高达7.12寸,性价比很好!...
- Tensorflow C++接口部署python深度学习训练模型
- expected at least 1 bean which qualifies as autowire candidate for this ***错误的分析
- 在不同linux服务器上复制anaconda的虚拟环境注意事项
- python append()方法
- java -p_javap使用实例图解
- 超静音服务器性能强,超静音办公室专用 戴尔T20微服务器评测