《编程珠玑》阅读小记(11) — 堆
来源:互联网 发布:在线模拟装机软件 编辑:程序博客网 时间:2024/05/17 21:38
章节简述
本章主要介绍堆,用该数据结构解决下面两个重要的问题:
- 排序,采用堆排序算法对n元数组排序,所花的时间不会超过O(nlogn),而且只需要几个字的额外空间;
- 优先级队列,堆通过插入新元素和提取最小元素这两种操作来维护元素集合,每个操作所需的时间都为O(logn);
本章采用自底向上的组织结构,从细节开始逐步过渡到正题。
堆数据结构
该部分介绍堆数据结构的设计思想。
优先级队列实现向量排序算法
优先级队列提供了一种简单的向量排序算法,优先在优先级队列中依次插入每个元素,然后按序删除它们,程序实现代码如下:
/************************************************************************//* * 优先级队列的类实现 *//************************************************************************/#ifndef _PRIQUEUE_H_#define _PRIQUEUE_H_#include <iostream>template<typename T>class PriQueue{private: int n, maxsize; T *x; void swap(int i, int j) { T temp = x[i]; x[i] = x[j]; x[j] = temp; }public: PriQueue(int m) :maxsize(m) { x = new T[maxsize + 1]; n = 0; } void insert(T t) { int i, p; x[++n] = t; //自底向上类似siftup函数内容实现优先级序列 for (i = n ; i > 1 && x[p=i/2] > x[i] ; i = p) swap(p, i); } //输出队列顶并调整队列结构 T extramin() { /*cout << "队列中的数据为:" << endl; for (int i = 1; i <= n; i++) cout << x[i] << "\t"; cout << endl;*/ int i, c; T t = x[1]; x[1] = x[n--]; //自顶向下调整队列结构 for (i = 1; (c = 2 * i) <= n; i = c) { if (c + 1 <= n && x[c + 1] < x[c]) c++; if (x[i] <= x[c]) break; swap(c, i); } return t; }};#endif
main主程序实现如下:
/************************************************************************//* 《编程珠玑》第十四章 堆* 问题:程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表,不允许重复* 方案:使用堆数据结构思想,构造优先级队列,设计出一种向量排序算法*//************************************************************************/#include <iostream>#include <algorithm>#include <cstdlib>#include "PriQueue.h"using namespace std;/************************************************************************//* 解决问题的向量排序算法 *//************************************************************************/template<typename T>void pqsort(T *v , int n){ PriQueue<T> pq(n); for (int i = 0; i < n; i++) { pq.insert(v[i]); } for (int j = 0; j < n; j++) { v[j] = pq.extramin(); }}const int N = 10;int main(){ int arr[N] = { 4, 12 , 56 , 32 , 24 , 68 , 33 , 6 , 7 , 2 }; cout << "排序前输入数据为 :"<<endl; for (int j = 0; j < N; j++) { cout << arr[j] << "\t"; } cout << endl; pqsort(arr,N); cout << "排序后输出数据为 : " << endl; for (int j = 0; j < N; j++) { cout << arr[j] << "\t"; } cout << endl; system("pause"); return 0;}
对于上面实现的优先级队列向量排序算法,n次insert和extractmin操作在最坏情况下的开销是O(nlogn),优于快速排序算法的最坏O(n^2)的复杂度,但是缺点是,该算法需要额外的n+1的字节的空间来存储数组x[0…n];
下面讨论的堆排序,改进了基于优先级队列的向量排序算法,代码更加简洁,而且不需要辅助数组,使用的空间更少。
堆排序算法
对于优先级队列实现的向量排序算法,需要两个数组,一个用于优先级队列,一个用于待排序的元素;而堆排序算法只需要一个数组,因此节省了空间开销。
思想:使用单个数组x同时表示两种抽象结构,左边是堆,右边是输入元素序列。元素的初始顺序是随意的,而最终则是有序的。
算法实现:
这里写代码片
原理
本章最终总结以下几个原理:
- 高效性,堆数据结构形状保证了堆中所有节点和根节点之间相差的层数在logn内,由于树是平衡的,所以函数siftup和siftdown的运行效率很高。堆排序通过在同一个实现数组中包含两种抽象结构(堆和元素序列)来避免使用额外的开销;
- 正确性;
- 抽象性,一个好的工程师能够分清某个组件做什么(用户看到的抽象功能)和如何做(黑盒实现)之间的差别;
- 过程抽象;
- 抽象数据类型:数据类型做什么是由它的方法和方法的规范给出的,而如何做则是由具体实现决定的;
0 0
- 《编程珠玑》阅读小记(11) — 堆
- 《编程珠玑》阅读小记(5) — 编程小事
- 《编程珠玑》阅读小记(1)— 开篇
- 《编程珠玑》阅读小记(3) — 数据决定数据结构
- 《编程珠玑》阅读小记(6) — 算法设计技术
- 《编程珠玑》阅读小记(9) — 取样问题
- 《编程珠玑》阅读小记(10) — 搜索
- 《编程珠玑》阅读小记(8) — 排序
- 《编程珠玑》阅读小记(4) — 编写正确的程序
- 《编程珠玑》阅读小记(7) — 代码调优与节省空间
- 编程珠玑第十四章—堆
- 编程珠玑---第一章 阅读笔记
- 优先队列 (堆的应用)- 编程珠玑
- 【编程珠玑】第十四章 堆(排序,优先级队列)
- 编程珠玑(2)第十四章学习笔记之“堆”
- 编程珠玑(2)第三章阅读笔记
- 编程珠玑(2)第四章阅读笔记
- 最大子向量(编程珠玑阅读笔记)
- python的xml库操作读写文件真是慢的无语,跟直接操作文本型的操作真不是一个级别的
- 替换xml中的非法字符及不可见字符
- linux中强大的screen命令
- 用Python生成不依赖dll的exe的操作步骤简介
- 花生壳与MDaemon架设邮件服务器案例图文教程
- 《编程珠玑》阅读小记(11) — 堆
- avformat_find_stream_info
- git服务器的建立和简单使用(ubuntu)
- MVC视图中@Html.DisplayFor 控件 日期的显示格式
- CentOS下yum安装mysql,jdk以及tomcat
- SD--如何在输出控制中增加自定义字段
- 第十二章,菜单小demo(Android)
- OJ积累--对象数组输入与输出
- npm install mongoose 无响应