快速排序

快速排序算法原理及实现(单轴快速排序、三向切分快速排序、双轴快速排序)

丶灬走出姿态 提交于 2019-12-17 16:48:04
欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. 单轴快速排序的基本原理 快速排序的基本思想就是从一个数组中任意挑选一个元素(通常来说会选择最左边的元素)作为中轴元素,将剩下的元素以中轴元素作为比较的标准,将小于等于中轴元素的放到中轴元素的左边,将大于中轴元素的放到中轴元素的右边,然后以当前中轴元素的位置为界,将左半部分子数组和右半部分子数组看成两个新的数组,重复上述操作,直到子数组的元素个数小于等于1(因为一个元素的数组必定是有序的)。 以下的代码中会常常使用交换数组中两个元素值的Swap方法,其代码如下 public static void Swap(int[] A, int i, int j){ int tmp; tmp = A[i]; A[i] = A[j]; A[j] = tmp; } 2. 快速排序中元素切分的方式 快速排序中最重要的就是步骤就是将小于等于中轴元素的放到中轴元素的左边,将大于中轴元素的放到中轴元素的右边,我们暂时把这个步骤定义为切分。而剩下的步骤就是进行递归而已,递归的边界条件为数组的元素个数小于等于1。以首元素作为中轴,看看常见的切分方式。 2.1 从两端扫描交换的方式 基本思想,使用两个变量i和j,i指向首元素的元素下一个元素(最左边的首元素为中轴元素),j指向最后一个元素

【数据结构】快速排序

◇◆丶佛笑我妖孽 提交于 2019-12-17 09:19:16
#include<iostream> using namespace std; int a[100000]; int i,j; int par(int r[],int first,int end) { i=first,j=end; r[0]=r[i]; while(i<j) { while(i<j&&r[0]<=r[j]) j--; if(i<j){ r[i]=r[j];i++; } while(i<j&&r[i]<=r[0]) i++; if(i<j) {r[j]=r[i];j--;} } r[i]=r[0]; return i; } int pos; void quickSort(int r[],int first,int end) { if(first<end){ pos=par(r,first,end); quickSort(r,first,pos-1); quickSort(r,pos+1,end);} } int main() { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; quickSort(a,1,n); for(int i=1;i<=n;i++) cout<<a[i]<<" "; } 来源: CSDN 作者: 狠人王 链接: https://blog.csdn.net/weixin_43238423

【计算机笔记】Java 排序

喜欢而已 提交于 2019-12-17 02:09:30
约定 待排序的元素需要实现 Java 的 Comparable 接口,该接口有 compareTo() 方法,可以用它来判断两个元素的大小关系。 使用辅助函数 less() 和 swap() 来进行比较和交换的操作,使得代码的可读性和可移植性更好。 排序算法的成本模型是比较和交换的次数。 public abstract class Sort < T extends Comparable < T > > { public abstract void sort ( T [ ] nums ) ; protected boolean less ( T v , T w ) { return v . compareTo ( w ) < 0 ; } protected void swap ( T [ ] a , int i , int j ) { T t = a [ i ] ; a [ i ] = a [ j ] ; a [ j ] = t ; } } 选择排序 从数组中选择最小元素,将它与数组的第一个元素交换位置。再从数组剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置。不断进行这样的操作,直到将整个数组排序。 选择排序需要 ~N 2 /2 次比较和 ~N 次交换,它的运行时间与输入无关,这个特点使得它对一个已经排序的数组也需要这么多的比较和交换操作。 public class

堆和堆排序:为什么说堆排序没有快速排序快

