数据结构与算法分析

优先队列

模型

  • Insert(插入) == Enqueue(入队)
  • DeleteMin(删除最小者) == Dequeue(出队)

基本实现

  • 简单链表:在表头插入,并遍历该链表以删除最小元

    时间代价昂贵

  • 二叉查找树

    二叉查找树支持许多不需要的操作,实现麻烦,不值得

最合适:二叉堆


二叉堆

堆的两种性质

结构性

  • 完全二叉树:除底层外完全填满,底层也是从左至右填
  • 完全二叉树的高为
  log N
  • 分布很有规律可以用数组实现

左儿子 = 2i

右儿子 = 2i + 1

堆序性

  • 树的最小元应该在根节点上
  • 每个节点X,X的父亲的关键字应该小于或等于X的关键字

实现

优先队列的声明

struct HeapStrcut ;
typedef struct HeapStruct *PriorityQueue ; PriorityQueue Intialize(int MaxElement) ;
void Destory(PriorityQueue H) ;
void MakeEmpty(PriorityQueue H) ;
void Insert(ElementType X, PriorityQueue H) ;
ElementType DeleteMin(PriotityQueue H) ;
ElementType Find(PritityQueue H) ;
int IsEmpty(PriorityQueue H) ;
int IsFull(PriorityQueue H) ; srtuct HeapStruct
{
int Capacity ;
int Size l
ElementType *Elements ;
}

初始化

