堆排序C++实现

堆排序的具体思路可以查看《算法导论》这本书,一下只提供笔者的C++实现代码,并且将笔者在编写程序的过程当中所遇到的一些细节问题拿出来作一番解释,希望能够对对堆排序有一个透彻的理解。

1、构造一个维护堆性质(最大堆)的函数

这里需要做一个假设:对于数组中下标为i的节点其左子树和右子树都是保持最大堆性质的堆。在假设成立的前提上,经过这一个维护函数维护过的堆才能够保证是一个最大堆。函数的C++实现代码如下:

 //假定对某一个节点i其左,右子树都是都是最大堆,但是对于节点i和它的左右子节点则可能破坏最大堆的性质,我们来写一个函数对这
//情况下的堆来进行维护使整体的堆满足最大堆性质
void MaxHeapify(int* a,int i,int low,int high)//输入为要被排序的数组和根节点,数组a当中被维护的那一部分的下标low,high
{
int l = left(i);//计算下标为i的节点的左子节点
int r = right(i);//计算下标为i的节点的右子节点
int largest;//保存i,l,r(即i和它的左右子节点)之间的最大数的下标
int temp;//交互数组中的数所使用的临时变量
//找到三个数当中最大的那个数,将最大的那个数和i进行互换
if (l<=high && a[l]>a[i])
{
largest = l;
}
else{
largest = i;
} if (r<=high && a[r]>a[largest])
{
largest = r;
}
if (largest != i)
{
temp = a[i];
a[i] = a[largest];
a[largest] = temp;
MaxHeapify(a, largest,low,high);//交换有可能破坏子树的最大堆性质,所以对所交换的那个子节点进行一次维护,而未交换的那个子节点,根据我们的假设,是保持着最大堆性质的。
}
}

代码中还有一个细节需要注意:

 //定义两个有参宏来寻找数组中的数之间的关系
#define left(x) 2*x+1;//获得左节点在数组中的下标
#define right(x) 2*(x+1);//获得右节点在数组中的下标

《算法导论》一书当中的数组都是以1作为起始下标的,所以书中计算左右节点的下标的公式分别为:2*i,2*i+1。但是在C++的程序当中数组都是从0开始的所以我们的计算方式也要进行修改。

建堆函数

这个函数负责将数组中元素的位置进行更改保证数组能够构造成为一个最大堆,实现如下:

//将数组建立为一个最大堆
//调整数组当中数的位置将其处理为一个最大堆
void BuildMaxHeap(int* a,int length)
{
for (int i = length / 2-1; i >= ; i--)
{
MaxHeapify(a, i, , length - );
}
}

其中MaxHeapify函数为在上文中创建的函数。有一个细节的位置和《算法导论》上面的不一样,i=length/2-1,这也是因为数组的起始下标为0所导致的。可以这样理解此处的减1,相当于在以1为起始的数组当中找到这个点之后,对数组整体进行向后位移一个单位就可以得到现在这个点的下标了。

在本节后面的习题当中有提到这么一个问题:为什么是从length/2-1递减到0,而不是从0开始递增到length/2-1呢?从length/2-1递减到0就意味着,从最后的一个非叶节点开始“从小到大”地进行维护,保证每一个点的子树都是最大堆,可以确保最大堆的性质,而如果从0递增到length/2-1则无法保证堆的性质,可以看如下反例:

对数组{14,10,8,16,7}从0递增到length/2-1的堆创建过程如下图所示:

可见无法保证最大堆性质。

堆排序函数

实现程序如下:

 //堆排序函数
void HeapSort(int a[],int length)
{
int temp;
BuildMaxHeap(a,length);
for (int i = length - ; i >= ; i--)
{
//交换根节点和数组的最后一个节点
temp = a[i];
a[i] = a[];
a[] = temp;
MaxHeapify(a, , , i-);//维护从下标为i-1到0的子数组
}
}

在缩减被排列数组这一思路上面我采用的方法是在函数当中输入被排序数组的下标范围。