帅比萌擦擦* 提交于 2019-12-17 00:06:18
“堆(Heap)” 是一种特殊的数。堆这种数据结构的应用场景非常多,最经典的莫过于堆排序了。堆排序是一种原地的、时间复杂度为 O(nlogn) 的排序算法。 快速排序,平均情况下,它的时间复杂度为 O(nlogn)。尽管这两种排序算法的时间复杂度都是 O(nlogn),甚至堆排序比快速排序的时间复杂度还要稳定, 但是,在实际的软件开发中,快速排序的性能要比堆排序好,这是为什么呢? 如何理解“堆”? 前面我们提到,堆是一种特殊的树。我们现在就来看看,什么样的树才是堆。我罗列了两点要求,只要满足这两点,它就是一个堆。 堆是一个完全二叉树; 堆中的每一个节点都大于等于(或者小于等于)其子树中每个节点的值 我分别解释一下这两点。 第一点,堆必须是一个完全二叉树。还记得我们之前讲的完全二叉树的定义吗?完全二叉树要求,除了最后一层,其他层的节点个数都是满的,最后一层的节点都靠左排列。 第二点,堆中的每个节点的值必须大于等于(或者小于等于)其子树中每个节点的值。实际上,我们还可以换一种说法,堆中每个节点的值都大于等于(或者小于等于)其左右子节点的值。这两种表述是等价的。 对于每个节点的值都大于等于子树中每个节点值的堆,我们叫作“大顶堆”。对于每个节点的值都小于等于子树中每个节点值的堆,我们叫作“小顶堆”。 定义解释清楚了,你来看看,下面这几个二叉树是不是堆? 其中第 1 个和第 2 个是大顶堆

快速排序

杀马特。学长 韩版系。学妹 提交于 2019-12-16 22:38:30
输入 第一行为数列的总个数,第二行为待排序的数列 输出 排序后的数列 样例输入 8 10 4 6 3 8 2 5 7 样例输出 2 3 4 5 6 7 8 10 代码: #include<iostream> #include<cstring> int r[110]; int Partition(int r[ ],int first,int end) { int i=first; int j=end; r[0]=r[i]; while(i<j) { while(i<j&&r[0]<=r[j]) j--; if(i<j) { r[i]=r[j]; i++; } while(i<j && r[i]<= r[0]) i++; if(i<j) { r[j]=r[i]; j--; } } r[i]=r[0]; return i; } void QuickSort(int r[ ],int first,int end ) { if(first<end) { int pivotpos=Partition(r,first,end); QuickSort(r,first,pivotpos-1); QuickSort(r,pivotpos+1,end ); } } using namespace std; int main() { int n; cin>>n; for(int i=1;i<=n;i++)

pta6-1 快速排序

孤者浪人 提交于 2019-12-16 22:25:08
给一个无序表,使用快速排序算法对它进行排序。 函数接口定义: int Partition(SqList &L,int low,int high); void QuickSort(SqList &L, int low, int high); 其中L是待排序表,low和high是排序的区间。 裁判测试程序样例: # include <iostream> using namespace std ; # define MAXSIZE 50 typedef int KeyType ; typedef struct { KeyType key ; } ElemType ; typedef struct { ElemType r [ MAXSIZE + 1 ] ; int length ; } SqList ; void Create ( SqList & L ) { int i ; cin >> L . length ; for ( i = 1 ; i <= L . length ; i ++ ) cin >> L . r [ i ] . key ; } void Output ( SqList L ) { int i ; for ( i = 1 ; i <= L . length ; i ++ ) cout << L . r [ i ] . key << " " ; cout << endl

PAT乙级1045 快速排序

旧巷老猫 提交于 2019-12-16 13:16:08
1045 快速排序 (25分) 著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的 N 个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元? 例如给定 $N = 5$, 排列是1、3、2、4、5。则: 1 的左边没有元素,右边的元素都比它大,所以它可能是主元; 尽管 3 的左边元素都比它小,但其右边的 2 比它小,所以它不能是主元; 尽管 2 的右边元素都比它大,但其左边的 3 比它大,所以它不能是主元; 类似原因,4 和 5 都可能是主元。 因此,有 3 个元素可能是主元。 输入格式: 输入在第 1 行中给出一个正整数 N( ≤); 第 2 行是空格分隔的 N 个不同的正整数,每个数不超过 1。 输出格式: 在第 1 行中输出有可能是主元的元素个数;在第 2 行中按递增顺序输出这些元素,其间以 1 个空格分隔,行首尾不得有多余空格。 输入样例: 5 1 3 2 4 5 输出样例: 3 1 4 5递推预处理数组左边的最大值,预处理右边的最小值 1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 6 using namespace

