1 数组对象

2 可以视为一棵完全二叉树

3 一个堆可以被看作一棵二叉树和一个数组,如下图所示:

4 下标计算(通常使用内联函数或者宏来定义下标操作):

  • 已知某个结点的下标为i
  • 其父节点下标:i/2向下取整
  • 左孩子下标:2i
  • 右孩子下标:2i+1

5 最大堆:除根节点以外的每个节点i,有A[PARENT(i)] >= A[i]

最小堆:除根节点意外的每个节点i,有A[PARENT(i)] <= A[i]


堆排序

步骤:

  1. 建大顶堆
  2. 去堆顶元素与当前堆的最后一个元素进行互换。
  3. 该堆顶元素已达最终位置,排除出堆
  4. 对剩下的堆进行最大堆调整
  5. 重复2到4步

排序过程

1 建堆过程

1) 从第一个非叶子节点开始,对value为8的节点进行调整,无需调整。

2) 对value值为9的节点进行调整。

3) 对value为2的节点调整

4) 对value为3的节点进行调整

     ----》

5) 对value为7的节点进行调整

  ---》

建堆完成

2 堆顶元素与当前堆的最后一个元素进行互换。

3 该堆顶元素已达最终位置,排除出堆

4 对剩下的堆进行调整

递归进行堆首和堆尾互换以及调整堆的步骤,结果即为排好序的堆。



代码实现

// heapsort.h
class HeapSort:public BaseSort {
public:
HeapSort(int Array[], int len) : BaseSort() {
this-&gt;Array = Array;
this-&gt;len = len;
}
void sort();
private:
/* 建堆 */
void buildMaxHeap(); /* 调整堆,以保持最大堆性质 */
void maxHeapIfy( int i , int curlen); /* 堆排序 */
void heapSort(); /* 返回父节点下标 */
int Parent(int i) {
if ( i % 2 == 0 )
return i/2;
else
return i/2 + 1;
}; /* 返回左孩子节点下标 */
int Left(int i) { return 2 * i + 1; }; /* 返回右孩子节点下标 */
int Right(int i) { return 2 * i + 2; };
private:
int* Array;
int len;
};

相关成员函数实现

// heapsort.cpp
#include "heapsort.h"
void HeapSort::sort() {
heapSort();
}
void HeapSort::heapSort() { buildMaxHeap();
int i = this->len;
int tmp;
while( i > 0 ) {
tmp = this->Array[0];
this->Array[0] = this->Array[i-1];
this->Array[i-1] = tmp;
i--;
maxHeapIfy(0, i);
}
}
void HeapSort::maxHeapIfy( int i, int curlen ) {
int left, right, largest;
int tmp;
left = Left(i);
right = Right(i);
if ( left < curlen-1
&& Array[left] > Array[i])
largest = left;
else
largest = i;
if ( right < curlen-1
&& Array[right] > Array[largest])
largest = right;
if ( largest != i ) {
tmp = Array[i];
Array[i] = Array[largest];
Array[largest] = tmp;
maxHeapIfy(largest, curlen);
}
}
void HeapSort::buildMaxHeap() {
int i;
for ( i = (len-1)/2 ; i >= 0; i-- ) {
maxHeapIfy(i, len);
if (DEBUG) {
printArray(this->Array, this->len, "midResult");
}
}
}

测试代码:

 /* --------- HeapSort -------- */
int b[10] = {7,3,2,9,8,5,1,10,4,6};
HeapSort* heapsort = new HeapSort(b, len);
heapsort->sort();
printArray(b, len, "HeapSort ");

参考资料:

《算法导论 2rd》

http://www.cnblogs.com/Anker/archive/2013/01/23/2873422.html  《算法导论》读书笔记之第6章 堆排序

