堆排序

快速排序,归并排序,堆排序的数组和单链表实现

和自甴很熟 提交于 2019-12-03 07:11:42
原文链接: https://www.cnblogs.com/DarrenChan/p/8807112.html 这三个排序的时间复杂度都是O(nlogn),所以这里放到一起说。 回到顶部 1. 快速排序 # 快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 步骤为: 从数列中挑出一个元素,称为"基准"(pivot), 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。 最优时间复杂度:O(nlogn) 最坏时间复杂度:O(n2) 稳定性:不稳定 从一开始快速排序平均需要花费O(n log n)时间的描述并不明显

Mysql 排序优化

左心房为你撑大大i 提交于 2019-12-03 04:58:27
原文链接: https://www.cnblogs.com/moss_tan_jun/p/6021822.html 为了优化SQL语句的排序性能,最好的情况是避免排序,合理利用索引是一个不错的方法。因为索引本身也是有序的,如果在需要排序的字段上面建立了合适的索引,那么就可以跳过排序的过程,提高SQL的查询速度。下面我通过一些典型的SQL来说明哪些SQL可以利用索引减少排序,哪些SQL不能。假设t1表存在索引key1(key_part1,key_part2),key2(key2) a.可以利用索引避免排序的SQL 1 2 3 4 SELECT * FROM t1 ORDER BY key_part1,key_part2; SELECT * FROM t1 WHERE key_part1 = constant ORDER BY key_part2; SELECT * FROM t1 WHERE key_part1 > constant ORDER BY key_part1 ASC ; SELECT * FROM t1 WHERE key_part1 = constant1 AND key_part2 > constant2 ORDER BY key_part2; b.不能利用索引避免排序的SQL 1 2 3 4 5 6 7 8 9 10 11 //排序字段在多个索引中,无法使用索引排序

堆排序(heapsort)

99封情书 提交于 2019-12-03 02:06:33
#include<iostream> #include<stdio.h> using namespace std; /** 创建一个堆:大的数是根 */ void swap(int arr[],int i,int j) { int temp= arr[i]; arr[i]=arr[j]; arr[j]=temp; } void heapify(int tree[],int n,int i) { //检查输入的这个节点的位置对不对 //如果大的数在底层就让它上去 if(i>=n) { return; } int c1 = 2*i+1; int c2 = 2*i+2; //计算两个儿子的编号 int max = i; if(c1<n && tree[c1]>tree[max]) { max=c1; } if(c2<n && tree[c2]>tree[max]) { max=c2; } //查找儿子们和父亲中那个大 if(max!=i) { swap(tree,max,i); heapify(tree,n,max); } //如果儿子大于父亲就交换 //然后继续往下一层判断 } void build_heap(int tree[],int n) { //对每一节点都检查一遍就成功建立成了一个堆 int last_node = n-1; int parent=(last_node-1)

堆排序原理及其js实现

匿名 (未验证) 提交于 2019-12-03 00:39:02
图文来源:https://www.cnblogs.com/chengxiao/p/6129630.html 堆排序是利用 堆 这种数据结构而设计的一种排序算法,堆排序是一种 选择排序, 它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。堆排序是利用 堆 这种数据结构而设计的一种排序算法,堆排序是一种 选择排序, 它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。 堆     堆是具有以下性质的 完全二叉树 :每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图: 同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子 该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是: 接下来,我们来看看堆排序的基本思想及基本步骤: 堆排序基本思想及步骤 堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了 步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。   a

关于写堆排序的实现及感悟