PriorityQueue Intialize(int MaxElement)
{
PriorityQueue H ;
H->Elements = malloc((MaxElement + 1) * sizeof(ElementType) ;
if(H->Elements == NULL)
FatalError("内存不足");
H->Capacity = MaxElement ;
H->Size = 0;
H->Elements[0] = MinData ;//在根节点赋一个绝对的小的值 return H ;
}

Insert操作

上滤

void Insert(ElementType X, PriorityQueue H)
{
int i ;
if(IsFull(H))
Error("堆满") ; for(i = ++H->Size;H->Elements[i/2] > X;i/2)
H->Elenemts[i] = H->Elements[i/2] ;
H->Elements[i] = X ; return H ;
}

Delete函数

下滤

先拿到最后一个元素,和当前被删除后剩下的空穴的最小儿子比较,如果儿子小则换至空穴,继续下滤,反之将最后一个元素放置空穴结束下滤

ElementType Insert(PriorityQueue H)
{ int i,Child ;
ElementType MinElement,LastElement ; if(IsEmpty(H))
{
Error("堆为空") ;
return H->Elements[0] ;
}
MinElement = H->Elements[1];
LastElement = H->Elements[H->Size--] ;
for(i = 1; i * 2 <= H->Size;i = Child)
{
Child = i * 2;
if(Child != H->Size && H->Element[Child] > H->Elements[Child + 1])
Child ++ ; if(LastElement > H->Elements[Child)
H->Elements[i] = H->Elements[Child] ;
else break ;
}
H->Elements[i] = LastElement ; return MinElenemt;
}

左式堆

性质

高效支持Merge操作

和二叉树唯一区别在于:左式堆不是理想平衡的

对于堆中的每一个节点X,左儿子的零路径长NPL大于右儿子的零路径长NPL

- 零路径长(NPL):从该节点到一个没有两个儿子的节点的最短路径长

左式堆的类型声明

PriorityQueue Intailize(void) ;
ElementType FindMin(PriorityQueue H) ;
int IsEmpty(PriorityQueue H) ;
PriorityQueue Merge(PriorityQueue H1,PriorityQueue H2) ; #define Insert(X,H) (H = Insert1(X,H)) ; //为了兼容二叉堆 PriorityQueue Insert1(ElementType, PriorityQueue H) ;
PriorityQueue DeleteMin(PriorityQueue H) ; sturct TreeNode
{
ElementType Element ;
PriorityQueue Left ;
PriorityQueue Right ;
int Npl ;
}

Merge操作

驱动程序

PriorityQueue Merge(PriorityQueue H1,PriorityQueue H2)
{
if(H1 == NULL)
return H2 ;
eles if(H2 == NULL)
return H1 ;
else if(H1->Element > H2->Element)
return Merge1(H1,H2) ;
else
return Merge1(H1S,H2) ;
}

实际操作

PriorityQueue Merge1(PriortyQueue H1,PriorityQueue H2)
{
if(H1->Left == NULL)
H1->Left = H2 ;
else
{
H2->Right = Merge1(H1->Right,H2) ;
if(H1->Left->Npl < H1->Right->Npl)
SwapChildren(H1) ;
H1->Npl = H1->Right->Npl + 1;
} return H1 ;
}

Insert操作

PriorityQueue Insert(ElementType X,PriorityQueue H)
{
PriorityQueue SinglNode ;
SinglNode = malloc(sizeof(TreeNode)) ;
if(SinglNode == NULL)
FatalError("内存不足") ;
else
{
SingleNode->Element = X ;
SingleNode->Npl = 0 ;
SingleNode->Left = SingleNode->Right = NULL ;
Merge(SingleNode,H) ;
}
return H ;
}

Delete操作

PriorityQueue DeleteMin1(PriorityQueue H)
{
PriorityQueue LeftHeap,RightHeap ; if(IsEmpty(H))
FatalError("队列为空") ;
else
{
LeftHeap = H1->Left ;
RightHeap = H1->Right ;
free(H) ;
Merge(LeftHeap,RightHeap) ;
}
}

二项队列

结构

  • 二项队列是堆序树的集合,称为森林
  • 堆序中每颗树都是有约束的树,称为二项树
  • 高度为k的二项树有一颗二项树Bk-1附接到另一颗二项树Bk-1的根上

二项队列的实现

二项队列将是二项树的数组

二项树的每个节点包含数据,第一个儿子和兄弟

二项队列的类型声明 `

typedef struct BinNode *Position ;
typedef struct Collection *BinQueue ; struct BinNode
{
ElementType Element ;
Position LeftChild ;
Position NextBiling ;
} typedef Position BinTree ; struct Collection
{
int CurrentSize ;
BinTree TheTrees[MaxTree] ;
}

Merge操作

合并两个相同大小的两颗二项树

BinTree ConbineTrees(BinTree T1,BinTree T2)
{
if(T1->Element > T2->Element)
return CombineTree(T2,T1) ;
T2->NextBling = T1->LeftChild ;
T1->LeftChild = T2 ; return T1 ;
}

合并两个优先队列

BinQueue Merge(BinQueue H1,BinQueue H2)
{
BinTree T1,T2,Carry = NULL ;
int i ,j ;
if(H1->CurrentSize + H2->CurrentSize > Capacity)
Error("合并后过大") ; H1->CurrentSize += H2->CurrentSize ;
for(i = 0;j = 1;j <= H1->CurrentSize; i++,j *= 2)
{
T1 = H1->TheTree[i] ;
T2 = H2->TheTree[i] ; switch(!!T1 + 2 * !!T2 + 4 * !!Carry)
{
case 0 : //空树
case 1:
break ; //只有H1
case 2:
H1->TheTree[i] = T2
H2->TheTree[i] = NULL ;
break ;
case 4:
H1->TheTree[i] = Carry ;
Carry = NULL ;
case 3: //h1 and h2
Carry = CombineTrees(T1,T2) ;
H1->TheTree[i] = H1->TheTree[i] = NULL ;
break ;
case 5: //h1 and carry
Carry = ConbineTrees(T1,Carry) ;
H1->TheTrees[i] = NULL ;
case 6:
Carry = ConbineTrees(T2,Carry) ;
H2->TheTrees[i] = NULL ;
case 7: //都有
H1->TheTree[i] = Carry ;
Carry = CombineTrees(T1,T2) ;
H2->TheTrees[i] = NULL ;
break ; } }
return H1 ;
}

总结

优先队列可以用二叉堆实现,简单快速

但考虑到Merge操作,又延申了左式堆和二次队列

优先队列(堆) -数据结构(C语言实现)的更多相关文章

  1. 数据结构( Pyhon 语言描述 ) — —第10章:树

    树的概览 树是层级式的集合 树中最顶端的节点叫做根 个或多个后继(子节点). 没有子节点的节点叫做叶子节点 拥有子节点的节点叫做内部节点 ,其子节点位于层级1,依次类推.一个空树的层级为 -1 树的术 ...

  2. Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET

    Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET Python -- 堆数据结构 heapq 分类: Python 2012-09 ...

  3. 数据结构(C语言)—排序

    数据结构(C语言)—排序 排序 排序是按关键字的非递增或递减顺序对一组记录中心进行排序的操作.(将一组杂乱无章的数据按一定规律顺次排列起来.) 未定列表与不稳定列表 假设 Ki = Kj ( 1 ≤ ...

  4. c++学习书籍推荐《清华大学计算机系列教材:数据结构(C++语言版)(第3版)》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <清华大学计算机系列教材:数据结构(C++语言版)(第3版)>习题解析涵盖验证型.拓展型.反思型.实践型和研究型习题,总计290余道大题.525道 ...

  5. 数据结构C语言版 有向图的十字链表存储表示和实现

    /*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...

  6. 数据结构C语言版 表插入排序 静态表

    数据结构C语言版 表插入排序.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情./*  数据结构C语言版 表插入排序  算法10.3 P267-P270  编译 ...

  7. 数据结构C语言版 弗洛伊德算法实现

    /* 数据结构C语言版 弗洛伊德算法  P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...

  8. 《数据结构-C语言版》(严蔚敏,吴伟民版)课本源码+习题集解析使用说明

    <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明 先附上文档归类目录: 课本源码合辑  链接☛☛☛ <数据结构>课本源码合辑 习题集全解析  链接☛☛☛  ...

  9. 堆的C语言实现

    在C++中,可以通过std::priority_queue来使用堆. 堆的C语言实现: heap.c /** @file heap.c * @brief 堆,默认为小根堆,即堆顶为最小. */ #in ...

  10. Python实现堆数据结构

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/3/18 19:47 # @Author : baoshan # @Site ...

随机推荐

  1. HDU1005 Number Sequence(找规律,周期是变化的)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1005 Number Sequence Time Limit: 2000/1000 MS (Java/O ...

  2. mybatis逆向工程处理text类型字段

    如果数据库中的字段为text或者blob这种大文本类型,在使用MybatisGenerator工具自动生成代码的时候会将其进行特殊处理(一个新的sql片段),结果会导致无法对该字段的值进行操作. 修改 ...

  3. linux下安装php扩展amqp

    1 安装扩展必要依赖 rabbitmq-c 安装包地址:https://github.com/alanxz/rabbitmq-c/releases wget -c https://github.com ...

  4. 深入理解Java虚拟机(一) 运行时数据区划分

    前言:从我学Java的第一天开始,我的大学老师就告诉我 Java语言相比C.C++的语言有一个非常强大的功能,那就是自动内存管理:我们用Java编码时不需要申请或释放内存等,这些工作全部交由我们的Ja ...

  5. C++编译器是如何管理类和对象的,类的成员函数和成员变量

    C++中的class从面向对象理论出发,将变量(属性)和函数(方法)集中定义在一起,用于描述现实世界中的类.从计算机的角度,程序依然由数据段(栈区内存)和代码段(代码区内存)构成. #include ...

  6. 在Java中发送http的post请求,设置请求参数等等

    前几天做了一个定时导入数据的接口,需要发送http请求,第一次做这种的需求,特地记一下子, 导包 import java.text.SimpleDateFormat;import java.util. ...

  7. easyui图标

    只要在icons属性上,加上图标对应的名字,easyUI就会显示对应的图标,这些图标都是easyui内置的.

  8. IntelliJ IDEA(2018)安装和破解。

    一.下载并安装, IntelliJ IDEA的官网:https://www.jetbrains.com           二.破解. 百度下载一个 JetbrainsCrack-2.6.2.jar ...

  9. helloworld模块

    环境: HelperA64开发板 Linux3.10内核 时间:2019.01.11 目标:编译helloword模块 ​ 1.当出先下面错误时候,查找问题 ​ 问题为Make的时候默认为PC-X86 ...

  10. 【Mac】安装 Homebrew 出错 Failed during: git fetch origin master:refs/remotes/origin/master --tags --force

    今天在 Mac 装 Homebrew 遇到了一个问题,在网上找了大量解决方案,做个总结. Mac 版本 High Sierra 10.13.6. 问题描述 在 Mac 终端输入了 Homebrew 官 ...