今天早上起来完成了一个完整的基于二叉堆实现的优先队列,其中包含最小优先和最大优先队列。

  上篇说了优先队列的特性,通过建堆和堆排序操作,我们就已经看到了这种数据结构中的数据具有某种优先级别,要么非根节点大于他的子节点,要么就相反,在最大优先队列中最大优先级别就是指节点值最大的数据为根节点,每次出队时肯定是最大的先出去,反之则是最小优先队列,但要注意插入时的数据不一定是最大或最小的,优先队列会通过一点小技巧找到所有节点之间的关系并对应起来,重新使得你随意插入的数据满足优先队列的特性,因而这种数据结构的使用很普遍。比如:操作系统中的任务调度等。

  用线性表实现这种数据结构并不难,下面是代码:

/**
* PrioityQueue(优先队列)
*/ #include <stdio.h>
#include <stdlib.h>
#include <conio.h> typedef int ElemType; typedef struct
{
ElemType * arr;
int size;
}Heap; /* 全局函数 */
Heap * Initialize_Heap();
void Build_Min_Heap();
void Build_Max_Heap();
void Heap_Sort();
int Heap_Minimum();
int Heap_Maximum();
int Heap_Extract_Min();
int Heap_Extract_Max();
void Heap_Insert_Max();
void Heap_Insert_Min();
void Destroy_Heap(); /* 静态函数 */
static int HeapParent();
static int HeapLeft();
static int HeapRight();
static void Min_Heapify();
static void Max_Heapify();
static void Heap_Increase_Min_Key();
static void Heap_Increase_Max_Key(); /*
* 初始化堆
* 参数说明:无参数
*
* 返回堆
*/
Heap * Initialize_Heap(void)
{
Heap * heap; heap = (Heap *)malloc(sizeof(Heap));
heap -> arr = (ElemType *)malloc(sizeof(ElemType));
heap -> size = -1; return heap;
} /*
* 节点i的双亲
*/
static int HeapParent(int i)
{
return i/2;
} /*
* 节点i的左孩子
*/
static int HeapLeft(int i)
{
return 2*i + 1;
} /*
* 节点i的右孩子
*/
static int HeapRight(int i)
{
return 2*(i + 1);
} /*
* 维护最小堆的性质
*/
static void Min_Heapify(Heap * heap, int i)
{
int l = HeapLeft(i);
int r = HeapRight(i);
int smallest;
int temp; if(l < heap -> size && heap -> arr[l] < heap -> arr[i])
smallest = l;
else
smallest = i;
if(r < heap -> size && heap -> arr[r] < heap -> arr[i])
smallest = r;
if(smallest != i)
{
temp = heap -> arr[i];
heap -> arr[i] = heap -> arr[smallest];
heap -> arr[smallest] = temp;
Min_Heapify(heap, smallest);
}
} /*
* 维护最大堆的性质
*/
static void Max_Heapify(Heap * heap, int i)
{
int _L = HeapLeft(i);
int _R = HeapRight(i);
int largest;
int temp; if(_L < heap -> size && heap -> arr[_L] > heap -> arr[i])
largest = _L;
else
largest = i;
if(_R < heap -> size && heap -> arr[_R] > heap -> arr[largest])
largest = _R;
if(largest != i)
{
temp = heap -> arr[i];
heap -> arr[i] = heap -> arr[largest];
heap -> arr[largest] = temp;
Max_Heapify(heap, largest);
}
} /*
* 建最小堆
*/
void Build_Min_Heap(Heap * heap)
{
int i; for(i = heap -> size/2; i >= 0; i--)
Min_Heapify(heap, i);
} /*
* 建最大堆
*/
void Build_Max_Heap(Heap * heap)
{
int i; for(i = heap -> size/2; i >= 0; i--)
Max_Heapify(heap, i);
} /*
* 最大优先队列 - 排序
*/
void Heap_Sort(Heap * heap)
{
int i;
int temp; Build_Max_Heap(heap);
for(i = heap -> size; i >= 0; i--)
{
temp = heap -> arr[0];
heap -> arr[0] = heap -> arr[i];
heap -> arr[i] = temp;
-- heap -> size;
Max_Heapify(heap, 0);
}
} /*
* 最小优先队列 - 最小值
*/
int Heap_Minimum(Heap * heap)
{
return heap -> arr[0];
} /*
* 最大优先队列 - 最大值
*/
int Heap_Maximum(Heap * heap)
{
return heap -> arr[0];
} /*
* 最小优先队列 - 去除最小值节点
*/
int Heap_Extract_Min(Heap * heap)
{
int min; if(heap -> size < 0)
{
fprintf(stderr, "Heap underflow!\n");
return 0;
}
min = heap -> arr[0];
heap -> arr[0] = heap -> arr[heap -> size];
heap -> arr[heap -> size] = min;
-- heap -> size;
Min_Heapify(heap, 0); return min;
} /*
* 最大优先队列 - 去除最大值节点
*/
int Heap_Extract_Max(Heap * heap)
{
int max; if(heap -> size < 0)
{
fprintf(stderr, "Heap underflow!\n");
return 0; //提前退出
}
max = heap -> arr[0];
heap -> arr[0] = heap -> arr[heap -> size];
-- heap -> size;
Max_Heapify(heap, 0); return max;
} /*
* 将key的值赋给节点i。此处将key值插入最小堆中
*
* 参数说明:
* 1.接收一个已存在的堆
* 2.节点位置
* 3.与堆节后数据相同类型的键值
*/
static void Heap_Increase_Min_Key(Heap * heap, int i, ElemType key)
{
int temp; if(key > heap -> arr[i])
{
printf("请输入小于当前节点值的数据\n");
return ;
}
heap -> arr[i] = key;
while(i > 0 && heap -> arr[HeapParent(i)] > heap -> arr[i])
{
temp = heap -> arr[i];
heap -> arr[i] = heap -> arr[HeapParent(i)];
heap -> arr[HeapParent(i)] = temp;
i = HeapParent(i);
}
} /*
* 将key的值赋给节点i。此处将key值插入最大堆中
*
* 参数说明:
* 1.接收一个已存在的堆
* 2.节点位置
* 3.与堆节后数据相同类型的键值
*/
static void Heap_Increase_Max_Key(Heap * heap, int i, ElemType key)
{
int temp; if(key < heap -> arr[i])
{
printf("请输入大于当前节点值的数据\n");
return ;
}
heap -> arr[i] = key;
while(i > 0 && heap -> arr[HeapParent(i)] < heap -> arr[i])
{
temp = heap -> arr[i];
heap -> arr[i] = heap -> arr[HeapParent(i)];
heap -> arr[HeapParent(i)] = temp;
i = HeapParent(i);
}
} /*
* 将key值插入最小堆
*/
void Heap_Insert_Min(Heap * heap, ElemType key)
{
++ heap -> size;
heap -> arr[heap -> size] = 65533;
Heap_Increase_Min_Key(heap, heap -> size, key);
} /*
* 将key值插入最大堆
*/
void Heap_Insert_Max(Heap * heap, ElemType key)
{
++ heap -> size;
heap -> arr[heap -> size] = -65533;
Heap_Increase_Max_Key(heap, heap -> size, key);
} /*
* 如果堆存在则销毁堆
*
* 无参数/返回值
*/
void Destroy_Heap(Heap * heap)
{
if(heap && heap -> arr)
{
free(heap -> arr);
free(heap);
heap = NULL;
}
} // 主函数
int main(void)
{
ElemType val;
Heap * heap;
char c;
int i, cont = 0; heap = Initialize_Heap(); puts("1) Insert Heap 2) Extract Max");
puts("3) Display 4) Exit"); while((c = getch()) != '4')
{
switch(c)
{
case '1' : cont ++;
printf("Enter key:");
scanf("%d", &val);
Heap_Insert_Max(heap, val);
break;
case '2' : cont --;
printf("Max key = %d\n", Heap_Extract_Max(heap));
break;
case '3' : Build_Max_Heap(heap);
printf("显示数据:\n");
for(i = 0; i < cont; i++)
printf("%d ", heap -> arr[i]);
printf("NULL\n");
break;
}
}
// Destroy_Heap(); return 0;
}

  参考资料:1.《算法导论》- 堆排序 (84~93)。

       2.百度百科 - 优先队列

       3.百度百科 - 堆