排序算法(2) 堆排序 C++实现的更多相关文章

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

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

  2. Java排序算法之堆排序

    堆的概念: 堆是一种完全二叉树,非叶子结点 i 要满足key[i]>key[i+1]&&key[i]>key[i+2](最大堆) 或者 key[i]<key[i+1] ...

  3. 排序算法之堆排序(Heapsort)解析

    一.堆排序的优缺点(pros and cons) (还是简单的说说这个,毕竟没有必要浪费时间去理解一个糟糕的的算法) 优点: 堆排序的效率与快排.归并相同,都达到了基于比较的排序算法效率的峰值(时间复 ...

  4. 《排序算法》——堆排序(大顶堆,小顶堆,Java)

    十大算法之堆排序: 堆的定义例如以下: n个元素的序列{k0,k1,...,ki,-,k(n-1)}当且仅当满足下关系时,称之为堆. " ki<=k2i,ki<=k2i+1;或k ...

  5. C++编程练习(13)----“排序算法 之 堆排序“

    堆排序 堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆(也叫最大堆):或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆(也叫最小堆). 最小堆和最大堆如 ...

  6. 数据结构与算法之PHP排序算法(堆排序)

    一.堆的定义 堆通常是一个可以被看做一棵树的数组对象,其任一非叶节点满足以下性质: 1)堆中某个节点的值总是不大于或不小于其父节点的值: 每个节点的值都大于或等于其左右子节点的值,称为大顶堆.即:ar ...

  7. 八大排序算法之七—堆排序(Heap Sort)

    堆排序是一种树形选择排序,是对直接选择排序的有效改进. 基本思想: 堆的定义如下:具有n个元素的序列(k1,k2,...,kn),当且仅当满足 时称之为堆.由堆的定义可以看出,堆顶元素(即第一个元素) ...

  8. Python 一网打尽<排序算法>之堆排序算法中的树

    本文从树数据结构说到二叉堆数据结构,再使用二叉堆的有序性对无序数列排序. 1. 树 树是最基本的数据结构,可以用树映射现实世界中一对多的群体关系.如公司的组织结构.网页中标签之间的关系.操作系统中文件 ...

  9. 排序算法FOUR:堆排序HeapSort

    /** *堆排序思路:O(nlogn) * 用最大堆,传入一个数组,先用数组建堆,维护堆的性质 * 再把第一个数与堆最后一个数调换,因为第一个数是最大的 * 把堆的大小减小一 * 再 在堆的大小上维护 ...

随机推荐

  1. MySQL decimal unsigned 更新负数不报错却为0

    今天在验证接口的并发问题时,把之前通过 redis 解决的并发压力转移到 mysql 上(redis 在 set 保存数据和数据过期需要去向数据库获取时存在时延,会存在空挡造成大并发多插入数据的风险: ...

  2. JavaScript中函数的变量提升问题

    函数的大体分三种,一种是函数的声明,一种是函数表达式(又称为函数的字面量) 1.函数的声明 => function myFn(){}; 2.函数的表达式 => var myFn = fun ...

  3. Fiddler实现手机抓包——小白入门(转载csdn)

    手机用fiddler抓包 电脑最好是笔记本,这样能和手机保持统一局域网内:其他不多说,直接说步骤了. 一.对PC(笔记本)参数进行配置    1. 配置fiddler允许监听到https(fiddle ...

  4. JavaScript窗口打开与关闭及如何使用opener使子窗口对父窗口进行操作

    一.打开与关闭窗口 1.打开窗口:可以使用window对象中的Open()方法. newWindow = window.open(url,windowname,location); 参数说明: url ...

  5. Shell如何解决文件流管道的文本拼接失效问题

    前言: 近期由于业务的需要,需实现通过监控日志文件的内容并定时将日志的有效内容通过邮件进行告警. 文本内容的格式如下: 1 aaa 2 bbb 4 ccc 7 ddd 希望输出: bbb ccc 版本 ...

  6. Linux 文件流管理

    1. 打开/关闭文件 1). 打开文件 / fopen 作用: 打开一个文件,将其与文件流联系起来,方便后续的操作 头文件: #include <stdio.h> 函数原型: FILE * ...

  7. java.sql.SQLException: Access denied for user 'root '@'localhost' (using password: YES) 最蠢

    我犯了七年前的错误,一个空格,昨天就想到的,还对比了一下密码有没有空格 问题原因1:多写空格 在datasource.properties 中的username 的值root后面多写了一个空格, jd ...

  8. Walkway.js – 创建简约的 SVG 线条动画

    Walkway.js 是一个使用线条和路径元素组成 SVG 动画图像的简单方法.只需根据提供的配置对象创建一个新的 Walkway 实例就可以了.这种效果特别适合那些崇尚简约设计风格的网页.目前, W ...

  9. vue项目引入element

    前提工作-安装并配置好以下环境: 1.安装node  2.安装git 1.初始化项目 vue init webpack vue-elementui npm run dev 2.安装element np ...

  10. Docker部署golang微服务项目

    这篇博客是为了记录一下部署步骤. 因为实训需要,我要在服务器上用docker部署我们小组的微服务项目.我们的微服务有Gateway,User,Scene,Device四个部分,分别占用不同的端口,其中 ...