快速排序

分治法-合并排序和快速排序

房东的猫 提交于 2020-03-19 12:41:37
分治法是按照以下方案工作的: 将问题的实例划分为同一个问题的几个较小的实例,最好拥有同样的规模 对这些较小的实例求解(一般使用递归方法,但在问题规模足够小的时候,有时会利用另一种算法以提高效率) 如果必要的话,合并较小问题的解,以得到原始问题的解 分治法的流程: 4.1 合并排序 合并排序是成功应用分治技术的一个完美例子(书上说的)。 对于一个需要排序的数组,合并排序把它一分为二,并对每个子数组递归排序,然后把这两个排好序的子数组合并为一个有序数组。 代码实现: /** * 合并排序 * @author xiaofeig * @since 2015.9.16 * @param array 要排序的数组 * @return 返回排好序的数组 * */ public static int[] mergeSort(int[] array){ if(array.length>1){ int[] subArray1=subArray(array,0,array.length/2); int[] subArray2=subArray(array,array.length/2,array.length); subArray1=mergeSort(subArray1); subArray2=mergeSort(subArray2); return merge(subArray1,subArray2

快速排序(基本的挖坑填补法)

回眸只為那壹抹淺笑 提交于 2020-03-17 08:54:50
快速排序算法是基于 分治 策略的另一个排序算法。 该方法的基本思想是: 1.先从数列中取出一个数作为基准数,记为x。 2.分区过程,将不小于x的数全放到它的右边,不大于x的数全放到它的左边。(这样key的位置左边的没有大于key的,右边的没有小于key的,只需对左右区间排序即可) 3.再对左右区间重复第二步, 直到各区间只有一个数 #include<stdio.h> void sort(int *arr,int l,int h)//完成该函数一次即完成一躺排序 { int key; int low=l; int high=h; if(l>=h) { return ; } key=arr[l]; while(low<high) { while(low<high&&arr[high]>key)//只要比标准值大,就向前走 high--; if(low<high) { arr[low]=arr[high]; low++;//别忘了low要向后走!!! } while(low<high&&arr[low]<key) low++; if(low<high) { arr[high]=arr[low]; high--; } } //下面三句话写low写high都一样,此时low与high相等 arr[low]=key; sort(arr,l,low-1);//找当前分配好的值的左边 sort

Python的希尔排序、快速排序和归并排序

本秂侑毒 提交于 2020-03-17 07:08:53
目录 一、希尔排序(Shell Sort) 二、快速排序(Quicksort) 三、归并排序 四、排序算法效率比较 五、搜索 六、二分法查找 一、希尔排序 (Shell Sort) 1、定义:是插入排序的一种,只不过间隔设为gap。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。 2、原理:将数组列在一个表中并对列分别进行插入排序,重复这过程,不过每次用更长的列(步长更长了,列数更少了)来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身还是使用数组进行排序。 3、希尔排序的实现: shell_sort(alist): """希尔排序法""" n = len(alist) # 初始步长 gap = n // 2 #折半设定,若n=9,则gap=4 while gap > 0: #gap=1进行最后一次循环 # 按步长进行插入排序 for j in range(gap, n):#从gap开始,控制子序列中的所有元素 i = j # 插入排序 while i > 0: if alist[i] < alist[i-gap]: alist[i-gap], alist[i] =

java语言实现快速排序

此生再无相见时 提交于 2020-03-17 04:53:02
快速排序 快速排序是对冒泡排序的一种改进。 首先,找出一个基准值,然后将元素中比这个基准值小的放在基准值左边,比基准值大的元素放在基准值右边。这样一趟排序下来,基准值左边的元素都比基准值小,基准值右边的元素都比基准值大。 然后在用同样的方法,分别对左边元素和右边元素递归地进行排序,最终使整个序列有序。 这里,我选中间元素为基准值,我将从序列两端进行遍历,从左边遇到一个比基准值大的元素便停下,从右边遇到一个比基准值小的元素也停下,然后将两个元素交换位置。但是在遍历过程中,如果遍历到同一个元素时,就可以退出遍历了,因为此时左右两边都已经满足小于或者大于基准值了。交换之后还要判断当前元素是否是基准值,如果左边当前元素为基准值,接下来判断右边元素即可;右边同理。 代码如下 public class QuickSort { public static void main ( String [ ] args ) { int [ ] array = { - 9 , 78 , 0 , 23 , - 567 , 70 , - 1900 , 4561 } ; quickSort ( array , 0 , array . length - 1 ) ; System . out . println ( Arrays . toString ( array ) ) ; } public static

【从0到1学算法】快速排序

谁说胖子不能爱 提交于 2020-03-12 21:34:19
系列文章导航: 【从0到1学算法】二分查找法 【从0到1学算法】大O表示法 【从0到1学算法】 数组和链表 【从0到1学算法】选择排序 【从0到1学算法】递归 今天我们将学习快速排序,是最快的排序算法之一,速度比选择排序快得多! 一、分而治之 在学习快速排序前,先上开胃菜,快速排序中用到的算法--分而治之(divide and conquer, D&C,分治法)。只能解决一种问题的算法毕竟用处有限,而D&C提供了解决问题的思路。当面对新问题束手无策时,不妨自问:使用分而治之能解决吗?来个示例:假设你是农场主,有一块土地。 你要将这块土地均匀分成方块(正方形),且分出的方块要尽可能大。显然,下面的分法都不符合要求。 使用D&C解决问题分为两个步骤: 找出基线条件,这个条件必须尽可能简单。 不断将问题分解(或者说缩小规模),直到符合基线条件。 下面就来使用D&C找出解决方案。首先,找出基线条件。最容易处理的情况是,一条边的长度是另一条的整数倍。比如下图,一边是50m,另一边是25m,那么最大方块为25mx25m。 接下来是缩小问题规模,首先找出这块地可容纳的最大方块。 划出了两块640mx640m的方块,同时余下一小块地。接下来我们将继续对余下的小块地使用相同的算法。 适用于这小块地的最大方块,也适用于整块地的最大方块(可参阅欧几里算法)。问题规模缩小了

蓝桥杯第七届D题:快速排序

淺唱寂寞╮ 提交于 2020-03-12 06:43:50
题目描述 排序在各种场合经常被用到。 快速排序是十分常用的高效率的算法。 其思想是:先选一个“标尺”, 用它把整个队列过一遍筛子, 以保证:其左边的元素都不大于它,其右边的元素都不小于它。 这样,排序问题就被分割为两个子区间。 再分别对子区间排序就可以了。 下面的代码是一种实现,请分析并填写划线部分缺少的代码。 思路 就是快排的另一种写法,思路和 快速排序 一样 代码 # include <stdio.h> void swap ( int a [ ] , int i , int j ) { int t = a [ i ] ; a [ i ] = a [ j ] ; a [ j ] = t ; } int partition ( int a [ ] , int p , int r ) { int i = p ; int j = r + 1 ; int x = a [ p ] ; while ( 1 ) { while ( i < r && a [ ++ i ] < x ) ; while ( a [ -- j ] > x ) ; if ( i >= j ) break ; swap ( a , i , j ) ; } swap ( a , p , i ) ; //填空处 return j ; } void quicksort ( int a [ ] , int p , int r )

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

南笙酒味 提交于 2020-03-12 04:05:44
题目: 著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的 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 我的代码: # include <iostream> # include <cstdio> # include <vector> # include <string> # include <set> # include <map> # include

快速排序算法的递归与非递归

◇◆丶佛笑我妖孽 提交于 2020-03-11 12:59:18
//quick sort void quicksort (int array[], int low, int high){ if(low<high){ int index = getindex(array,low,high); quicksort(array,index+1,high); quicksort(array,0,high); } } int getindex(int array[],int low, int high){ int temp = array[low]; while (low<high){ if(array[high] >temp ){ high --; } array[low] = array[high]; if(array[low]<temp){ low++; } array[high] = array[low]; } array[low] =temp; return low; } //非递归的形式来实现快排 void quichsortnorecusive(int array[],int low,int high[]){ stack<int> s; s.push(low); s.push(high); while(!s.empty()){ int h = s.top(); s.pop(); int l = s.top(); s.pop(); int

快速排序

佐手、 提交于 2020-03-11 12:01:19
假设对以下10个数进行快速排序: 我们先模拟快速排序的过程:首先,在这个序列中随便找一个数作为基准数,通常为了方便,以第一个数作为基准数。 在初始状态下,数字6在序列的第1位。我们的目标是将6挪到序列中间的某个位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于6,右边的数都大于等于6。那么如何找到这个位置k呢? 我们要知道,快速排序其实是冒泡排序的一种改进,冒泡排序每次对相邻的两个数进行比较,这显然是一种比较浪费时间的。 而快速排序是分别从两端开始”探测”的,先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换他们。这里可以用两个变量iii和jjj,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵iii”和“哨兵jjj”。刚开始的时候让哨兵iii指向序列的最左边,指向数字6。让哨兵jjj指向序列的最右边,指向数字8。 首先哨兵jjj开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵jjj先出动,这一点非常重要。哨兵jjj一步一步地向左挪动(即j=j−1),直到找到一个小于6的数停下来。接下来哨兵iii再一步一步向右挪动(即i=i+1),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵iii停在了数字7面前。 现在交换哨兵$i$和哨兵$j$所指向的元素的值。交换之后的序列如下。 到此

快速排序及STL中的sort算法

浪尽此生 提交于 2020-03-11 10:39:42
   快速排序基本思想是,对待排序序列进行划分(Partition),一次划分,选择一个元素作为枢轴,然后将所有比枢轴小的元素放到枢轴的左边,将比枢轴大的元素放到枢轴的右边。然后对该枢轴划分的左右子序列分别再进行划分,如此递归。Partition是一个非常重要的概念,因为它只需要O(n)的时间复杂度就可以将待排序序列划分为两块具有大小关系的区间,可以根据这一特性求解待排序序列中最大的k个数、第k大的数等类似问题。   快速排序算法复杂度O(nlogn).   就平均时间而言,快速排序是目前被认为是最好的一种内部排序方法,其平均时间是O(nlogn),最坏情况是O(n^2),最坏的情况就是如下倒序完后再正序排的情况。   C++代码如下: #include "stdafx.h" #define MAXSIZE 20 typedef struct{ int r[MAXSIZE+1]; int len; }SqList; int Partition(SqList &L, int low, int high) { L.r[0] = L.r[low]; // 以第一个元素作为枢轴 int pivotkey = L.r[low];// 记录枢轴关键字 while (low < high) { while(low<high && L.r[high]>=pivotkey)       --high