快速排序

排序算法之——归并排序和快速排序

最后都变了- 提交于 2019-12-06 10:59:24
冒泡排序、插入排序、选择排序这三种算法的时间复杂度都为 \(O(n^2)\) ,只适合小规模的数据。今天,我们来认识两种时间复杂度为 \(O(nlogn)\) 的排序算法——归并排序(Merge Sort)和快速排序(Quick Sort),他们都用到了 分治思想 ,非常巧妙。 1. 归并排序(Merge Sort)? 1.1. 归并排序算法实现 归并排序 的核心思想其实很简单,如果要排序一个数组,我们先把数组从中间分成前后两部分,然后分别对前后两部分进行排序,再将排好序的两部分数据合并在一起就可以了。 归并排序使用的是分治思想,分治也即是分而治之,将一个大问题分解为小的子问题来解决。分治算法一般都是用递归来实现的。 分治是一种解决问题的处理思想,递归是一种编程技巧 。 如果要对数组区间 [p, r] 的数据进行排序,我们先将数据拆分为两部分 [p, q] 和 [q+1, r],其中 q 为中间位置。对两部分数据排好序后,我们再将两个子数组合并在一起。当数组的起始位置小于等于终止位置时,说明此时只有一个元素,递归也就结束了。 递推公式: merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r)) 终止条件: p >= r 不用再继续分解 对两个子数组进行合并的过程如下所示,我们先建立一个临时数组

快速排序的java实现

