堆排序

数据结构中涉及的排序算法

末鹿安然 提交于 2019-12-07 22:06:21
下面按照课本的分类,做了大致的内排序的归类的图片: 下面我们逐个来实现排序的算法: 一、插入排序算法: 包括:直接插入、折半插入、和希尔排序 其中,插入排序的思想都是一样的,都是以首个待排序的数字作为假设已经有序的序列,然后从已经有序的序列的最后一个位置,从后往前找满这趟比较中元素适合放置的位置。 1. 直接插入插入排序: /* 直接插入插入排序,假定首个元素有序, 待插入元素和前面的元素依次大小比较, 如果满足该元素小于前面一次由后到前的元素,就依次移动元素 循环判断 时间复杂度O(n^2) 稳定排序 基本有序时时间复杂度为O(n) */ void insertSort1(int a[], int n){ //直接插入排序 int temp,j; for(int i=1;i<n;i++){ temp = a[i]; j = i-1; while(j>=0 and temp<a[j]){ //逐个元素比较,逐个移动元素 a[j+1] = a[j]; j--; } a[j+1] = temp; } } void insertSort2(int a[], int n){ int i, j, temp; for(i=1;i<n;i++){ temp = a[i]; for(j=i-1;temp<a[j] and j>=0;j--){ a[j+1] = a[j]; } a[j+1] =

堆 堆排序 优先队列 图文详解(Golang实现)

ぐ巨炮叔叔 提交于 2019-12-06 08:25:20
引入 # 在实际应用中,我们经常需要从一组对象中查找 最大值 或 最小值 。当然我们可以每次都先排序,然后再进行查找,但是这种做法效率很低。哪么有没有一种特殊的数据结构,可以高效率的实现我们的需求呢,答案就是 堆(heap) 堆分为最小堆和最大堆,它们的性质相似,我们以最小堆为例子。 最小堆 # 举例 # 如上图所示,就为一个最小堆。 特性 # 是一棵完全二叉树 如果一颗二叉树的任何结点,或者是树叶,或者左右子树均非空,则这棵二叉树称做满二叉树(full binary tree) 如果一颗二叉树最多只有最下面的两层结点度数可以小于2,并且最下面一层的结点都集中在该层最左边的连续位置上,则此二叉树称做完全二叉树(complete binary tree) 局部有序 最小堆对应的完全二叉树中所有结点的值均不大于其左右子结点的值,且一个结点与其兄弟之间没有必然的联系 二叉搜索树中,左子 < 父 < 右子 存储结构 # 由于堆是一棵完全二叉树,所以我们可以用顺序结构来存储它,只需要计算简单的代数表达式,就能够非常方便的查找某个结点的父结点和子节点,既避免了使用指针来保持结构,又能高效的执行相应操作。 Copy 结点i的左子结点为2xi+1,右子结点为2xi+2 结点i的父节点为(i-1)/2 数据结构 # Copy // 本例为最小堆 // 最大堆只需要修改less函数即可 type

数据结构之内外排序

喜你入骨 提交于 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个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的

堆 堆排序 优先队列 图文详解(Golang实现)

扶醉桌前 提交于 2019-12-05 22:17:04
引入 在实际应用中,我们经常需要从一组对象中查找 最大值 或 最小值 。当然我们可以每次都先排序,然后再进行查找,但是这种做法效率很低。哪么有没有一种特殊的数据结构,可以高效率的实现我们的需求呢,答案就是 堆(heap) 堆分为最小堆和最大堆,它们的性质相似,我们以最小堆为例子。 最小堆 举例 如上图所示,就为一个最小堆。 特性 是一棵完全二叉树 如果一颗二叉树的任何结点,或者是树叶,或者左右子树均非空,则这棵二叉树称做满二叉树(full binary tree) 如果一颗二叉树最多只有最下面的两层结点度数可以小于2,并且最下面一层的结点都集中在该层最左边的连续位置上,则此二叉树称做完全二叉树(complete binary tree) 局部有序 最小堆对应的完全二叉树中所有结点的值均不大于其左右子结点的值,且一个结点与其兄弟之间没有必然的联系 二叉搜索树中,左子 < 父 < 右子 存储结构 由于堆是一棵完全二叉树,所以我们可以用顺序结构来存储它,只需要计算简单的代数表达式,就能够非常方便的查找某个结点的父结点和子节点,既避免了使用指针来保持结构,又能高效的执行相应操作。 结点i的左子结点为2xi+1,右子结点为2xi+2 结点i的父节点为(i-1)/2 数据结构 // 本例为最小堆 // 最大堆只需要修改less函数即可 type Heap []int func (h Heap)

选择排序

拈花ヽ惹草 提交于 2019-12-05 15:06:20
直接插入排序 目录 简述 步骤 代码 back 简述 直接插入排序是一种简单的排序,基本操作就是,从一堆数中选择一个数,然后插入到排好序的列表中(本列表)。这种方法也称归位。直接插入排序,每一次选择数字,都是一种归位。 举个例子,就好比如,你在打扑克,然后你抽到了一堆扑克牌,你要对它进行排序,你会很直接地,从一边或者中间选择一张扑克牌,然后根据数值大小,进行插入排序。选出的牌,你会很自然的插入到比它小的前面。不一会,你的手中的扑克牌就完成了排序。 算法的步骤 以下是《数据结构C语言版》的算法步骤: 设待排序的记录存放在数组r[1..n]中,r[1]是一个有序序列。 循环n-1c次,每次使用顺序查找法,查找r[i] (i=2,...n)在已排好序的序列r[1...i-1]中的插入位置,然后将r[i]插入表长为i-1的有序序列r[1...i-1],直到r[n]插入表长为n-1的有序序列r[1...n-1],最后得到一个表长为n的有序序列。 我的理解: 按要求选出一个最大或者最小的值,然后放到最前面,再从剩下的几个选出最大或者最小的,重复刚刚的操作,一直到整个数组有序 特性 直接插入法的平均时间复杂度是O(n^2^),其空间复杂度是S(1)。 主要特点是: 是稳定的 算法比较简便,而且容易书写 适用于链表的结构 对基本有序的情况的话,更为适合使用。但是,如果基数非常大,那么复杂度比较高

堆排序Heap_Sort

巧了我就是萌 提交于 2019-12-05 12:31:09
堆排序就是借助二叉堆进行排序,不了解二叉堆的可以先看 这里 。本文以升序排序为例,首先将待排序数组放置在最小堆中,此时堆顶一定是数组中最小的元素,然后删除堆顶元素,此时调整后的最小堆顶会是第二小的元素,从而实现排序。 时间复杂度:O(nlogn) 代码: public static void main(String [] args) { Heap<Integer> h = new Heap<>(); Integer[] i = {20,30,90,40,70,110,60,10,100,50,80}; for (int j = 0; j < i.length; j++) { h.insert(i[j]); } while(!h.isEmpty()) { System.out.print(h.getFirst()+" "); h.deleteFirst(); } } 输出结果: 10 20 30 40 50 60 70 80 90 100 110 来源: https://www.cnblogs.com/lbrs/p/11925163.html

经典排序算法

随声附和 提交于 2019-12-05 08:34:10
  排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。用一张图概括: 关于时间复杂度: 平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序。 线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序。 O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 希尔排序。 线性阶 (O(n)) 排序 基数排序,此外还有桶、箱排序。 关于稳定性: 稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序。 不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序。 名词解释: n:数据规模 k:“桶”的个数 In-place:占用常数内存,不占用额外内存 Out-place:占用额外内存 稳定性:排序后 2 个相等键值的顺序和排序之前它们的顺序相同 冒泡排序   冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

堆排序问题

早过忘川 提交于 2019-12-05 05:30:38
堆排序 堆排序是在二叉树的概念上建立起来的一种排序方式,利用的是二叉树中的完全二叉树;完美二叉树两种树形结构来完成堆排序 关于完全二叉树的概念可以去查阅一些,这里不作详细说明,完美二叉树依据从上至下,从左至右的方式可以转换成一种数组存储结构,每一个节点都是对应 数组索引 。 基本概念:   0.堆排序分为大顶堆,小顶堆,每一个堆都是从大到小和从小到大(堆顶 > 左右 | 堆顶 < 左右)   1.按照0索引开始从上至下,N个节点的完全二叉树,最后一个非叶子节点N / 2 - 1,非叶子节点的范围 = [0,N / 2 -1]   2.非叶子节(N)点和自己的左(L)右(R)节点的关系:L = N * 2 + 1 R = N * 2 + 2   3.堆排序方式:我们从下至上查找,每次完成一个非叶子节点的堆排序,使根节点的值最大,交换根节点和最后一个节点的值 对于从最后一个非叶子节点像上进行推导: /** * 我们从最下最左的非叶子节点开始构建堆,叶子节点本身就是堆了。 * 我们需要构建最后一个非叶子节点的堆 * */ public void heap(int[] arr){ int a = arr.length/2-1; //找到最后一个非叶子节点索引 int l = a * 2 + 1; //左子节点索引 int r = a * 2 + 2; //右子节点索引 int i = 0;

golang中sort包实现与应用

流过昼夜 提交于 2019-12-05 01:49:12
1、简介 sort包中实现了3种基本的排序算法:插入排序.快排和堆排序.和其他语言中一样,这三种方式都是不公开的,他们只在sort包内部使用.所以用户在使用sort包进行排序时无需考虑使用那种排序方式,sort.Interface定义的三个方法:获取数据集合长度的Len()方法、比较两个元素大小的Less()方法和交换两个元素位置的Swap()方法,就可以顺利对数据集合进行排序。sort包会根据实际数据自动选择高效的排序算法。 type Interface interface { // 返回要排序的数据长度 Len() int //比较下标为i和j对应的数据大小,可自己控制升序和降序 Less(i, j int ) bool // 交换下标为i,j对应的数据 Swap(i, j int ) } 任何实现了 sort.Interface 的类型(一般为集合),均可使用该包中的方法进行排序。这些方法要求集合内列出元素的索引为整数。 这里我直接用源码来讲解实现: 1、源码中的例子: type Person struct { Name string Age int } type ByAge []Person //实现了sort接口中的三个方法,则可以使用排序方法了 func (a ByAge) Len() int { return len (a) } func (a ByAge) Swap

数据结构与算法之美学习笔记:第十四讲

我只是一个虾纸丫 提交于 2019-12-05 00:30:27
一、课前问题 几乎所有的编程语言都会提供排序函数,比如C语言中qsort(),C++ STL中的sort()、stable_sort(),还有Java语言中的Collections.sort()。 在平时的开发中,我们也都是直接使用这些现成的函数来实现业务逻辑中的排序功能。那你知道这些排序函数是如何实现的吗?底层都利用了哪种排序算法呢? 基于这些问题,今天我们就来看排序这部分的最后一块内容:如何实现一个通用的、高性能的排序函数? 二、如何选择合适的排序算法 如果要实现一个通用的、高效率的排序函数,我们应该选择哪种排序算法?我们先回顾一下前面讲过的一种排序算法。 我们前面讲过,线性排序算法的时间复杂度比较低,适用场景比较特殊。所以如果要写一个通用的排序函数,不能选择线性排序算法。 如果对小规模数据进行排序,可以选择时间复杂度是O(n )的算法; 如果对大规模数据进⾏排序,时间复杂度是O(nlogn)的算法更加高效。 所以,为了兼顾任意规模数据的排序,一般都会首选时间复杂度是O(nlogn)的排序算法来实现排序函数。 时间复杂度是O(nlogn)的排序算法不止一个,我们已经讲过的有归并排序、快速排序,后面讲堆的时候我们还会讲到堆排序。堆排序和快速排序都有比较多的应用,比如Java语言采用堆排序实现排序函数,C语言使用快速排序实现排序函数。 不知道你有没有发现,