快速排序

快速排序 quicksort

爷,独闯天下 提交于 2021-01-27 06:34:46
快速排序是一种最常见的高效排序算法,时间复杂度为 O ( n 2 ) ,但是平均的时间复杂度是 O(n·lgn) 。而且可以证明,随机选取参照值的快速排序的时间复杂度期望值为 O(n·lgn) 。 C语言中已经存在快速排序的函数qsort: #include <stdlib.h> void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); 本文 仿照该函数的结构,提供了 随机化快速排序的一种实现,还包括了两个可以作为函数指针参数的比较函数,分别是整形比较函数comparInt和字符串比较函数comparStr。 #include <stdio.h> #include <string.h> #include <stdlib.h> void *quicksort(void *base, size_t nmeb, size_t size, int(*compar)(const void *, const void *)) { if (nmeb < 2) return; int i, j, key; key = rand() % nmeb; swap(base, base + key * size, size); i = 1; j = nmeb - 1; while

冒泡排序,快速排序、选择排序及二分法查找思想回顾

。_饼干妹妹 提交于 2020-04-07 13:28:45
回顾冒泡排序、快速排序,直接选择排序以及递归思想。快速排序和二分查找都融入了分而治之的思想,一分再分,递归之。 1、冒泡排序 相邻元素之间逐对两两比较,若不符合预期则先交换位置再继续比较,如此,每次比较都能把最大或最小的元素放在预期位置,直到完成排序。 2、快速排序 1、准备工作:先选定一个参考值,设置两个指针(设为i,j,分别指向数字序列的头和尾)。 2、同时从数字序列的两头进行扫描对比,将大于参考值的数字都放于参考值的一侧,小于参考值的数字置于另一侧。直到i,j指向同一个位置,这个位置即为参考值的预期位置,设为m。 3、对大于参考值一侧,令i=m+1,对小于参考值的一侧,令j=m-1。再分别对参考值的两侧重复步骤1、2。 4、重复步骤1、2、3,直到i>j。 public static int getMiddle(int[] array, int i, int j) {   int key = array[i];   while(i<j)   {   //从前向后扫描     while (i<j && array[j]>key)      {       j--;      }   array[i] = array[j];   //从后向前扫描     while (i<j && array[i]<key)     {       i++;     }   array[j]

浙大PAT 1045. 快速排序(25)

流过昼夜 提交于 2020-04-02 07:23:03
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的N个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元? 例如给定N = 5, 排列是1、3、2、4、5。则: 1的左边没有元素,右边的元素都比它大,所以它可能是主元; 尽管3的左边元素都比它小,但是它右边的2它小,所以它不能是主元; 尽管2的右边元素都比它大,但其左边的3比它大,所以它不能是主元; 类似原因,4和5都可能是主元。 因此,有3个元素可能是主元。 输入格式: 输入在第1行中给出一个正整数N(<= 10 5 ); 第2行是空格分隔的N个不同的正整数,每个数不超过10 9 。 输出格式: 在第1行中输出有可能是主元的元素个数;在第2行中按递增顺序输出这些元素,其间以1个空格分隔,行末不得有多余空格。 输入样例: 5 1 3 2 4 5 输出样例: 3 1 4 5 关于这道题目 网上已经有的两种解法 ,具体的不做细讲,大家进去看即可 正反遍历法:http://www.kkun.cc/articles/67 基于主元位置不变法:http://blog.csdn.net/gq_bob/article/details/49520161 今天我想讲的方法是 单次遍历排除法(总之时间复杂度不是O(N

随手编程---快速排序(QuickSort)-Java实现

此生再无相见时 提交于 2020-03-27 19:32:46
背景 快速排序,是在上世纪60年代,由美国人东尼·霍尔提出的一种排序方法。这种排序方式,在当时已经是非常快的一种排序了。因此在命名上,才将之称为“快速排序”。这个算法是二十世纪的七大算法之一,平均情况下时间复杂度为Ο(nlogn),而且在O(nlogn)的情况下,实际的运算速度都要快于其他同时间复杂度的排序方法。 对东尼·霍尔以及快速排序的提出背景感兴趣的同学,可以看看这篇介绍:http://www.nowamagic.net/librarys/veda/detail/2391 排序思想 快速排序的思路想到很困难,但是理解起来却非常容易 他的思路是这样的: 1、先选定队列中,某一个元素为基数Value(一般选择头元素,或尾元素)。 2、将基数Value依次与所有元素比较大小。按照比较结果将元素分为两个队列A、B。一个所有元素比基数Value大,一个所有元素比基数Value小。 3、将A作为新的队列,再次选定基数,然后分成两个更小的队列 4、就这样一直将每一个小的队列无限的拆分成更小的两个队列。 5、一直到一个队列已经拆分成不能拆封为止(也就是一个元素) 6、因为队列之间的顺序都是固定的。将这些队列一次组合起来,整体的排序就算完成了。 (防盗连接:本文首发自http://www.cnblogs.com/jilodream/ ) 注意这里有两个最核心的步骤,就是 1、选出Value元素

PAT1045—— 快速排序

﹥>﹥吖頭↗ 提交于 2020-03-25 06:10:24
著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的N个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元? 例如给定N = 5, 排列是1、3、2、4、5。则: 1的左边没有元素,右边的元素都比它大,所以它可能是主元; 尽管3的左边元素都比它小,但是它右边的2它小,所以它不能是主元; 尽管2的右边元素都比它大,但其左边的3比它大,所以它不能是主元; 类似原因,4和5都可能是主元。 因此,有3个元素可能是主元。 输入格式: 输入在第1行中给出一个正整数N(<= 10 5 ); 第2行是空格分隔的N个不同的正整数,每个数不超过10 9 。 输出格式: 在第1行中输出有可能是主元的元素个数;在第2行中按递增顺序输出这些元素,其间以1个空格分隔,行末不得有多余空格。 输入样例: 5 1 3 2 4 5 输出样例: 3 1 4 5 对快排的理解还很浅显,不能把题目的意思和快排的枢纽联系起来,只能通过字面意思来做题。就是某个数的前面都是比它小,后面都是比它大的,就是答案集合中的一个。那么肯定它正好在排序好之后的位置,所以和排序好后的数列比较,并且要符合前面说的要求。 代码转自:http://blog.csdn.net/fang_abc/article/details

快速排序和归并排序

♀尐吖头ヾ 提交于 2020-03-21 18:33:41
#include<iostream> using namespace std; #define ElemType int const int Maxn=105; int Partition(ElemType A[],int low,int high){ ElemType pivot=A[low]; int i=low,j=high; while(i<j){ while(i<j&&A[j]>=pivot)j--; A[i]=A[j]; while(i<j&&A[i]<=pivot)i++; A[j]=A[i]; } A[i]=pivot; return i; } void QuickSort(ElemType A[],int low,int high){ if(low<high){ int pivotPos=Partition(A,low,high); QuickSort(A,low,pivotPos-1); QuickSort(A,pivotPos+1,high); } } //时间:最好和平均O(n*log2(n)) 最坏O(n^2) //空间:最好和平均O(log2(n)) 最坏O(n) //不稳定 void Merge(ElemType A[],int low,int mid,int high){ int i,j,k; ElemType *B=new ElemType

快速排序详解 Java实现

旧街凉风 提交于 2020-03-20 22:10:03
3 月,跳不动了?>>> 一、快速排序的优缺点 对一个东西,首先要讲他的利与弊,才知道怎么使用它。快速排序适用于各种不同的输入数据且在一般应用中比其他排序都要快得多。 快速排序引人注目的特点包括它是原地排序(只需要一个很小的辅助栈),且长度为N的数组排序所需的时间和NlgN成正比 。它的主要缺点是非常脆弱,在实现时要非常小心才能避免低劣的性能。 有了对比,才能知道它的好处。其实快速排序是一种分治的排序算法。它将一个数组分成两个子数组,将两部分独立地排序。讲到这里,有人就会有个疑问,那不是和归并排序一样吗?合并排序也是分治算法的一种,也是将一个数组分成两个子数组。 快速排序和归并排序时互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以整个数组排序;而快速排序将数组排序的方式则是当两个数组都有序时整个数组也就自然有序了。在第一种情况下,递归调用发生在处理整个数组之前;在第二种情况下,递归调用发生在处理整个数组之后。在归并排序中,一个数组被等分为两半;在快速排序中,切分的位置取决于数组的内容。 这句话最重要。 二、快速排序的实现 public class Quick{ public static void sort(Comparable[] a){ StdRandom.shuffle(a);//消除对输入的依赖,直接生成随机数 sort(a,0,a.length-1);

快速排序

孤者浪人 提交于 2020-03-20 21:57:37
3 月,跳不动了?>>> 1、思想 每次选出一个基准,然后将数组剩下的元素分为两部分,一部分小于基准放到左边,一部分大于基准放到右边。然后对基准左右两部分分别做同样处理,分治思想。 2、时间复杂度 最快 O(nlogn) ,最坏 O (n^2) ,平均 O(nlogn) 。 3、代码实现 //常规版 public class quickSort { public static void QuickSort(int[] arr){ QSort(arr, 0, arr.length-1); } private static void QSort(int[] arr, int low, int hight) { int pivot; if(low < hight){ pivot = Partition(arr, low, hight); QSort(arr, low, pivot-1); QSort(arr, pivot+1, hight); } } private static int Partition(int[] arr, int low, int hight) { if(arr == null || low < 0 || hight >= arr.length){ new Exception(); } int pivotkey = arr[low]; while(low <

随机快速排序(使用Python描述)

被刻印的时光 ゝ 提交于 2020-03-20 12:51:56
title   代码复制自 随机快速排序的实现-夜雨最萌 .和快速排序一样呀😂   随机快速排序与快速排序的思路一样,差异就是取主元之前,随机快速排序多了一个步骤:而随机快速排序是随机取得一个元素,但是又会与最后一个元素交换位置.取得主元的下标位置实际上还是最后一个下标.快速排序是习惯取得最后一个元素. 此算法特性 此算法适用场景 代码实现 import random def random_quicksort(a,left,right): if(left<right): mid = random_partition(a,left,right) random_quicksort(a,left,mid-1) random_quicksort(a,mid+1,right) def random_partition(a,left,right): ######################################## t = random.randint(left,right) #生成[left,right]之间的一个随机数 a[t],a[right] = a[right],a[t] ######################################## # 相比经典随机快速排序,增加了上面两行代码 x = a[right] i = left-1 #初始i指向一个空

快速排序和堆排序

心不动则不痛 提交于 2020-03-20 07:47:12
快速排序思想:在partition中,首先以最右边的值作为划分值x,分别维护小于x的区间,等于x的区间,以及大于x的三个区间,最后返回划分值的左边界和右边界.时间复杂度为O(nlogn). public class QuickSort { public static void quickSort(int[] arr) { if(arr == null || arr.length < 2) return ; sortProgress(arr, 0 , arr.length - 1); } public static void sortProgress(int[] arr, int L, int R) { if(L < R) { //随机取L到R之间的一个数与R交换. swap(arr, L + (int)(Math.random() * (R - L + 1)), R); //p数组的大小为2,p[0]表示划分值的左边界,p[1]表示划分值的右边界. int[] p = partition(arr, L, R); sortProgress(arr, L, p[0] - 1); sortProgress(arr, p[1] + 1, R); } } public static int[] partition(int[] arr, int L, int R) { int less = L