快速排序

排序算法——快速排序

拜拜、爱过 提交于 2020-03-06 12:26:41
今天介绍快速排序,这也是在实际中最常用的一种排序算法,速度快,效率高。就像名字一样,快速排序是最优秀的一种排序算法。 思想 快速排序采用的思想是分治思想。 快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正 确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。 举例说明一下吧,这个可能不是太好理解。假设要排序的序列为 2 2 4 9 3 6 7 1 5 首先用2当作基准,使用i j两个指针分别从两边进行扫描,把比2小的元素和比2大的元素分开。首先比较2和5,5比2大,j左移 2 2 4 9 3 6 7 1 5 比较2和1,1小于2,所以把1放在2的位置 2 1 4 9 3 6 7 1 5 比较2和4,4大于2,因此将4移动到后面 2 1 4 9 3 6 7 4 5 比较2和7,2和6,2和3,2和9,全部大于2,满足条件,因此不变 经过第一轮的快速排序,元素变为下面的样子 [1] 2 [4 9 3 6 7 5] 之后,在把2左边的元素进行快排,由于只有一个元素,因此快排结束

C#快速排序类

[亡魂溺海] 提交于 2020-03-06 12:25:06
快速排序的基本思想是基于分治策略的。对于输入的子序列ap..ar,如果规模足够小则直接进行排序,否则分三步处理: 分解(Divide):将输入的序列ap..ar划分成两个非空子序列ap..aq和aq+1..ar,使ap..aq中任一元素的值不大于aq+1..ar中任一元素的值。 递归求解(Conquer):通过递归对p..aq和aq+1..ar进行排序。 合并(Merge):由于对分解出的两个子序列的排序是就地进行的,所以在ap..aq和aq+1..ar都排好序后不需要执行任何计算ap..ar就已排好序。 这个解决流程是符合分治法的基本步骤的。因此,快速排序法是分治法的经典应用实例之一。 using System; namespace VcQuickSort { /// <summary> /// ClassQuickSort 快速排序。 /// 范维肖 /// </summary> public class QuickSort { public QuickSort() { } private void Swap(ref int i,ref int j) //swap two integer { int t; t=i; i=j; j=t; } public void Sort(int [] list,int low,int high) { if(high<=low) { /

基础算法之快速排序Quick Sort

做~自己de王妃 提交于 2020-03-06 11:47:38
原理 快速排序(Quicksort)是对 冒泡排序 的一种改进。 从数列中挑出一个元素,称为" 基准 "(pivot); 排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在本次排序退出之后,该基准就处于数列的中间位置。这个称为 分区 (partition)操作; 递归 地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。 例子 将无序数组[3,6,4,2,5,1]进行快速排序 1) , 先把第一项[3]取出来作为基准 依次与其余项进行比较(3出列后大喝一声,比我小的站前边,比我大的站后边,行动吧!霸气侧漏~), 如果比[3]小就放[3]前边,2 1都比[3]小,全部放到[3]前边 如果比[3]大就放[3]后边,6 4 5比[3]大,全部放到[3]后边, 一趟排完后变成下边这样: 排序前:3,6,4,2,5,1 排序后:2,1,3,6,4,5 2) , 对前面一半[2,1]继续进行快速排序 重复步骤1)后变成下边这样: 排序前:2,1 排序后:1,2 前面一半排序完成,总的数组为: 排序前:2,1,3,6,4,5 排序后:1,2,3,6,4,5 3) ,对后面一半[6,4,5]继续进行快速排序 重复步骤1)后变成下边这样: 排序前:6,4,5 排序后:4,5,6 后面一半排序完成,总的数组为: 排序前

排序算法之快速排序(Quicksort)解析

