堆排序

图解排序算法(三)之堆排序

邮差的信 提交于 2020-02-08 23:14:47
预备知识 堆排序   堆排序是利用 堆 这种数据结构而设计的一种排序算法,堆排序是一种 选择排序, 它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。 堆    堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图: 同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子 该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是: 大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] ok,了解了这些定义。接下来,我们来看看堆排序的基本思想及基本步骤: 堆排序基本思想及步骤    堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了 步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。   a.假设给定无序序列结构如下 2

常用算法之----堆排序

喜欢而已 提交于 2020-02-08 22:58:34
预备知识 堆排序   堆排序是利用 堆 这种数据结构而设计的一种排序算法,堆排序是一种 选择排序, 它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。 堆    堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图: 同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子 该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是: 大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] ok,了解了这些定义。接下来,我们来看看堆排序的基本思想及基本步骤: 堆排序基本思想及步骤    堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了 步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。   a.假设给定无序序列结构如下 2

图解排序算法(三)之堆排序

≡放荡痞女 提交于 2020-02-08 17:40:56
图解排序算法(三)之堆排序 预备知识 堆排序   堆排序是利用 堆 这种数据结构而设计的一种排序算法,堆排序是一种 选择排序, 它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。 堆    堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图: 同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子 该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是: 大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] ok,了解了这些定义。接下来,我们来看看堆排序的基本思想及基本步骤: 堆排序基本思想及步骤    堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了 步骤一 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。   a.假设给定无序序列结构如下 2

堆排序

六月ゝ 毕业季﹏ 提交于 2020-02-08 17:26:11
堆排序 定义 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。 堆 是一种完全二叉树, 堆 有两种类型: 大根堆 小根堆 ,两种类型的概念如下: 大根堆:每个结点的值都大于或等于左右孩子结点 小根堆:每个结点的值都小于或等于左右孩子结点 大根堆 小根堆 完全二叉树 :是 一种除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐的树 算法描述 首先将待排序的数组构造出一个大根堆 取出这个大根堆的堆顶节点(最大值),与堆的最下最右的元素进行交换,然后把剩下的元素再构造出一个大根堆 重复第二步,直到这个大根堆的长度为1,此时完成排序。 代码实现 def heapify ( arr , n , i ) : largest = i l = 2 * i + 1 # left = 2*i + 1 r = 2 * i + 2 # right = 2*i + 2 if l < n and arr [ i ] < arr [ l ] : largest = l if r < n and arr [ largest ] < arr [ r ] : largest = r if largest != i : arr

数据结构——堆排序

╄→гoц情女王★ 提交于 2020-02-08 16:44:36
堆排序算法就是通过维护一个小根堆或者大根堆的数据结构。小/大根堆本质上是一个完全二叉树。利用了完全二叉树的性质,即完全二叉树节点x的子节点编号为2x和2x+1。 利用这个性质,我们可以让一个一维数组来模拟这个二叉树,数组下标从1开始建立,下标为2*x和2*x+1的就是x的左子树和右子树。 #include<bits/stdc++.h> using namespace std; const int N = 100010; //h[n]是堆数组(一维存储) int h[N]; //s表示的是堆的大小,就是size int s; //向下维护堆(此代码是小根堆) void down(int x){ int t = x; //判断x是否小于左右子节点 if( x*2 <= s && h[x*2] < h[t]) t = x*2; if( x*2+1 <= s && h[x*2+1] < h[t]) t = x*2+1; //如果x小于了左右子节点,则交换数值 if( t != x){ swap(h[t],h[x]); //递归维护子节点的子节点 down(t); } return ; } int main(){ ios::sync_with_stdio(0); cin.tie(); int n,m; cin>>n>>m; for(int i = 1 ; i <= n ; i ++ ){

排序算法--堆排序

你说的曾经没有我的故事 提交于 2020-02-08 09:36:04
重新学习数据结构里面的堆排序,堆排序是基础排序算法里面效率最好的 实现: #include <iostream> #include <cmath> using namespace std; template <class T> //n是待排序序列的长度 //p[n]是待排序序列 //这里用了template,用于泛型 void sift(T p[],int i,int n) { int j; T t; t=p[i]; j=2*(i+1)-1; while(j<=n) { if((j<n)&&(p[j]<p[j+1])) j=j+1; if(t<p[j]) { p[i]=p[j]; i=j; j=2*(i+1)-1; } else j=n+1; } p[i]=t; return; } template <class T> void hip_sort(int n,T p[]) { int i; int mm; mm=n/2; for(i=mm-1;i>=0;i--) { sift(p,i,n-1); } for(i=n-1;i>=1;i--) { t=p[0]; p[0]=p[i]; p[i]=t; sift(p,0,i-1); } return; } 来源: CSDN 作者: HWQlet 链接: https://blog.csdn.net/HWQlet/article

排序算法

