堆排序

快速排序和堆排序

心不动则不痛 提交于 2020-03-20 07:47:12
快速排序思想:在partition中,首先以最右边的值作为划分值x,分别维护小于x的区间,等于x的区间,以及大于x的三个区间,最后返回划分值的左边界和右边界.时间复杂度为O(nlogn). public class QuickSort { public static void quickSort(int[] arr) { if(arr == null || arr.length < 2) return ; sortProgress(arr, 0 , arr.length - 1); } public static void sortProgress(int[] arr, int L, int R) { if(L < R) { //随机取L到R之间的一个数与R交换. swap(arr, L + (int)(Math.random() * (R - L + 1)), R); //p数组的大小为2,p[0]表示划分值的左边界,p[1]表示划分值的右边界. int[] p = partition(arr, L, R); sortProgress(arr, L, p[0] - 1); sortProgress(arr, p[1] + 1, R); } } public static int[] partition(int[] arr, int L, int R) { int less = L

【算法学习】堆排序建立最大堆

∥☆過路亽.° 提交于 2020-03-17 15:58:44
本文代码均转自: 作者:早就戒了 来源:CSDN 原文:https://blog.csdn.net/qq_37169817/article/details/79777264 版权声明:本文为博主原创文章,转载请附上博文链接! 1 public class HeapSort { 2 public static int[] maxHeap(int[] array) { 3 // 1.构建大顶堆 4 for (int i = array.length / 2 - 1; i >= 0; i--) { 5 // 从第一个非叶子结点从下至上,对于数组从右至左调整结构 6 adjustHeap(array, i, array.length); 7 } 8 return array; 9 } 10 11 private static void adjustHeap(int[] array, int i, int length) { 12 int parent = array[i]; 13 for (int k = 2 * i + 1; k < length; k = k * 2 + 1) { 14 // 2*i+1表示左节点,k = k * 2 + 1表示继续调整子节点 15 if (k + 1 < length && array[k] < array[k + 1]) 16 k = k + 1;/

面试笔记 | 排序算法

非 Y 不嫁゛ 提交于 2020-03-10 12:37:20
引用于 菜鸟教程 排序算法 01 堆排序 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列; 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列; 02 快速排序 03 归并排序 来源: CSDN 作者: 大虎牙 链接: https://blog.csdn.net/qq_34170700/article/details/104769866

选择排序-堆排序

依然范特西╮ 提交于 2020-03-08 16:42:12
文章目录 算法简介 Java 实现 时间复杂度 空间复杂度 算法稳定性 算法简介 二叉堆 一棵完全二叉树,对于大顶堆来说,任何一个结点都要大于等于它左右孩子结点,对于小顶堆,任何一个结点都要小于等于它的左右孩子。 二叉堆与数组的联系 二叉堆一般存储在数组中,有这样的性质,如果我们把二叉堆按照从上到下,从左到右的顺序依次存进数组,如果 index 是某个结点的下标值,那么它左右孩子结点的下标值分别是 2*index+1 和 2*index+2 ,不信的筒子们可以尝试写到数组中看看规律。我在数组中怎么知道这个下标的值是右结点还是左结点呢?我们减去 2 除以 2 除得尽就是右结点,否则是左结点,并且其父节点的下标也可以确定了。这个数组保存着这个二叉堆的所有信息 二叉堆的增删 二叉堆的新增和删除,我们会把一个结点新增到最下一层的最后面,然后与父节点比较,进而上浮或者不动;对于删除来讲,假如我们删除某一个中间结点,我们就需要用最尾部结点对删掉的节点位置进行补位,补上之后,再对这个补位的结点和最小(大)的直接子结点比较,进而选择下沉或不动 堆排序 我们利用二叉堆,上浮下沉的性质每次找到最大的结点上浮到顶端,然后我们再保存到最后面,这样就可以从小到大排序了!详细的说堆排序就是先创建大顶堆或小顶堆,然后把这个堆根和最尾部交换位置,将除了尾部的继续构成堆,这样不断循环就可以实现堆排序了 上浮还是下沉

堆排序

邮差的信 提交于 2020-03-08 10:54:19
基本思想: 堆排序是利用堆这种数据结构设计的一种排序算法,它是选择排序的一种。通过堆来进行数据选择。 堆是一个近似完全二叉树的结构,同时满足的性质:子结点的键值或索引总是小于(或者大于)它的父节点。 排升序要建大堆,排降序建小堆。 代码实现: void Swap ( int * a , int * b ) { int t = * a ; * a = * b ; * b = t ; } void AdjustDown ( int array [ ] , int size , int r ) { int left = 2 * r + 1 ; int right = 2 * r + 2 ; if ( left >= size ) { return ; } int m = left ; if ( right < size && array [ right ] > array [ left ] ) { m = right ; } if ( array [ r ] >= array [ m ] ) { return ; } Swap ( array + r , array + m ) ; AdjustDown ( array , size , m ) ; } // 建堆 void CreateHeap ( int array [ ] , int size ) { for ( int i = (

剑指offer:最小的k个数

…衆ロ難τιáo~ 提交于 2020-03-08 00:30:18
题目描述 输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。 堆排序,牛客网调烦了跑到力扣调,还是力扣界面比较舒服… 其实还可以优化一下,初始化之后调整k次可以输出后k位。也可以用冒泡、快排,但是冒泡数据大了就不好跑了,快排写的循环太多会超时 堆排序参考: 数组排序——堆排序 # -*- coding:utf-8 -*- class Solution: def GetLeastNumbers_Solution(self, tinput, k): # write code here if not tinput or k>len(tinput): return [] tinput=self.HeapSort(tinput,len(tinput)-1) return tinput[:k] def HeapSort(self,tinput,end): i=end/2 while i>=0:#初始化最大堆 self.sift(tinput,i,end) i-=1 for i in range(end):#每一次取出堆顶,与堆底交换,再调整堆 temp=tinput[0] tinput[0]=tinput[end-i] tinput[end-i]=temp self.sift(tinput,0,end-i-1)

【排序】--C语言实现堆排序

独自空忆成欢 提交于 2020-03-07 13:50:54
堆排序 堆排序使用【大顶堆】或者【小顶堆】实现。分为两步:构建堆和调整堆,主要时间都花在了构建堆上。堆排序效率比较高,适用于数据量比较大的场景。 代码 # include <stdio.h> /* 函数描述:构建大顶堆 函数参数:数组 根节点的下标 最后一个结点的下标 */ void AdjustMaxHeap ( int * a , int root , int last ) { int i , child ; int tmp = a [ root ] ; for ( ; 2 * root + 1 <= last ; root = child ) //循环到结点没有孩子结点为止 { child = 2 * root + 1 ; if ( child + 1 <= last && a [ child ] < a [ child + 1 ] ) //先找出两个孩子结点中较大的一个 { child ++ ; } if ( a [ child ] > a [ root ] ) //如果孩子结点比较大,则和根节点交换 { a [ root ] = a [ child ] ; a [ child ] = tmp ; } else { break ; } } } void swap ( int * x , int * y ) { int t = * x ; * x = * y ; * y =

【数据结构与算法之美】排序优化:如何实现一个通用的、高性能的排序函数?

我与影子孤独终老i 提交于 2020-03-05 22:04:21
目录 一、如何选择合适的排序算法? 1.排序算法一览表 2.为什选择快速排序? 二、如何优化快速排序? 三、通用排序函数实现技巧 四、课后思考 一、如何选择合适的排序算法? 1.排序算法一览表 时间复杂度 是稳定排序? 是原地排序? 冒泡排序 O(n^2) 是 是 插入排序 O(n^2) 是 是 选择排序 O(n^2) 否 是 快速排序 O(nlogn) 否 是 归并排序 O(nlogn) 是 否 桶排序 O(n) 是 否 计数排序 O(n+k),k是数据范围 是 否 基数排序 O(dn),d是纬度 是 否 2.为什选择快速排序? 1)线性排序时间复杂度很低但使用场景特殊,如果要写一个通用排序函数,不能选择线性排序。 2)为了兼顾任意规模数据的排序,一般会首选时间复杂度为O(nlogn)的排序算法来实现排序函数。 3)同为O(nlogn)的快排和归并排序相比,归并排序不是原地排序算法,所以最优的选择是快排。 二、如何优化快速排序? 导致快排时间复杂度降为O(n)的原因是分区点选择不合理,最理想的分区点是:被分区点分开的两个分区中,数据的数量差不多。如何优化分区点的选择?有2种常用方法,如下: 1.三数取中法 ①从区间的首、中、尾分别取一个数,然后比较大小,取中间值作为分区点。 ②如果要排序的数组比较大,那“三数取中”可能就不够用了,可能要“5数取中”或者“10数取中”。 2.随机法