旧时模样 提交于 2019-12-06 08:04:18
package com.sort;/** * @Auth wxr * @Date 2019 */public class QuickSort { public static void sortNumLeft(int [] source,int from,int to){ if(source.length>1&&to-from>0) { int curse = source[from]; int j = from; for (int i = from + 1; i < to + 1; i++) { if (curse > source[i]) { int ss = source[i]; for (int k = i; k > j; k--) { source[k] = source[k - 1]; } source[j] = ss; j++; } } sortNumLeft( source, 0, j -1 ); sortNumRight( source, j + 1, source.length - 1 ); } } public static void sortNumRight(int [] source,int from,int to){ if(source.length>1&&to-from>0) { int curse = source[from]; int j =

数据结构之内外排序

喜你入骨 提交于 2019-12-06 06:59:06
一、内排序 排序类别 排序方法 最好时间复杂度 平均时间复杂度 最坏时间复杂度 辅助空间 稳定性 备注 插入类 插入 O(n) O(n 2 ) O(n 2 ) O(1) 稳定 大部分已排序时较好 希尔排序 - O(n s ),1<s<2 - O(1) 不稳定 s是所选分组 交换类 冒泡排序 O(n) O(n 2 ) O(n 2 ) O(1) 稳定 n小时较好 快速排序 O(nlogn) O(nlogn) O(n 2 ) O(logn) 不稳定 n大时较好 选择类 选择 O(n 2 ) O(n 2 ) O(n 2 ) O(1) 不稳定 n小时较好 堆排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定 n大时较好 归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 稳定 n大时较好 基数排序 O(d(n+rd)) O(d(n+rd)) O(d(n+rd)) O(rd) 稳定 见下文 1.插入排序(InsertSort) 插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的

快速排序的优化

浪尽此生 提交于 2019-12-06 06:55:35
  在我的上一篇博客中(https://www.cnblogs.com/algorithm-process/p/11963856.html),我们提到了快速排序划分的三钟方法,在快速排序中,我们希望对序列进行划分时,能将一个序列进行两等分,但是我们在使用时始终选取第一个元素为基准值,这样就会导致在一些情况(比如是降序排列的序列)下,无法将序列进行等分或是近似等分。如果我们每次选择基准值是一个中间值是不是能尽可能的将待排序的序列做到一个趋近于等分的情况呢?接下来就是由这种思想而提出的优化方法。  三点中值法   思想:在左边界p,右边界r和中间下标mid所代表的元素之间选择一个作为基准点,选择方法为 找到这三个值中中间那个作为基准点。    代码如下: 1 int partition(int a[],int p,int r){ 2 //选取一个基准点 3 int midIndex= p+((r-p)>>1);//中间下标 4 int midValue=-1;//中间值下标 5 if(a[p]<=a[midIndex]&&a[p]>=a[r]) midValue=p; 6 else if(a[r]<=a[midIndex]&&a[r]>=a[p]) midValue=r; 7 else midValue=midIndex; 8 swap(a[midValue],a[p]); 9 10

快速排序

我只是一个虾纸丫 提交于 2019-12-06 06:27:09
快速排序的介绍 快速排序(quick sort)的采用了 分治 的策略。 分治策略指的是: 将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。 快排的基本思想是: 在序列中找一个划分值,通过一趟排序将 未排序的序列 排序成 独立的两个部分,其中左边部分序列都比划分值小,右边部分的序列比划分值大,此时划分值的位置已确认,然后再对这两个序列按照同样的方法进行排序,从而达到整个序列都有序的目的。 先来看一个 我更想称之为伪快排的快排代码 def quick_sort(array): if len(array) < 2: return array else: pivot = array[0] less_than_pivot = [x for x in array if x <= pivot] more_than_pivot = [x for x in array if x > pivot] return quick_sort(less_than_pivot) + [pivot] + quick_sort(more_than_pivot) 这段代码最关键的是pivot这个参数,这段代码里取序列的第一个元素,然后以这个元素为分组的基准,利用 列表解析式 使得它左边的值都比它小,右边的值都比它大。然后再分别对这些序列进行递归排序。

快速排序

此生再无相见时 提交于 2019-12-06 05:23:53
  快速排序为什么被称之为 快速 排序呢?从字面意思上来看肯定是因为它比较快啦。当然实际上也是这样,相比于其他的排序算法,它的平均的时间复杂度为O(nlogn),这可以说是很快的一种排序算法了。当然在某些情况下,也会出现比其他排序算法慢的情形,所以 没有什么最好的排序算法,只有最合适的排序算法 。所以在平常应用的时候要根据实际情况来选择合适的排序算法。   拿为什么快排比较快呢?因为它每次进行了划分,选择一个基准值后,将这个待排序序列分成了小于基准值的一半和大于基准值的一半,然后继续进行相同的操作,知道最后的一半只剩下一个元素。   对快速排序算法的描述:     1.分解:数组A[p...r]被划分为连个子数组A[p...q-1]和A[q+1...r],使得A[p...q-1]中所有的数都比A[q]小,A[q+1...r]中所有的数都比A[q]大;     2.解决:通过递归调用快速排序,对子数组A[p...q-1]和A[q+1...r]进行排序;     3.合并:因为数组原址排序,所进行完之后数组A[p...r]已经有序。   代码如下: 1 quicksort(int a[],int l,int r){//快排递归形式 2 if(l<r){ 3 int q=partition(a,l,r);//找到中间数,不一定是中位数 4 quicksort(a,l,q-1); 5

3. 快速排序

坚强是说给别人听的谎言 提交于 2019-12-06 04:24:02
  快速排序( Quick Sort )与冒泡排序均为 交换类排序 。快排是对冒泡排序的一种改进。由于 关键字的比较和交换是跳跃进行 的,因此,快速排序是一种 不稳定 的排序方法。 0. 序 1. 冒泡排序 2. 快速排序 2.1 基本思想 2.2 一趟快速排序(一趟划分) 2.3 过程 2.4 实现 2.5 复杂度分析 2.5.1 时间复杂度(包含证明) 2.5.2 空间复杂度 0. 序   快速排序算法最早由图灵奖获得者 Tony Hoare 设计出来的,他在形式化方法理论以及 ALGOL60 编程语言的发明中都有卓越的贡献,是上世纪最伟大的计算机科学家之一。   快速排序被列为 20 世纪十大算法之一。   1. 冒泡排序   假设在排序过程中,记录序列 R[1...n] 的状态为:   更多的冒泡排序讲解见 https://www.cnblogs.com/datamining-bio/p/9715774.html   2. 快速排序   快速排序也是通过不断比较和移动交换来实现排序的,只不过它的实现,增大了记录的比较和移动的距离,将 关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减少了总的比较次数和移动交换次数 。   2.1 基本思想   通过一趟排序将待排记录 分割成独立的两部分 ,其中一部分记录的关键字均比另一部分记录的关键字小

java实现快速排序,归并排序

十年热恋 提交于 2019-12-05 20:44:53
//1.快速排序 import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] a = new int[n]; for(int i=0;i<n;i++) { a[i] = sc.nextInt(); } qsort(a,0,n-1); for(int i=0;i<n;i++) { System.out.print(a[i]+" "); } sc.close(); } private static int getPos(int[] a,int left,int right) { int mid = a[right]; while(left<right) { while(left<right && a[left]<=mid) { left++; } a[right] = a[left]; while(left<right && a[right]>=mid) { right--; } a[left] = a[right]; } a[left] = mid; return left; } private static void qsort(int[] a,int

快速排序实现

一世执手 提交于 2019-12-05 19:53:45
1 #include<stdio.h> 2 int a[] = {23,46,0,8,11,18}; 3 void qsort(int left,int right){ 4 if(left>=right){ 5 return; 6 } 7 int i = left; 8 int j = right; 9 int key = a[i]; 10 while(i<j){ 11 while(i<j&&a[j]>key){ 12 j--; 13 } 14 a[i] = a[j]; 15 while(i<j&&a[i]<key){ 16 i++; 17 } 18 a[j] = a[i]; 19 } 20 a[i] = key; 21 qsort(left,i-1); 22 qsort(i+1,right); 23 } 24 int main(){ 25 qsort(0,5); 26 int i=0; 27 for(;i<6;i++){ 28 printf("%d\n",a[i]); 29 } 30 return 0; 31 } 来源: https://www.cnblogs.com/zgang/p/11943051.html

快速排序

对着背影说爱祢 提交于 2019-12-05 13:12:15
void QuickSort(int nLow, int nHigh) { int s = nLow; int e = nHigh; int nPivot = nLow; if (s >= e) { return; } while (1) { while (g_szArray[nLow] <= g_szArray[nPivot] && nLow <= e) { nLow++; } while (g_szArray[nHigh] > g_szArray[nPivot] && nHigh >= s) { nHigh--; } if (nLow > nHigh) { break; } else { g_szArray[nLow] = g_szArray[nLow] + g_szArray[nHigh]; g_szArray[nHigh] = g_szArray[nLow] - g_szArray[nHigh]; g_szArray[nLow] = g_szArray[nLow] - g_szArray[nHigh]; nLow++; nHigh--; } } /*g_szArray[nHigh] = g_szArray[nPivot] + g_szArray[nHigh]; g_szArray[nPivot] = g_szArray[nHigh] - g_szArray[nPivot];