社会主义新天地 提交于 2020-02-08 05:13:18
排序算法 文章目录 排序算法 1.数据结构定义 2.冒泡排序 3.冒泡排序的改进 4.简单选择排序 5.直接插入排序 6.希尔排序(相当于直接插入排序的升级,先搞懂插入排序) 7.堆排序(相当于简单选择排序的升级) 8.归并排序 9.快速排序(冒泡排序的升级) 参考 1.数据结构定义 # define MAXSIZE 10000 /* 用于要排序数组个数最大值,可根据需要修改 */ typedef struct { int r [ MAXSIZE + 1 ] ; /* 用于存储要排序数组,r[0]用作哨兵或临时变量 */ int length ; /* 用于记录顺序表的长度 */ } SqList ; /* 交换L中数组r的下标为i和j的值 */ void swap ( SqList * L , int i , int j ) { int temp = L -> r [ i ] ; L -> r [ i ] = L -> r [ j ] ; L -> r [ j ] = temp ; } 2.冒泡排序 平均时间复杂度:O(n2) 从后往前依次比较相邻的两个数,如果后面的数比较小就交换位置,这样的话每循环一次就会有一个最小值被换到最前面了,然后再依次把其他的数冒上去。 go语言实现: // BubbleSort 冒泡排序 func BubbleSort ( array [ ] int

必须知道的八大种排序算法【java实现】(三) 归并排序算法、堆排序算法详解

不羁岁月 提交于 2020-02-07 09:07:29
一、归并排序算法 基本思想:   归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。 归并排序示例: 合并方法: 设r[i…n]由两个有序子表r[i…m]和r[m+1…n]组成,两个子表长度分别为n-i +1、n-m。 j=m+1;k=i;i=i; //置两个子表的起始下标及辅助数组的起始下标 若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束 //选取r[i]和r[j]较小的存入辅助数组rf 如果r[i]<r[j],rf[k]=r[i]; i++; k++; 转⑵ 否则,rf[k]=r[j]; j++; k++; 转⑵ //将尚未处理完的子表中元素存入rf 如果i<=m,将r[i…m]存入rf[k…n] //前一子表非空 如果j<=n , 将r[j…n] 存入rf[k…n] //后一子表非空 合并结束。 算法实现:   /** * 归并排序 * 简介:将两个(或两个以上)有序表合并成一个新的有序表 即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列 * 时间复杂度为O(nlogn) * 稳定排序方式 * @param nums 待排序数组 * @return 输出有序数组 */ public static int[]

堆排序(大小根堆实现)

蓝咒 提交于 2020-02-05 21:24:18
文章目录 堆排序 堆的定义 堆排序 构造大根堆 构造小根堆 实现堆排序 测试代码 算法复杂度 堆排序 堆排序的基本思想: 对于一组待排序数据,首先按堆的定义建立初始堆(大根堆或小根堆); 取出堆顶元素(最大或最小),将剩余的元素继续调整成新堆,就得到次大或次小元素; 反复执行 1、2 ,直到全部元素排序成顺序或逆序,堆排序结束 堆的定义 对于 n 个元素的序列 {K1, K2, …, Kn},当且仅当满足下列关系时称为堆,其中 2i 和 2i +1应不大于 n 其中,1 <= i <= n/2 当任意 K[i] 都小于 K[2i] 和 K[2i + 1] 时,为小根堆 当任意 K[i] 都大于 K[2i] 和 K[2i + 1] 时,为大根堆 堆排序   堆排序是一种树形选择排序,可以将待排序数组看成是一个完全二叉树,则由堆的定义表明,该完全二叉树中,所有非叶子节点的值都不大于(或不小于)其左、右孩子节点的值。   因此,在一个堆中,堆顶元素(二叉树根节点)必定为该序列中的最大(或最小)元素。   所以堆排序就是,先构造堆,取堆顶元素,再构造新堆,重复这一过程,直到排序完成 假设待排序数组为:N = {55, 60, 40, 10, 80, 65, 15, 5, 75}; 结构如下: 构造大根堆 构造大根堆,要使得该二叉树中所有非叶子节点的值都大于其左右节点,及使节点 1、2、3

堆与堆排序——数据结构的克星

两盒软妹~` 提交于 2020-02-05 13:58:28
其实建堆和堆排序十分的简单,就是不断的向下调整的过程 建堆是从floor(2/i)处开始,一直到根节点,依次不断的向下调整 堆排序是从最后一个节点不断的与第一个根节点交换,然后再让第一 个节点不断的向下的调整 # include <bits/stdc++.h> using namespace std ; int a [ 15 ] = { - 1000 , 1 , 5 , 6 , 3 , 9 , 5 , 4 , 2 , 7 , 7 } ; int n = 10 ; //表示数组的长度 void adjust_down ( int i , int len ) { int left = 2 * i ; int right = 2 * i + 1 ; int m = i ; //记录最大值 if ( left <= len && a [ m ] < a [ left ] ) { m = left ; } if ( right <= len && a [ m ] < a [ right ] ) { m = right ; } if ( m != i ) //如果左右孩子都不满足,就不需要继续向下跟新了 { swap ( a [ m ] , a [ i ] ) ; adjust_down ( m , len ) ; } } void build_heap ( ) { for ( int i =