旧街凉风 提交于 2020-03-06 11:47:29
一.快速排序算法的优点,为什么称之为快排? Quicksort是对归并排序算法的优化,继承了归并排序的优点,同样应用了分治思想。 所谓的分治思想就是对一个问题“分而治之”,用分治思想来解决问题需要两个步骤: 1.如何“分”?(如何缩小问题的规模) 2.如何“治”?(如何解决子问题) 快排的前身是归并,而正是因为归并存在不可忽视的缺点,才产生了快排。归并的最大问题是需要额外的存储空间,并且由于合并过程不确定,致使每个元素在序列中的最终位置上不可预知的。针对这一点,快速排序提出了新的思路:把更多的时间用在“分”上,而把较少的时间用在“治”上。从而解决了额外存储空间的问题,并提升了算法效率。 快排之所以被称为“快”排,是因为它在平均时间上说最快的,主要原因是硬件方面的,每趟快排需要指定一个“支点”(也就是作为分界点的值),一趟中涉及的所有比较都是与这个“支点”来进行比较的,那么我们可以把这个“支点”放在寄存器里,如此这般,效率自然大大提高。除此之外,快排的高效率与分治思想也是分不开的。 二.算法思想 按照快排的思想,对一已知序列排序有如下步骤: 1.指定“支点” 注意,是“指定”,并没有明确的约束条件,也就是说这个支点是任意一个元素,一般我们选择两种支点:当前序列首元,或者随机选取 两种方式各有优劣,前者胜在简单,但可能影响算法效率 快排中,支点的最终位置越靠近中间位置效率越高

※交换排序(1)——快速排序(quick sort)