算法与数据结构——排序(六)堆排序

馋奶兔 提交于 2020-03-05 02:46:33
在前面的排序算法里面,我们发现每次找到一个最小的数都要进行很多次的比较,比如在n个数里面,我们如果想要找到最小的数,那么就需要比较 n-1次,那么我们想,能不能减少每次比较的次数呢。 其实发现是可以的,在前面的简单选择排序算法里面,我们每次找到最小的数后,剩余的一些数,其实有的是已经经过比较了的,所以在我们寻找第二小的数的时候,完全可以利用第一次的比较结果,但是由于我们没有把第一次比较的结果记录下来,所以我们在后面的比较过程中用不到,那么我们会想,能不能想办法把第一次比较的结果保存下来呢。办法肯定是有的,这就是今天我们要学习的堆排序。 那么什么是堆排序呢,我们首先要弄清楚什么是堆。看下面的两个图,它们都是堆: 通过图我们可以看出,它们的根结点,要么比他们的左右孩子都大,要么比他们的左右孩子都小。这就是堆。具体的定义就是: 堆是具有以下性质的完全二叉树,每个结点的值都大于或者等于其左右孩子结点的值,叫做大顶堆,每个结点的值都小于或者等于其左右孩子结点的值,叫做小顶堆。由二叉树的一个性质,我们可以知道,一个完全二叉树,如果它的根结点位置是i,那么它左孩子位置就是2i,右孩子位置就是2i+1,所以大顶堆可以定义为ki>=k2i并且ki>=k2i+1,小顶堆的符号刚刚相反。 把堆进行层序遍历装入数据组,是如下结果: 堆排序算法,就是把一个序列构造成一个大顶堆(此处以大顶堆为例)