交换排序(冒泡,快速排序)

柔情痞子 提交于 2019-12-16 03:23:26
交换排序 1.交换排序的思想 交换排序的思想为两两比较关键字的大小,若关键字次序相反,则这两个元素就进行交换,直到数组中没有出现反序的元素为止。 在这里主要介绍两种算法: 冒泡排序 快速排序 2.冒泡排序 冒泡排序的思想为在无序区中相邻两个元素比较,不断调整元素的位置,使关键字最小的元素像气泡一样冒出水面。 例:每经历一轮有效排序,都有一个元素加入有序区(冒泡到数组的一端) 数组下标 原始 第一轮 第二轮 第三轮 第四轮 0 4 0 0 0 0 1 2 4 1 1 1 2 3 2 4 2 2 3 1 3 2 4 3 4 0 1 3 3 4 冒泡排序是相邻元素的比较,是一个稳定的排序算法。 代码: /*冒泡排序 o(n^2) 稳定*/ void BubbleSort(Elem elem[], int len) { bool flag; for (int i = 0; i < len - 1; i++) { flag = false; for (int j = len - 1 ; j > i; j--) { if (elem[j].key < elem[j-1].key) { swap(elem[j - 1], elem[j]); flag = true; } } if (!flag) break; } } 3.快速排序法 快速排序法是冒泡算法的改进,也属于交换排序。 区别:

数据结构常见面试题

让人想犯罪 __ 提交于 2019-12-15 20:44:56
数据结构常见面试题 1、数组和链表的区别。 从逻辑结构上来看 ,数组必须实现定于固定的长度,不能适应数据动态增减的情况,即数组的大小一旦定义就不能改变。当数据增加是,可能超过原先定义的元素的个数;当数据减少时,造成内存浪费;链表动态进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。 从内存存储的角度看 ;数组从栈中分配空间(用new则在堆上创建),对程序员方便快速,但是自由度小;链表从堆中分配空间,自由度大但是申请管理比较麻烦。 从访问方式类看 ,数组在内存中是连续的存储,因此可以利用下标索引进行访问;链表是链式存储结构,在访问元素时候只能够通过线性方式由前到后顺序的访问,所以访问效率比数组要低。 2、简述快速排序过程 1)选择一个基准元素,通常选择第一个元素或者最后一个元素, 2)通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的元素值比基准值大。 3)此时基准元素在其排好序后的正确位置 4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。 3、快速排序的改进 只对长度大于k的子序列递归调用快速排序,让原序列基本有序,然后再对整个基本有序序列用插入排序算法排序。实践证明,改进后的算法时间复杂度有所降低,且当k取值为 8 左右时,改进算法的性能最佳。 选择基准元的方式 对于分治算法

快速排序

落爺英雄遲暮 提交于 2019-12-15 19:59:15
# include <stdio.h> void input ( int [ ] , int n ) ; //输入函数 void output ( int [ ] , int n ) ; //输出函数 void quicksort ( int [ ] , int low , int high ) ; //快排调用函数 int split ( int a [ ] , int low , int high ) ; //分割排序函数 int main ( ) //10 5 8 9 2 1 10 6 4 3 7 测试数据 { int a [ 10 ] ; int n ; scanf ( "%d" , & n ) ; input ( a , n ) ; quicksort ( a , 0 , n - 1 ) ; //传a的起始下标和最终下标 output ( a , n ) ; return 0 ; } void input ( int a [ ] , int n ) { for ( int i = 0 ; i < n ; i ++ ) scanf ( "%d" , & a [ i ] ) ; } void output ( int a [ ] , int n ) { for ( int i = 0 ; i < n ; i ++ ) printf ( "%d " , a [ i ] ) ;