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

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

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

/**
* 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. 【转载】Java反射机制详解

    转自:http://baike.xsoftlab.net/view/209.html#3_8 1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对 ...

  2. mediasoup-demo安装记录

    环境CentOS 7 64位 VMWare12虚拟机(win10主机),安装好NodeJS 10.13(大于8.9就可以) 已按照GitHub说明拉下来代码,配置好Node环境,开始执行npm sta ...

  3. 【安卓逆向】ARM常见汇编指令总结

    跳转指令 B 无条件跳转 BL 带链接的无条件跳转 BX 带状态切换的无条件跳转 BLX 带链接和状态的无条件跳转 存储器与寄存器交互数据指令(核心) 存储器:主存和内存 寄存器中放的数据:可以是字符 ...

  4. Android学习14

    Fragment Fragment是依赖于Activity的,不能独立存在的. 一个Activity里可以有多个Fragment. 一个Fragment可以被多个Activity重用. Fragmen ...

  5. 【 Hibernate 】Hibernate的session更新和删除失败问题

    applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xm ...

  6. 外键约束:foreign key

    *外键 foreign key* 1.概念:如果一个实体的(student)的某个字段,指向(引用)另个实体(class)的主键 (class:class_id),就称为student实体的class ...

  7. 基于jmeter+ant实现的接口自动化测试

    jmeter+ANT接口自动化测试框架 项目说明 本框架是一套基于jmeter+Ant+Excel+Python而设计的数据驱动接口自动化测试框架,jmeter 作为执行器,Ant 作为构建工具,进行 ...

  8. 讲解一下类的继承super

    class Test1(object): def __init__(self,ids): self.ids=ids class Par(Test1): def __init__(self,ids,us ...

  9. CentOS6.5_x64安装MySQL-5.6.17,在已经启动MySQL服务的情况下,出现密码报错ERROR 2002 (HY000)

    1.修改MySQL配置文件,使MySQL登陆时跳过密码验证 skip-grant-tables 2.重启MySQL服务 service mysql restart 3.进入MySQL,修改user表中 ...

  10. Linux下编译并使用miracl密码库

    参考:http://blog.sina.com.cn/s/blog_53fdf1590102y9ox.html MIRACL(Multiprecision Integer and RationalAr ...