Priority Queue(优先队列)的更多相关文章

  1. Algorithms - Priority Queue - 优先队列

    Priority queue - 优先队列 相关概念 Priority queue优先队列是一种用来维护由一组元素构成的集合S的数据结构, 其中的每一种元素都有一个相关的值,称为关键字(key). 一 ...

  2. priority queue优先队列初次使用

    题目,排队打印问题 Input Format One line with a positive integer: the number of test cases (at most 20). Then ...

  3. 优先队列Priority Queue和堆Heap

    对COMP20003中的Priority queue部分进行总结.图片来自于COMP20003 queue队列,顾名思义特点先进先出 priority queue优先队列,出来的顺序按照优先级prio ...

  4. STL之heap与优先级队列Priority Queue详解

    一.heap heap并不属于STL容器组件,它分为 max heap 和min heap,在缺省情况下,max-heap是优先队列(priority queue)的底层实现机制.而这个实现机制中的m ...

  5. 优先队列(Priority Queue)

    优先队列(Priority Queue) A priority queue must at least support the following operations: insert_with_pr ...

  6. c++ STL:队列queue、优先队列priority queue 的使用

    说明:本文全文转载而来,原文链接:http://www.cppblog.com/wanghaiguang/archive/2012/06/05/177644.html C++ Queues(队列) C ...

  7. 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅴ

    命题Q.对于一个含有N个元素的基于堆叠优先队列,插入元素操作只需要不超过(lgN + 1)次比较,删除最大元素的操作需要不超过2lgN次比较. 证明.由命题P可知,两种操作都需要在根节点和堆底之间移动 ...

  8. 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅳ

    2.4.4 堆的算法 我们用长度为 N + 1的私有数组pq[]来表示一个大小为N的堆,我们不会使用pq[0],堆元素放在pq[1]至pq[N]中.在排序算法中,我们只能通过私有辅助函数less()和 ...

  9. 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅰ

    许多应用程序都需要处理有序的元素,但不一定要求他们全部有序,或者是不一定要以此就将他们排序.很多情况下我们会手机一些元素,处理当前键值最大的元素,然后再收集更多的元素,再处理当前键值最大的元素.如此这 ...

