堆排序

堆排序的python实现

只谈情不闲聊 提交于 2020-12-19 08:23:08
#--coding: utf8 -- # 堆排序的思想 -- 以大根堆为例: # 1) 构建堆 # 2) 把堆根取下来放到有序区去 -- 堆跟是当前堆上最大的数字 # 3) 此时堆没有根了,重新调整堆,然后重复1) - 3)直到堆成为一个空堆 # # 堆排序是选择排序的一种: 也是每次从未排序的区域选择一个值放入已排序的区域 # 它对直接选择排序的改进是: 对于以前已经比较过的结果可以保留下来:不用再重复比较:这也是堆的特性 def heap_sort(arr): build_heap(arr) arrlen = len(arr) for i in reversed(range(1, arrlen)): # 把堆跟(最大的值)放到最后面去 swap(arr, 0, i) # 重新调整堆 heapify(arr, 0, i - 1) def swap(arr, index1, index2): tmp = arr[index1] arr[index1] = arr[index2] arr[index2] = tmp def build_heap(arr): """ 以arr[0]到arr[(arrlen / 2)]为根的这些子树是需要调整的子树 其他的都是叶子节点 """ arrlen = len(arr) for i in reversed(range(0, (arrlen - 1

Heapsort 和 priority queue

怎甘沉沦 提交于 2020-04-18 04:49:28
一、二叉堆含义及属性: 堆(heap)亦被称为:优先队列(priority queue),是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。在队列中,调度程序反复提取队列中第一个作业并运行,因而实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权。堆即为解决此类问题设计的一种数据结构。同垃圾收集存储的堆含义不同。 表示堆的数组A有两个属性: A.length : 代表A数组的元素个数; A.heapsize : 代表A数组中 属于堆元素个数。有时候(排序时),数组A的部分元素不属于堆。刚开始建堆的是偶,A.heapsize = A.length,排序时,每次从堆顶取出最大值,A.heapsize递减,直至排序完成. 下图是一个建好后的二叉堆: 从图中可知,已知某节点的索引值i,可以轻松获取其对应父节点,左,右子节点的索引值。有: Parent(i) return i/2; 或者 return i >> 1; Left(i) return i*2; 或者 return i << 1; Right(i) return i*2+1; 或者 return (i << 1) + 1; 二叉堆分两种: 最大堆,最小堆,均遵循堆属性。最大堆,每个节点i满足: A[Parent(i)] ≥ A[i]

常用算法(冒泡、插入、选择、快速)和二叉树详解

浪子不回头ぞ 提交于 2020-04-08 13:59:31
  同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。   计算机科学中,算法的 时间复杂度 是一个函数,它定量描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号(Order)表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,它考察当输入值大小趋近无穷时的情况。 定义   在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。 算法复杂度   算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是指执行算法所需要的计算工作量;而空间复杂度是指执行这个算法所需要的内存空间。(算法的复杂性体现在运行该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度)。 时间复杂度   1. 一般情况下,算法的基本操作重复执行的次数是模块n的某一个函数f(n),因此,算法的时间复杂度记做:T(n)=O(f(n)) 分析:随着模块n的增大,算法执行的时间的增长率和 f(n) 的增长率成正比,所以 f(n) 越小,算法的时间复杂度越低,算法的效率越高。   2.

堆排序原理及其js实现

送分小仙女□ 提交于 2020-04-06 07:56:12
图文来源:https://www.cnblogs.com/chengxiao/p/6129630.html 堆排序是利用 堆 这种数据结构而设计的一种排序算法,堆排序是一种 选择排序, 它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。堆排序是利用 堆 这种数据结构而设计的一种排序算法,堆排序是一种 选择排序, 它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。 堆     堆是具有以下性质的 完全二叉树 :每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图: 同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子 该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是: 大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] 接下来,我们来看看堆排序的基本思想及基本步骤: 堆排序基本思想及步骤 堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n