匿名 (未验证) 提交于 2019-12-03 00:34:01
本人在想着了解了算法的思想后,然后用语言实现应该不难,本着这个想法着实被虐了一下,但是还是坚持了下来,用了接近三个小时多,通过在草稿纸的一步步推演,测试,调试,终于给写了下来; 我想很多人应该和我一样,算法的思想都很明白,甚至在草稿纸上能一步步划出来,但是实现为代码,确写不出来。我总结了一下,一个算法,一开始你可能是写不出来的,但是可以试着分步骤,实现局部的,然后再合并; 直接拿今天的例子来,堆排序; 1、首先理解堆的概念,可以理解为一种数据结构,将数组在逻辑上转为完全二叉树的形式; 2、了解一个节点的父节点和左子节点、右子节点的关系; father(i) = i / 2; leftChild(i) = 2 * i + 1; rightChild(i) = 2 * i + 2;(这里的下标是按数组存的下标) 了解了上面的知识,下面就是实现的细节了。 1、按大根堆思想每次将一个最大数放到大根;然后交换数组末尾和首位,得到最大值,放在数组的末尾; 2、将除去数组末尾的数再按大根堆循环进行; 3、得到排序后的数组; public static int [] heapSort ( int [] array ) { for ( int n = array . length ; n > 0 ; n --) { //需要一个外部循环,每次只能得到一个最大值,放入数组末尾; int i = n /

堆排序

匿名 (未验证) 提交于 2019-12-03 00:30:01
输入: A[1...n] 步骤 1 2 时间复杂度分析 + O(n) n-1 [log2(n-1),log2(n-2)...1] nlogn O(nlogn) 文章来源: 堆排序

研磨算法:排序之堆排序

匿名 (未验证) 提交于 2019-12-03 00:21:02
标签(空格分隔): 研磨算法 堆排序是利用堆这种数据结构而设计的一种排序算法, 堆排序是一种选择排序 ,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。 堆在Java中也称做优先级队列,使用过二叉堆的数据结构来实现的,用数组保存并按照一定条件排序,但实现对数级别的 删除最大元素 和插入元素操作。 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。 由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。 对于大顶堆和小顶堆,如果我们要取前最大的几个,我们要使用小顶堆;如果要取前最小的几个,要使用大顶堆。举一个例子:比如A与参加某个选秀节目,选秀节目要取前10名,那么A需要和前10名中最差的一个比,所以要找出最小的。 堆的操作涉及到上浮和下沉,我们把堆想象成一个严密的黑社会组织。每一个子节点表示一个下属,父节点表示直接上级。 当一个很有能力的新人加入组织的时候,就会逐渐提升,将能力不够的上级踩到脚下,直到遇到一个更强的领导。这就是上浮swim。当一个领导被外来者取代后,如果他的下属比他厉害,那么他们的角色就会互换

堆排序(heapsort)

匿名 (未验证) 提交于 2019-12-03 00:15:02
#include<iostream> #include<stdio.h> using namespace std; /** 创建一个堆:大的数是根 */ void swap(int arr[],int i,int j) { int temp= arr[i]; arr[i]=arr[j]; arr[j]=temp; } void heapify(int tree[],int n,int i) { //检查输入的这个节点的位置对不对 //如果大的数在底层就让它上去 if(i>=n) { return; } int c1 = 2*i+1; int c2 = 2*i+2; //计算两个儿子的编号 int max = i; if(c1<n && tree[c1]>tree[max]) { max=c1; } if(c2<n && tree[c2]>tree[max]) { max=c2; } //查找儿子们和父亲中那个大 if(max!=i) { swap(tree,max,i); heapify(tree,n,max); } //如果儿子大于父亲就交换 //然后继续往下一层判断 } void build_heap(int tree[],int n) { //对每一节点都检查一遍就成功建立成了一个堆 int last_node = n-1; int parent=(last_node-1)

算法第二章作业

匿名 (未验证) 提交于 2019-12-03 00:13:02
在这一年的打题过程中,从最开始的手敲冒泡排序到现在一直用STL里的sort,排序算法使用的频率可以说是非常高的了,而且各种排序算法的思想和有关的一些数据结构也会经常用到,但之前一直听说sort是基于快排的,就会有疑问――堆排序的最坏最好复杂度都是nlogn,而快排的最坏复杂度是n 2 ,为什么不用堆排呢。国庆这几天断断续续地看完了老师给的博客之后终于明白了这个问题,而且更加深入地了解了sort函数对快排的极致优化。 从平均时间上来说,堆排的时间常数要比快排大,因为堆排会让某些数据出现很多大幅度的无效的移动,而快排则是将每个元素快速地移动到最终位置上或是附近,然后进行小范围的移动,详见 https://www.zhihu.com/question/20842649 http://mindhacks.cn/2008/06/13/why-is-quicksort-so-quick/ 那么std::sort又是怎么实现来尽量避免快排的最坏情况呢,这篇博客给出了详细的解答 http://feihu.me/blog/2014/sgi-std-sort/ 为了让自己看的时候不至于被各种函数名弄晕,做了个图辅助一下 基于个人的理解 __introsort_loop这个函数的主体部分就是快速排序的部分,但它与一般的快排不一样的是,为了尽量减少枢轴为极值引起的递归恶化,它选取了开头、中间

C语言排序之堆排序

匿名 (未验证) 提交于 2019-12-02 23:57:01
#include void swap(int *array,int a,int b) { int temp = array[a]; array[a] = array[b]; array[b] = temp; } void AdjustHeap(int *array,int s,int m) { int temp; int j ; temp = array[s]; for(j = 2*s; j = array[j]) { break; } array[s] = array[j]; s = j; } array[s] = temp; } void HeapSort(int *array,int length) { int i,j; for(i = length/2; i > 0; i--) { AdjustHeap(array,i,length); } for(j = length-1; j > 0; j--) { swap(array,0,j); AdjustHeap(array,0,j-1); } } int main(void) { int k = 0; int Array[5] = {4,2,1,3,0}; HeapSort(Array,5); for(k = 0; k 来源:博客园 作者: 晓风哥哥 链接:https://www.cnblogs.com/HMM0530/p