こ雲淡風輕ζ 提交于 2020-03-06 11:46:55
快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。步骤为: 从序列中挑出一个元素,作为"基准"(pivot). 把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作。 对每个分区递归地进行步骤1~3,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。 快速排序是对冒泡排序的一种改进! 快速排序的代码如下: public static void quickSort(int[] numbers,int low,int high) { if(low < high) {    int middle = getMiddle(numbers,low,high);    quickSort(numbers, low, middle-1);    quickSort(numbers, middle+1, high); } } public static int getMiddle(int[] numbers, int low,int high) { int temp = numbers[low]; while(low < high){ //高位判断 while (low < high && numbers[high] > temp) { high--; }

八大排序(三)-------快速排序

蹲街弑〆低调 提交于 2020-03-06 08:59:47
快速排序法介绍: 快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列 感觉自己能力并不足以将一个问题,或算法讲解的足够清楚,只是在别人的基础上理解,明白了代码的含义,知道了执行的流程,知道了原理,但是要我自己讲述,或者深入的说出其底层原理,做不来 所以很多内容粗糙且模糊,见谅 所以这下面的是我参考的别人的讲解,来源忘了 假设我们现在对“6 1 2 7 9 3 4 5 10 8”这个10个数进行排序。首先在这个序列中随便找一个数作为基准数(不要被这个名词吓到了,就是一个用来参照的数,待会你就知道它用来做啥的了)。为了方便,就让第一个数6作为基准数吧。接下来,需要将这个序列中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边,类似下面这种排列。 3 1 2 5 4 6 9 7 10 8 在初始状态下,数字6在序列的第1位。我们的目标是将6挪到序列中间的某个位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于6,右边的数都大于等于6。想一想,你有办法可以做到这点吗? 给你一个提示吧。请回忆一下冒泡排序,是如何通过“交换”

六、python实现快速排序

拈花ヽ惹草 提交于 2020-03-05 23:48:34
python实现快速排序 第一种(两个指针分别都两头开始) #6.快速排序 时间复杂度O(nlogn) 空间复杂度O(logn) def quick_sort ( L , start , end ) : if start < end : i = start j = end pivot = L [ start ] while i < j : while L [ j ] >= pivot and i < j : j -= 1 L [ i ] , L [ j ] = L [ j ] , L [ i ] while L [ i ] <= pivot and i < j : i += 1 L [ i ] , L [ j ] = L [ j ] , L [ i ] quick_sort ( L , start , i - 1 ) quick_sort ( L , i + 1 , end ) return L L = [ 5 , 6 , 4 , 8 , 2 , 1 , 7 , 3 , 0 , 1 ] print ( quick_sort ( L , 0 , len ( L ) - 1 ) ) 结果#[0, 1, 1, 2, 3, 4, 5, 6, 7, 8] 第二种方法 算法导论版本(两个指针都从头开始) 来源: CSDN 作者: 大大大言言言 链接: https://blog.csdn.net

C++实现排序算法之快速排序

白昼怎懂夜的黑 提交于 2020-03-05 15:07:24
C++实现排序算法之快速排序 时间复杂度:O(N*logN); 算法稳定性:不稳定的排序算法; 1、快速排序的简单介绍   算法思想:基于分治的思想,是冒泡排序的改进型。首先在数组中选择一个基准点(该基准点的选取可能影响快速排序的效率,后面讲解选取的方法),然后分别从数组的两端扫描数组,设两个指示标志(low指向起始位置,high指向末尾),首先从后半部分开始,如果发现有元素比该基准点的值小,就交换low和high位置的值,然后从前半部分开始扫秒,发现有元素大于基准点的值,就交换low和high位置的值,如此往复循环,直到low>=high,然后把基准点的值放到high这个位置。一次排序就完成了。以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。 2、快速排序算法的特点 • 快速排序的时间主要耗费在划分操作上,对长度为k的区间进行划分,共需k-1次关键字的比较; • 最坏情况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。时间复杂度为O(n n); • 在最好情况下,每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数

AcWing 107. 超快速排序

时光毁灭记忆、已成空白 提交于 2020-03-05 08:25:39
在这个问题中,您必须分析特定的排序算法----超快速排序。 该算法通过交换两个相邻的序列元素来处理n个不同整数的序列,直到序列按升序排序。 对于输入序列9 1 0 5 4,超快速排序生成输出0 1 4 5 9。 您的任务是确定超快速排序需要执行多少交换操作才能对给定的输入序列进行排序。 输入格式 输入包括一些测试用例。 每个测试用例的第一行输入整数n,代表该用例中输入序列的长度。 接下来n行每行输入一个整数ai,代表用例中输入序列的具体数据,第i行的数据代表序列中第i个数。 当输入用例中包含的输入序列长度为0时,输入终止,该序列无需处理。 输出格式 对于每个需要处理的输入序列,输出一个整数op,代表对给定输入序列进行排序所需的最小交换操作数,每个整数占一行。 数据范围 0≤N<500000, 0≤ai≤999999999 输入样例: 5 9 1 0 5 4 3 1 2 3 0 输出样例: 6 0 # include <iostream> # include <cstdio> # include <cstring> # include <algorithm> # include <queue> using namespace std ; typedef long long LL ; const int N = 500010 ; LL res ; int n , a [ N ] , b

PAT乙级1045-----快速排序 (25分)

Deadly 提交于 2020-03-04 18:05:11
1045 快速排序 (25分) 输入样例: 5 1 3 2 4 5 输出样例: 3 1 4 5思路:1.首先找可能主元,将所给数组排序然后对比初始数组,找到主元2.对所有可能主元,从左到右遍历一遍初始数组找最大值,将所有可能主元的左侧最大值存储3.对所有可能主元,从右到左遍历一遍初始数组找最小值,将所有可能主元的右侧最小值存储4.可能主元满足主元元素大于左侧最大值小于右侧最小值,则判定为主元5.测试点2输出主元个数为0,但是要输出两个换行,否则会有格式错误(即,输出主元的那行为空,但还要再换一行)首次通过代码: 1 #include<stdio.h> 2 #include<stdlib.h> 3 int a[100005]; 4 int b[100005]; 5 int maybe[100005]; 6 int max[100005]; 7 int min[100005]; 8 int cmp(const void *a,const void *b){ 9 return *(int *)a-*(int *)b; 10 } 11 12 int main(){ 13 int sum; 14 scanf("%d",&sum); 15 for(int i=0;i<sum;i++) 16 {scanf("%d",&a[i]); 17 b[i]=a[i]; 18 } 19 qsort(b