各位读者,大家好。 因为算法和数据结构相关的知识都是在国外学的,所以有些词汇翻译的可能不准确,然后一些源代码的注释可能是英文的,如有给大家带来什么不方便,请见谅。今天我想写一下Heap相关的知识,从基本的结构到最后的一些常用functions. Heap 的数据结构其实可以看成Array, 例如a[] = {5,3,6,8,2,1,0}这个数组, 我们可以将其看作如下的结构:

Heap又可以分成2种类型:Max-Heap 和 Min-Heap。 Max-Heap的意思是每一个node的key值都要大于它的children的key值;反之Min-Heap的的结构是每个node的key值都小于它的children的key值。 例如一个Max-Heap的结构如下:

对于以上的Heap 数据结构的分析,可以分析出对于一个含有N个元素的heap或者称之为array,其heap的结构的的高度(level)是1+logN. 例如上面的结构就是1+log7 = 3 层。

如果一个heap当中只有一个element破坏了Max-heap/Min-Heap structure的结构,那么如果希望重构这个heap让其重新维持Max/Min的话,这个element需要跟它的children中的较大的值交换,一直交换到它的children都小于它的key值为止,这个过程最多进行这个tree的高度次(即:the height of tree), 而这个height就是O(logN)。我们称这个过程为Max-Heapify或者Min-Heapify。以下展示的是C++的代码来实现Max-heapify的过程, 如下:

/*
heapify() function is used to keep the heap structure as max/min heap. If there is a node voilate the max/min heap, this function will try to correct it and restructure it still keep the max/min heap property. parameter: 1. a[], the array
2. i; where the node violate the max/min heap
3. n; the numbers of the a[]; return: void */
void heapify(int a[], int i, int n){ int j, temp;
j = *i;//the node i's left node if (j >= n){//i is the leaf of the tree return;
} temp = a[i]; while (j < n) {//i is not the leaf if (a[j]<a[j+]) {//left child is less than right child j = j + ;
} if (temp>a[j]) { break;
} if (temp <= a[j]) {// if node i violate the structure, exchange the values. a[j/] = a[j];
a[j] = temp;
j = j * ;
} }
}

以上的代码展示的是max-heapify 的过程, 那么如何将一个乱续的heap或者array重构成一个max-heap或者min-heap呢?其实有了以上的功能,将一个完全杂乱的heap装换成max-heap就很简单了。我们只需要从倒数第二层的最左边的一个element开始一直向上面的level的nodes做Max-heapify的过程utill to the root of the tree, 最后就一定能将整个heap转化成Max-Heap. 倒数第二层的最左边的一个element的index是N/2 - 1; 这中间的整个过程如下所示:

 

将整个unsorted heap转化成Max-Heap的过程的时间复杂度Efficiency = O(N), 而不是O(LogN); 这个复杂度的推导过程下次再跟大家解释,是通过数学运算推导出来的,这里就不详细解释了。其实这个代码很简单,他的C++的实现代码如下:

/*

 buildMaxHeap functions is used to force and restructure the heap to an maximum heap structure
parameters: 1: a[];
2: n;// the number of the arrary return void
*/ void buildMaxHeap(int a[], int n){ for (int i = n/-; i >= ; i --) { heapify(a, i, n);
} }

进过以上的过程,我们知道了如何将一个无序的heap或者array转换成Max-Heap, 那么接下来我们就解释一下如何将获得的Max-heap进行排序,它主要经过一下几个过程:

1. 交换heap的最后一个key a[N]和heap的root的key a[1]; 此时a[1]破坏了Max-heap的structure,a[N]是最大值。

2. 我们对除了最后几个已经交换过值的elements剩下的tree进行heapfy的过程;//假如从[j.....N]的elements是之前比较过的,那么就只对[1......j-1]进行heapify的过程。

其具体的c++代码的实现过程如下所示:

/*
heapSort function is to sort the heap in an descending or ascending order parameter:
1, a[], //the array
2, n,// how many nodes should be checked in the heapify function, actuall here is not all the node should be checked return void */ void heapSort(int a[], int n){ int temp; for (int i = n-; i >= ; i --) {//the last indices of array is n-1, loop until to the root temp = a[];
a[] = a[i];
a[i] = temp; heapify(a, , i-);
}
}

综合以上的不做,我们已经可以完成对一个完全无序的array或者heap进行heap-sort的过程,它的时间复杂度如下:

Efficiency = O(N)+O(1)+O(N*logN) = O(N*logN);

那么heap的总结就结束了,下周准备写一些Binary Search Tree (BST)的知识。

如果有什么错误的地方,欢迎大家留言指正,谢谢。

