【425】堆排序方法(二叉堆)优先队列(PQ)
参考:漫画:什么是二叉堆?
- 大根堆
- 小根堆
参考:漫画:什么是堆排序?
参考:漫画:什么是优先队列?
参考:【video】视频--第14周10--第8章排序10--8.4选择排序3--堆排序2--堆调整
堆的调整(小根堆)
- 输出堆顶元素之后,以堆中最后一个元素替代之;
- 然后将根节点值与左、右子树的根节点值进行比较,并与其中小者进行交换;
- 重复上述操作,直至叶子节点,将得到新的堆,称这个从堆顶至叶子的调整过程为“筛选”。
大根堆与上面类似。
通过3中方法实现ADT:
- 堆的形式
- 无序array
- 有序array
第一步:一组数据
如下图:

第二步:构建完全二叉树

第三步:构建大根堆
从 last_child/2 节点往前,每个节点与其子节点比较,按照 fixDown 操作,如下图:

第四步:pop 最大值
执行 delMax 操作,将最大值输出,然后将最后的节点编程根节点,然后执行 fixDown 操作,如下图:


参考:HEAP SORT
代码实现如下:
pq.h
// pq.h: ADT interface for a priority queue
#include <stdio.h>
#include <stdlib.h> typedef struct pqRep *PQ; PQ createPQ(int size);
void insertPQ(PQ q, int it);
int delMaxPQ(PQ q);
int isEmptyPQ(PQ q);
pqSort.c
/* pqSort.c: use a priority queue to sort an array of integers
into descending order
*/
#include "pq.h" int main() {
int a[] = {41, 2, 58, 156, 360, 81, 260, 74, 167, 13};
int length = sizeof(a)/sizeof(a[0]); PQ q = createPQ(length);
printf("Array: ");
for (int i = 0; i < length; i++) {
printf("%d ", a[i]);
insertPQ(q, a[i]);
}
printf("\nSorted: ");
while (!isEmptyPQ(q)) {
printf("%d ", delMaxPQ(q));
}
putchar('\n');
return EXIT_SUCCESS;
}
pqHP.c
// pqHP.c: priority queue implementation for pq.h using a heap
#include "pq.h" // 'static' means these functions are for local use only
static void fixDown(int *, int, int);
static void fixUp(int *, int); // Priority queue implementation using an unordered array
struct pqRep {
int nItems; // actual count of Items
int *items; // array of Items
int maxsize; // maximum size of array
}; PQ createPQ(int size) {
PQ q = malloc(sizeof(struct pqRep)); // make room for the structure
if (q == NULL) {
fprintf(stderr, "out of memory\n");
exit(0);
}
q->items = malloc((size+1) * sizeof(int)); // make room for the array
if (q->items == NULL) { // size+1 because heap 1..size
fprintf(stderr, "out of memory\n");
exit(0);
}
q->nItems = 0; // we have no items yet
q->maxsize = size; // remember the maxsize
return q; // return the initial PQ
} void insertPQ(PQ q, int it) {
if (q == NULL) {
fprintf(stderr, "priority queue not initialised\n");
exit(1);
}
if (q->nItems == q->maxsize) {
fprintf(stderr, "priority queue full\n");
exit(1);
}
q->nItems++; // adding another item
q->items[q->nItems] = it; // put the item at the end
fixUp(q->items, q->nItems); // fixUp all the way to the root
return;
} int delMaxPQ(PQ q) {
if (q == NULL) {
fprintf(stderr, "priority queue not initialised\n");
exit(1);
}
if (q->nItems == 0) {
fprintf(stderr, "priority queue empty\n");
exit(1);
}
int retval = q->items[1]; // this is the item we want to return
q->items[1] = q->items[q->nItems]; // overwrite root by last item
q->nItems--; // we are decreasing heap size by 1
fixDown(q->items, 1, q->nItems); // fixDown the new root
return retval;
} int isEmptyPQ(PQ q) {
int empty = 0;
if (q == NULL) {
fprintf(stderr, "isEmptyPQ: priority queue not initialised\n");
}
else {
empty = q->nItems == 0;
}
return empty;
} // fix up the heap for the 'new' element child
void fixUp(int *heap, int child) {
while (child>1 && heap[child/2]<heap[child]) {
int swap = heap[child]; // if parent < child, do a swap
heap[child] = heap[child/2];
heap[child/2] = swap;
child = child/2; // become the parent
}
return;
} // force value at a[par] into correct position
void fixDown(int *heap, int par, int len) {
int finished = 0;
while (2*par<=len && !finished) {// as long as you are within bounds
int child = 2*par; // the first child is here
if (child<len && heap[child]<heap[child+1]) {
child++; // choose larger of two children
}
if (heap[par]<heap[child]) { // if node is smaller than this child ...
int swap = heap[child]; // if parent < child, do a swap
heap[child] = heap[child/2];
heap[child/2] = swap;
par = child; // ... and become this child
}
else {
finished = 1; // else we do not have to go any further
}
}
return;
}
Compile and run:
prompt$ dcc pqHP.c pqSort.c
prompt$ ./a.out
Array: 41 2 58 156 360 81 260 74 167 13
Sorted: 360 260 167 156 81 74 58 41 13 2
通过array来实现ADT,就是每次通过遍历比array里面的最大值,然后输出,并由最后一个元素补位
pqUA.c
// pqUA.c: priority queue implementation for pq.h using an unordered array
#include "pq.h" struct pqRep {
int nItems; // actual count of Items
int *items; // array of Items
int maxsize; // maximum size of array
}; PQ createPQ(int size) {
PQ q = malloc(sizeof(struct pqRep)); // make room for the structure
if (q == NULL) {
fprintf(stderr, "out of memory\n");
exit(0);
} q->items = malloc(size * sizeof(int)); // make room for the array
if (q->items == NULL) {
fprintf(stderr, "out of memory\n");
exit(0);
}
q->nItems = 0; // we have no items yet
q->maxsize = size; // remember the maxsize
return q; // return the initial PQ
} void insertPQ(PQ q, int it) {
if (q == NULL) {
fprintf(stderr, "priority queue not initialised\n");
exit(1);
}
if (q->nItems == q->maxsize) {
fprintf(stderr, "priority queue full\n");
exit(1);
}
q->items[q->nItems] = it; // UNORDERED ARRAY, so put item at the end
q->nItems++; // increment the 'counter'
} int delMaxPQ(PQ q) { // UNORDERED, so need to linear search for max item
if (q == NULL) {
fprintf(stderr, "delmaxPQ: priority queue not initialised\n");
exit(1);
}
if (q->nItems == 0) {
fprintf(stderr, "priority queue empty\n");
exit(1);
}
int *array = q->items;
int last = q->nItems-1; // items occupy places 0 .. last
int max = 0; // assume initially item at max=0 has largest key
for (int i = 1; i <= last; i++){
if (array[max] < array[i]){ // now compare with every other item
max = i; // whenever we find a better one, update max
}
}
int retval = array[max]; // save the max item
array[max] = array[last]; // overwrite max location with last item
q->nItems--; // decrease the number of items
return retval; // return the max element
} int isEmptyPQ(PQ q) {
int empty = 0;
if (q == NULL) {
fprintf(stderr, "isEmptyPQ: priority queue not initialised\n");
}
else {
empty = q->nItems == 0;
}
return empty;
}
也可以通过有序array来实现,就是在插入的过程中就进行排序
pqOA.c
// pqOA.c: priority queue implementation for pq.h using an ordered array
#include "pq.h" struct pqRep {
int nItems; // actual count of Items
int *items; // array of Items
int maxsize; // maximum size of array
}; PQ createPQ(int size) {
PQ q = malloc(sizeof(struct pqRep)); // make room for the structure
if (q == NULL) {
fprintf(stderr, "out of memory\n");
exit(0);
}
q->items = malloc(size * sizeof(int)); // make room for the array
if (q->items == NULL) {
fprintf(stderr, "out of memory\n");
exit(0);
}
q->nItems = 0; // we have no items yet
q->maxsize = size; // remember the maxsize
return q; // return the initial PQ
} void insertPQ(PQ q, int it) {
if (q == NULL) {
fprintf(stderr, "priority queue not initialised\n");
exit(1);
}
if (q->nItems == q->maxsize) {
fprintf(stderr, "priority queue full\n");
exit(1);
}
int *array = q->items;
int last = q->nItems;
int i;
for (i=0; i<last && array[i]<it; i++) {
; // find location of item == it
}
int j;
for (j = last; j>i; j--){ // starting at last and go down to i
array[j] = array[j-1]; // shift items up
}
array[i] = it; // now insert item 'it' at i
q->nItems++; // increase the count
} int delMaxPQ(PQ q) {
if (q == NULL) {
fprintf(stderr, "priority queue not initialised\n");
exit(1);
}
if (q->nItems == 0) {
fprintf(stderr, "priority queue empty\n");
exit(1);
}
q->nItems--;
return q->items[q->nItems];
} int isEmptyPQ(PQ q) {
int empty = 0;
if (q == NULL) {
fprintf(stderr, "isEmptyPQ: priority queue not initialised\n");
}
else {
empty = q->nItems == 0;
}
return empty;
}
【425】堆排序方法(二叉堆)优先队列(PQ)的更多相关文章
- 纯数据结构Java实现(6/11)(二叉堆&优先队列)
堆其实也是树结构(或者说基于树结构),一般可以用堆实现优先队列. 二叉堆 堆可以用于实现其他高层数据结构,比如优先队列 而要实现一个堆,可以借助二叉树,其实现称为: 二叉堆 (使用二叉树表示的堆). ...
- 《Algorithms算法》笔记:优先队列(2)——二叉堆
二叉堆 1 二叉堆的定义 堆是一个完全二叉树结构(除了最底下一层,其他层全是完全平衡的),如果每个结点都大于它的两个孩子,那么这个堆是有序的. 二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组 ...
- 图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)
[0]README 0.1)为什么有这篇文章?因为 Dijkstra算法的优先队列实现 涉及到了一种新的数据结构,即优先队列(二叉堆)的操作需要更改以适应这种新的数据结构,我们暂且吧它定义为Dista ...
- 结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆
实现优先队列结构主要是通过堆完成,主要有:二叉堆.d堆.左式堆.斜堆.二项堆.斐波那契堆.pairing 堆等. 1. 二叉堆 1.1. 定义 完全二叉树,根最小. 存储时使用层序. 1.2. 操作 ...
- 优先队列的二叉堆Java实现
package practice; import edu.princeton.cs.algs4.StdRandom; public class TestMain { public static voi ...
- python下实现二叉堆以及堆排序
python下实现二叉堆以及堆排序 堆是一种特殊的树形结构, 堆中的数据存储满足一定的堆序.堆排序是一种选择排序, 其算法复杂度, 时间复杂度相对于其他的排序算法都有很大的优势. 堆分为大头堆和小头堆 ...
- 优先队列之二叉堆与d-堆
二叉堆简介 平时所说的堆,若没加任何修饰,一般就是指二叉堆.同二叉树一样,堆也有两个性质,即结构性和堆序性.正如AVL树一样,对堆的以此操作可能破坏者两个性质中的一个,因此,堆的操作必须要到堆的所有性 ...
- 数据结构与算法——优先队列类的C++实现(二叉堆)
优先队列简单介绍: 操作系统表明上看着是支持多个应用程序同一时候执行.其实是每一个时刻仅仅能有一个进程执行,操作系统会调度不同的进程去执行. 每一个进程都仅仅能执行一个固定的时间,当超过了该时间.操作 ...
- Binary Heap(二叉堆) - 堆排序
这篇的主题主要是Heapsort(堆排序),下一篇ADT数据结构随笔再谈谈 - 优先队列(堆). 首先,我们先来了解一点与堆相关的东西.堆可以实现优先队列(Priority Queue),看到队列,我 ...
随机推荐
- 大数据之路week06--day07(Hadoop生态圈的介绍)
Hadoop 基本概念 一.Hadoop出现的前提环境 随着数据量的增大带来了以下的问题 (1)如何存储大量的数据? (2)怎么处理这些数据? (3)怎样的高效的分析这些数据? (4)在数据增长的情况 ...
- 前端学习笔记--CSS样式--文本
1.文本与文字样式主要的属性: 子标签可以继承父标签的样式: 关于颜色: 文本属性: letter-spacing: line-height: text-align: 字体:
- python_反射——根据字符串获取模块中的属性
1.获取当前模块中的属性 class Person(object): def __init__(self,name,age): self.name = name self.age = age p = ...
- scoket --- 练习
三次握手,四次挥手(面试会问) 三次握手建连 [] 最开始的时候客户端和服务器都是处于CLOSED状态.主动打开连接的为客户端,被动打开连接的是服务器. TCP服务器进程先创建传输控制块TCB,时刻准 ...
- 进击web与web协议
我一直比较抵制web,web的各种协议以及后端与前端的交互,慢慢的发现除了数据和算法其实计算机软件方面还有另一块高地,那就是web协议. 十分感谢极客时间提供了性价比极高的课程,让我遇到了这么好的老师 ...
- AtCoder NIKKEI Programming Contest 2019 E. Weights on Vertices and Edges (并查集)
题目链接:https://atcoder.jp/contests/nikkei2019-qual/tasks/nikkei2019_qual_e 题意:给出一个 n 个点 m 条边的无向图,每个点和每 ...
- php数据类型之查看和判断数据类型
我们知道了一个数据的类型,才能进行下一步操作.后面的时候,大家可以学习到更多的知识——自定义功能(函数). 我们来做一个场景模拟:(注:眼前不用会写这个函数,以后会教大家) 假设,我们可以写一个智能的 ...
- 三十九.NoSQL概述 部署Redis服务 、 部署LNMP+Redis
1. 搭建Redis服务器 在主机 192.168.4.50 上安装并启用 redis 服务 设置变量test,值为123 查看变量test的值 1.1 搭建redis服务器 1.1.1 安装re ...
- 关于java中的值传递和引用传递(也就是地址传递)
概念解释: 值传递,传递值,在函数中形参发生的变化不影响实参. 引用传递,传递对象引用,在函数中形参发生的变化影响实参. ======================================= ...
- CSP考前总结
10.2 考试: 1.数位DP 或者找规律 2.SB题,扫一遍找最大最小即可 3.莫比乌斯反演 出题人相出个数论和数据结构的综合题,但是找不到NOIP级别的,没办法只能忍痛割爱出个莫比乌斯,话说回来, ...