堆排序的C++代码实现的更多相关文章

  1. 算法与数据结构(十四) 堆排序 (Swift 3.0版)

    上篇博客主要讲了冒泡排序.插入排序.希尔排序以及选择排序.本篇博客就来讲一下堆排序(Heap Sort).看到堆排序这个名字我们就应该知道这种排序方式的特点,就是利用堆来讲我们的序列进行排序.&quo ...

  2. Java常见排序算法之堆排序

    在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...

  3. 高速排序,归并排序,堆排序python实现

    高速排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n^2),平均情况下为O(n*logn),是不稳定的排序 归并排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n*l ...

  4. PAT1098【插入排序+堆排序】

    简单插入排序: 简单插入排序的核心思想: 把一条这么个难看的序列默认分为两个排好序的和未排好序的两个部分: 所以一开始排好序的只有一个a[0](好看的只有一个),难看的有N(数组长度)-1个a[1,n ...

  5. 常见内部排序算法对比分析及C++ 实现代码

    内部排序是指在排序期间数据元素全部存放在内存的排序.外部排序是指在排序期间全部元素的个数过多,不能同时存放在内存,必须根据排序过程的要求,不断在内存和外存之间移动的排序.本次主要介绍常见的内部排序算法 ...

  6. 排序陷阱 List.Sort Linq.OrderBy

    部分内容摘自:http://www.th7.cn/Program/net/201511/692766.shtml C#框架里面主要提供了两种排序方式:Array.Sort Linq.Orderby. ...

  7. Poj2002 Squares

    题意描述:有一堆平面散点集,任取四个点,求能组成正方形的不同组合方式有多少.相同的四个点,不同顺序构成的正方形视为同一正方形. 思路变迁: 1.最简单的方法,直接暴力搜索,即依次取四个顶点,根据其坐标 ...

  8. Python实现八大排序算法(转载)+ 桶排序(原创)

    插入排序 核心思想 代码实现 希尔排序 核心思想 代码实现 冒泡排序 核心思想 代码实现 快速排序 核心思想 代码实现 直接选择排序 核心思想 代码实现 堆排序 核心思想 代码实现 归并排序 核心思想 ...

  9. Linux内存管理与C存储空间

    ELF文件 在学习之前我们先看看ELF文件. ELF分为三种类型:.o 可重定位文件(relocalble file),可执行文件以及共享库(shared library),三种格式基本上从结构上是一 ...

随机推荐

  1. 一些javascript的工具书

    http://pan.baidu.com/s/1jGj9CvO

  2. iOS 自己封装的网络请求,json解析的类

    基本上所有的APP都会涉及网络这块,不管是用AFNetWorking还是自己写的http请求,整个网络框架的搭建很重要. 楼主封装的网络请求类,包括自己写的http请求和AFNetWorking的请求 ...

  3. google浏览器测试时清理缓存、强制不用缓存刷新快捷键(常用、效率)

    Ctrl+Shift+Del  清除Google浏览器缓存的快捷键  Ctrl+Shift+R  重新加载当前网页而不使用缓存内容

  4. Python人工智能之图片识别,Python3一行代码实现图片文字识别

    1.Python人工智能之图片识别,Python3一行代码实现图片文字识别 2.tesseract-ocr安装包和中文语言包 注意:

  5. js 加alert后才能执行方法

    原因是:访问页面时,某些js方法还没初始化(或者还没有加载出来)此时调用肯定不执行.alert起到了延迟的功能,当用户点击确定此时要执行的js恰好初始化完成,能正常执行. 解决方法是 加setTime ...

  6. 002_CentOS-6.4-x86_64安装包的说明

    http://mirrors.sohu.com/centos/6.6/isos/x86_64/?qq-pf-to=pcqq.group //souhu镜像下载地址 0_README.txt 25-Oc ...

  7. 【oracle】入门学习(一)

    一直想学oracle但都没有下定决心.这次借了书,一定要学好oracle. 目前学习 <Oracle从入门到精通> 明日科技 的Oracle 11g 版本 关系型数据库的基本理论 数据模型 ...

  8. CF1006C 【Three Parts of the Array】

    二分查找水题 记$sum[i]$为$d[i]$的前缀和数组 枚举第一段区间的结尾$i$ 然后二分出$lower$_$bound(sum[n]-sum[i])$的位置$x$,如果$sum[x]$与$su ...

  9. MAC下代理工具Charles使用

    一.跟踪HTTPS 1.下载官方的证书ssl.zip证书,解压成*.crt 2.可以通过邮箱或者发布到自己的服务器的方式,然后用手机去下载安装crt文件. 3.charles设置Proxy--> ...

  10. Java编程的逻辑 (62) - 神奇的序列化

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...