Heap Sorting 总结 (C++)的更多相关文章

  1. Heap &amp; Priority Queue

    Heap & Priority Queue Definition & Description: In computer science/data structures, a prior ...

  2. Find K most Frequent items in array

    给定一个String数组,求K个出现最频繁的数. 记录一下查到的资料和思路: 1. 使用heap sorting, 先用hashmap求出单词和词频.需要额外建立一个class Node,把单词和词频 ...

  3. 常见排序算法及其java实现

    最近学习了下java,感觉java在基本语法上与C++非常相似.作为练习,我用java实现了冒泡排序.选择排序.插入排序.基尔排序.快速排序.堆排序.计数排序.合并排序. 以下为实现代码: publi ...

  4. java学习笔记(详细)

    java平台 1.J2SE java开发平台标准版 2.J2EE java开发平台企业版 java程序需要在虚拟机上才可以运行,换言之只要有虚拟机的系统都可以运行java程序.不同系统上要安装对应的虚 ...

  5. 算法分析中最常用的几种排序算法(插入排序、希尔排序、冒泡排序、选择排序、快速排序,归并排序)C 语言版

    每次开始动手写算法,都是先把插入排序,冒泡排序写一遍,十次有九次是重复的,所以这次下定决心,将所有常规的排序算法写了一遍,以便日后熟悉. 以下代码总用一个main函数和一个自定义的CommonFunc ...

  6. Insert or Merge && Insertion or Heap Sort

    原题连接:https://pta.patest.cn/pta/test/1342/exam/4/question/27102 题目如下: According to Wikipedia: Inserti ...

  7. PTA Insertion or Heap Sort

    According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, and gr ...

  8. 1306. Sorting Algorithm 2016 12 30

    1306. Sorting Algorithm Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description One of the f ...

  9. 09-排序3 Insertion or Heap Sort

    和前一题差不多,把归并排序换成了堆排序.要点还是每一次排序进行判断 开始犯了个错误 堆排序该用origin2 结果一直在排序origin ,误导了半天以为是逻辑错误...一直在检查逻辑 建立最大堆 排 ...

随机推荐

  1. 阻塞IO

    服务端 from socket import * server = socket(AF_INET,SOCK_STREAM) server.bind(('127.0.0.1',8080)) server ...

  2. 关于 SVN 项目检出

    前几天呢,同事遇到这么一个问题:他新建了一个工作空间,当他通过 svn 检出公司项目的时候,准备过来测试运行,但是呢出现了下面的报错 [ERROR] Failed to execute goal or ...

  3. HTTP认证方式与https简介

    HTTP认证与https简介 HTTP请求报头: Authorization [ˌɔ:θəraɪˈzeɪʃn] HTTP响应报头: WWW-Authenticate [ɔ:ˈθentɪkeɪt] HT ...

  4. js math对象总结

    1:  Math 对象用于执行数学任务. 2:Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(), Math.sin() 这样的函数只是函数 3:通过把 ...

  5. LeetCode 665. Non-decreasing Array (不递减数组)

    Given an array with n integers, your task is to check if it could become non-decreasing by modifying ...

  6. Linux系列教程(七)——Linux帮助和用户管理命令

    上篇博客我们介绍了Linux文件搜索命令,其中find是用的最多的也是功能最强大的文件或目录搜索命令,和另一个搜索命令locate的区别是,find命令是全盘搜索,刚创建的文件也能搜索的到,而loca ...

  7. Linq Take和Skip详解

    Take()方法的作用就是:从查询结果中提取前n个结果. Skip()方法正好是Take()方法的反面,它可以跳过前n个结果,返回剩余的结果. 例如:查找年龄最大的3个人 表Student的数据是 N ...

  8. Problem C: 是否回文数?

    Description 定义Data类,有一个int类型的属性.定义其构造函数.setValue函数和isPalindrome函数,其中setValue函数用于设置属性值,isPalindrome用于 ...

  9. linux-rmdir

    linux-rmdir rmdir命令用于删除空目录,删除的目录的里面必须无任何东西,有点鸡肋的命令 从下面先建立了一个a文件夹. 命令: rmdir a,即可删除这个空目录,ls 就找不到这个文件夹 ...

  10. 数据库(概念、语法、DBMS、SQL语言:创建数据库、表格,添加、修改、删除数据记录)

    关系型数据库:以表作为实体,以主键和外键关系作为联系的一种数据结构. 主键:在关系型数据库中,用一个唯一的标识符来标志每一行,这个标识符就是主键.主键有两个特点:非空和不能重复. 外键:在关系型数据库 ...