数据结构——堆排序

北战南征 提交于 2020-03-05 02:43:18
堆排序总结 堆排序思想:最大堆的堆顶元素是全部数据中的最大值,输出这个值 。再将剩余元素整理成新的最大堆,此时堆顶元素有时又是剩余元素 的最大值,再输出这个值。继续这个过程,每次输出堆顶元素,并将 剩余元素整理成新的最大堆再输出... 堆排序要解决的几个问题 1:如何将数据排列成堆的形式——初始堆的建立 2:输出堆顶元素后,剩余元素如何再整理成新的堆——堆的整理 3:输出元素放在什么位置 预备知识: 1: 堆中的元素存储在一个数组中,根据堆中的各元素之间具有 有序性关系,可以使用二叉树的方式来表示一个堆。因为各元素从前 至后存放在数组的钱n 个单元中,所以所画的二叉树实际上是一颗完全 二叉树 2: 所以根据完全二叉树的性质,数组前一半的数据都是分值节点,后一半 的数据都是叶子节点 3: 即如果有七个数,分别占据数组的a[1]-a[7],那么7/2=3,所以a[1], a[2],a[3]为分支节点,剩下的为叶子节点 4: a[i]的左儿子为a[i*2],右儿子为a[i*2+1],如a[1]的左右儿子分别为 a[2]与a[3]。(这有赖于数组从a[0]开始,还是从a[1]开始) 建堆的过程: 见代码,见实例图 /*********************************************************/ /*数组从下标1开始*/ #include