C/C++ 数据结构之算法(面试)

独自空忆成欢 提交于 2020-03-27 08:16:46
数据结构中的排序算法。 排序算法的相关知识: (1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来。 (2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的。相反,如果发生改变,这种排序方法不稳定。 (3)排序算法的分类(分为5类):插入排序、选择排序、交换排序、归并排序和分配排序。 (4)排序算法两个基本操作:<1>比较关键字的大小。 <2>改变指向记录的指针或移动记录本身。 具体的排序方法: 插入排序 <1>插入排序(Insertion Sort)的思想:每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子记录中的适当位置,直到全部记录插入完成为止。 <2>常用的插入排序方法有直接插入排序和希尔排序。 (1)直接插入排序 <1>算法思路:把一个记录集(如一个数组)分成两部分,前半部分是有序区,后半部分是无序区;有序区一开始有一个元素r[0],无序区一开始是从r[1]到之后的所有元素;然后每次从无序区按顺序取一个元素r[i],拿到有序区中由后往前进行比较,每次比较时,有序区中比r[i]大的元素就往后移动一位,直到找到小于r[i]的元素,这时r[i]插到小元素的后面,则完成一趟直接插入排序。如此反复,从无序区不断取元素插入到有序区,直到无序区为空

排序总结

白昼怎懂夜的黑 提交于 2020-03-27 06:28:30
排序 代码实现: Sort方法GitHub 基于比较 的排序算法时间下限是O(nlogn):归并排序、堆排序、快排。其他都是O(n^2) 插入排序 直接插入 循环n-1次,每次将无序序列的第一个数插入到有序序列中。一开始有序序列只有一个数(第一个数),之后每插入一个有序序列+1 将第一个数作为哨兵,每次移动都将插入位置后到该数前的所有数往后移动一位 时间复杂度 :O(n^2) 最好情况:已经是有序序列,只用比较n-1次(因为是从后往前比较),不用移动。 最坏情况:逆序序列,每次向前比较到哨兵 空间复杂度 :O(1) 稳定 折半插入 其实是在直接插入的基础上,将无序序列的第一个数在有序序列中查找的时候变为折半查找 移动次数和直接插入相同,依赖于初始序列 时间复杂度 :O(n^2) 空间复杂度 :O(1) 稳定 希尔排序 将一组序列分组进行排序(隔5个数一组,隔3个一组...) 做到基本有序后对全体进行直接插入,因为基本有序,所以比较和插入次数能有效减少 时间复杂度 :O(n 1.25)~O(1.6n 1.25) 空间复杂度 :O(1) 不稳定 交换排序 冒泡排序 进行n-1次,从第一个数开始,两两比较,把大的数放后面。从而每次排序能确定最大的数并放到最后 当某次冒泡过程中不存在数值交换,则已为正序,不用再进行排序 时间复杂度 :O(n^2) 最好情况:正序,进行一次排序,比较n-1次

golang堆排序

▼魔方 西西 提交于 2020-03-25 01:52:00
package main import "fmt" func main() { arr := []int{6, 1, 2, 7, 9, 3, 4, 5, 10, 8} heapSort(arr) fmt.Println("---") fmt.Println(arr) } //堆排序 func heapSort(arr []int) { //求数组长度 //根据堆的规律,假设子节点的规律,假设子节点的坐标为i //左子节点坐标为2 i+1,右子节点坐标为2 i+2 //父节点的坐标为(i-1)/2. 此处可以计算无论最后一位数字在做左子节点,还是右子节点。父节点的坐标一定是(i-1)/2。 golang中/取整 //假设切片长度是len(arr),那么最后一位的坐标序号为len(arr)-1,可计算出父节点的位置为(len(arr)-1)/2 length := len(arr) last_node := length - 1 //建立最大堆,最大堆的概念就是父节点总是比子节点数字大。arr[0]最大 buildMaxheap(arr) //此处的含义是将堆的堆首与堆尾交换的过程,即为将最大值换到最后,最小值放到最先,然后再对arr[:n-1}执行此递归的过程 //比如 312 -> 21 3-->1 2 3=123 for i := last_node; i > 0; i-- {

java语言实现堆排序

我怕爱的太早我们不能终老 提交于 2020-03-24 14:31:40
1.堆 堆,其实是一个完全二叉树,分为大顶堆和小顶堆。 大顶堆:每个节点的值都大于或者等于其左右子节点的值 小顶堆:每个节点的值都小于或者等于其左右子节点的值 注意:堆中某个节点的左右子节点的值的大小关系没有要求,即左子节点的值可以大于、可以等于、也可以小于右子节点的值。 升序采用大顶堆、降序采用小顶堆。 2.堆排序 首先将 n 个元素的待排序序列构建成一个大顶堆,这样待排序序列的第一个元素(即大顶堆的根节点)就是最大的元素。 然后,将这个最大的元素与最后一个元素交换(即,根节点与最后一个叶子结点交换) 对剩下的前 n-1 个元素(即,除去最大元素的剩下的元素)重新执行上述步骤。 3.代码如下 构建大顶堆 外汇MT4教程 从最后一个非叶子节点开始,叶子结点自然不用调整,最后一个非叶子节点为array.length/2-1. 交换 交换完成之后,剩下的元素还需要调整成堆结构 public class HeapSort { public static void main(String[] args) { int[] array = {4,6,8,5,9,7,3,1,2}; heapSort(array); System.out.println(Arrays.toString(array)); } public static void heapSort(int[] array){ int

JS--排序算法之堆排序

血红的双手。 提交于 2020-03-21 22:24:29
目录 排序算法之堆排序 什么是堆? 堆排序 排序算法之堆排序 什么是堆? 堆是一颗完全二叉树 堆分为 最大堆和最小堆 最大堆父节点都大于子节点, 最小堆父节点都小于子节点 左子节点: 2*i +1 (i: 父节点index) 右子节点: 2*i+2 堆排序 利用最大堆实现升序, 最小堆实现降序. 因为最大堆的根父节点一定是最大的, 让它和队尾元素互换, 然后在从堆中排除最后一个元素, 并复原最大堆. 循环 n-1次. 关键在于构建最大堆 最大堆的构建过程 时间复杂度: O(n*log(n)) 不稳定的排序 特征: 找出最大的元素放在末尾(升序) function heapSort(ary) { // 实现最大堆 // start: 父节点, end: 循环深度 function maxHeap(ary, start, end) { let parent = start, // 父节点 son = parent*2 + 1, // 左子节点 temp = null; // 规定循序最大深度 while(son<=end) { // 如果存在右子节点, 并且判断右节点是否大于左节点 if(son+1<=end && ary[son] < ary[son+1]) son++; if(ary[son] > ary[parent]) { temp = ary[son]; ary[son] =

优先(级)队列

会有一股神秘感。 提交于 2020-03-21 02:47:14
优先队列    优先级队列 是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序。每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储。 优先队列是由堆来实现的。   重点:优先级队列,是要看优先级的,谁的优先级更高,谁就先得到权限。不分排队的顺序!如果优先队列中每个元素的优先级相同,则可任选其中一个。   优先队列的效率:时间复杂度为O(logn),其中n为队列中元素的个数。    堆实质上是满足如下性质的完全二叉树:   树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。 堆排序:   堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。 python中的优先队列   Python的 heapq模块 实现了一个适用于Python列表的最小堆排序算法。是一个最小堆,堆顶元素 a永远是最小的,Java中的优先队列类似. heapq模块提供了如下几个函数: heapq.heappush(heap, item) :把item添加到heap中(heap是一个列表) heapq.heappop(heap) : 把堆顶元素弹出,返回的就是堆顶(优先级最高的元素) heapq.heappushpop(heap, item)