随机推荐

  1. Swiper 移动端全屏轮播图效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  2. alsa driver--card

    1.创建声卡 snd_card是对声卡硬件抽象出来的结构体,几乎所有与声音相关的逻辑设备都是在snd_card的管理之下,声卡驱动的第一个动作通常就是创建一个snd_card结构体. 我们可以通过调用 ...

  3. Java 链接mongodb 执行集合查询

    public static String mongodbConnection(String phone){ String sendCode = null; //创建mongodb链接地址 MongoC ...

  4. maven设置指定jdk版本

    今天心血来潮准备折腾一下jeecg,去下载了一个maven版本的项目,既然下载了maven版的,当然就要配置好maven环境了. 因为之前简单学习过maven,当时使用的版本是3.3.9的,但是今天在 ...

  5. Centos610-Nginx-TCP代理配置

    1.安装Nginx 详见<nginx>安装 2.下载nginx_tcp_proxy_module模块 下载  wget https://github.com/yaoweibin/nginx ...

  6. python-用正则表达式筛选文本信息

    [摘要]  本文主要介绍如何对多个文本进行读取,并采用正则表达式对其中的信息进行筛选,将筛选出来的信息存写到一个新文本. 打开文件:open(‘文件名’,‘打开方式’)>>>file ...

  7. 91云服务器网络带宽测试,IO测试、全国ping测试

    91yun服务器测试一键包介绍 一键包主要是为了让大家快速对服务器的基本状况有一个了解.考虑到天朝的网络出口问题,所以这个一键包更加偏向网络的测试. 影响测试耗时主要是下载,整个测试如果是能跑满100 ...

  8. acm数论之旅--数论四大定理

    ACM数论之旅5---数论四大定理(你怕不怕(☆゚∀゚)老实告诉我)   (本篇无证明,想要证明的去找度娘)o(*≧▽≦)ツ ----------数论四大定理--------- 数论四大定理: 1.威 ...

  9. eclipse链接mySQL数据库常见错误

    1错误: 解决: 2,用户名输入错误 解决:查看自己的正确用户名https://zhidao.baidu.com/question/248308313.html 3. 解决: 链接示例:https:/ ...

  10. Spring的事务实现原理

    主流程 Spring的事务采用AOP的方式实现. @Transactional 注解的属性信息 name                当在配置文件中有多个 TransactionManager , ...