数据结构【三】:简单优先队列PriorityQueue
在数据结构【二】:简单阻塞队列BlockingQueue的基础上添加权限属性:priority,并控制enqueue时根据priority排序插入.
1.定义priority取值范围0~9
2.dequeue取出priority值最大的节点(最高进先出 largest-in,first-out ).
3.若priority相等,则继续遵循FIFO原则
注意 : 此代码未经生产环境检验,仅供学习参考.
PriorityQueue.h
#ifndef CUR_PRIORITYQUEUE_H
#define CUR_PRIORITYQUEUE_H
#include <stdlib.h>
#include <pthread.h> struct node{
int value;
int priority; //优先级,取值范围0~9
struct node * next;
}; typedef struct PriorityQueue_ST{
int capacity,remaining,closed;
struct node * head, *tail;
pthread_mutex_t queue_mutex;
pthread_cond_t cond_not_full;
pthread_cond_t cond_not_empty;
pthread_cond_t cond_empty;
}PriorityQueue; extern PriorityQueue* empty_queue(int _capacity);
extern int queue_free(PriorityQueue *q);
extern int is_empty(const PriorityQueue *q);
extern int is_full(const PriorityQueue *q);
extern int enqueue(struct node *item, PriorityQueue *q);
extern struct node* dequeue(PriorityQueue *q); #endif
PriorityQueue.c
#include "PriorityQueue.h"
#include <stdio.h> PriorityQueue* empty_queue(int _capacity)
{
PriorityQueue *q = malloc(sizeof(PriorityQueue));
q->head = q->tail = NULL;
q->capacity = q->remaining = _capacity;
q->closed = ;
pthread_mutex_init(&q->queue_mutex , NULL);
pthread_cond_init(&q->cond_not_full , NULL);
pthread_cond_init(&q->cond_not_empty , NULL);
pthread_cond_init(&q->cond_empty , NULL);
return q;
} int queue_free(PriorityQueue *q)
{
pthread_mutex_lock(&q->queue_mutex);
printf("close queue...\n");
q->closed = ;
//等待cond_empty
while(!is_empty(q))
{
pthread_cond_wait(&q->cond_empty, &q->queue_mutex);
}
free(q);
pthread_mutex_unlock(&q->queue_mutex);
printf("closed...\n");
} int is_empty(const PriorityQueue *q)
{
return q->capacity == q->remaining;
} int is_full(const PriorityQueue *q)
{
return q->remaining == ;
} int enqueue(struct node *item, PriorityQueue *q)
{ if(q->closed) goto err;
//lock
pthread_mutex_lock(&q->queue_mutex);
//等待cond_not_full
while(is_full(q))
{
pthread_cond_wait(&q->cond_not_full, &q->queue_mutex);
}
//设置最权限:大为9,最小为0,默认为0
item->priority = item->priority > ? : item->priority;
item->priority = item->priority < ? : item->priority; if(is_empty(q))
{
q->head = q->tail = item;
//通知所有等待cond_not_empty的线程
pthread_cond_broadcast(&q->cond_not_empty);
}
else
{
//插入时按优先级排序 : order by priority desc
struct node *big = NULL;
struct node *small = q->head;
while(small != NULL && small->priority >= item->priority)
{
big = small;
small = small->next;
} if(small == NULL)
{
//尾部插入 : big = q->tail
q->tail->next = item;
q->tail = item;
}else if(big == NULL)
{
//头部插入
q->head = item;
item->next = small;
}else
{
//中部插入
big->next = item;
item->next = small;
} }
q->remaining--;
//unlock
pthread_mutex_unlock(&q->queue_mutex); return ;
err :
return -;
} struct node* dequeue(PriorityQueue *q)
{ //已经关闭的空队列
if(q->closed && is_empty(q)) goto err;
//lock
pthread_mutex_lock(&q->queue_mutex);
//空队列,等待cond_not_empty
while(!q->closed && is_empty(q))
{
pthread_cond_wait(&q->cond_not_empty, &q->queue_mutex);
}
//take
struct node * temp = q->head;
q->head = q->head->next; //在未关闭队列的情况下,唤醒enqueue等待线程
if(!q->closed && is_full(q))
{
pthread_cond_broadcast(&q->cond_not_full); //TODO 1
}
q->remaining++;
//唤醒关闭队列线程
if(q->closed && is_empty(q))
{
pthread_cond_signal(&q->cond_empty);//TODO 2
} //注意:TODO 1和TODO 2其实是互斥的,不可能同时满足条件
//必须先判断是否激活cond_not_full然后remaining++
//最后再判断是否激活cond_empty
//unlock
pthread_mutex_unlock(&q->queue_mutex);
return temp;
err:
return NULL;
}
测试代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "PriorityQueue.h"
extern void* func_put(void* _q); PriorityQueue *q;
pthread_t thread1;
void main()
{
q = empty_queue();
pthread_create(&thread1,NULL,func_put,(void*)q);
srand((int) time()); int i;
for(i=; i<=; i++)
{
struct node * item = (struct node *)malloc(sizeof(struct node));
item->value = i;
item->next = NULL;
item->priority = ( + rand() % );
enqueue(item,q);
printf("enqueue -> value : %d, priority : %d, remaining : %d\n",i,item->priority,q->remaining);
sleep();
}
queue_free(q);
} void* func_put(void* _q)
{
PriorityQueue *q = (PriorityQueue*)_q;
struct node *item;
while((item = dequeue(q)) != NULL)
{
printf("dequeue -> value : %d, priority : %d, remaining : %d\n",item->value,item->priority,q->remaining);
free(item);
sleep();
}
}
测试结果:

数据结构【三】:简单优先队列PriorityQueue的更多相关文章
- 【Java源码】集合类-优先队列PriorityQueue
一.类继承关系 public class PriorityQueue<E> extends AbstractQueue<E> implements java.io.Serial ...
- [Swift]实现优先队列PriorityQueue
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Java优先队列PriorityQueue的各种打开方式以及一些你不知道的细节
目录 Java优先队列PriorityQueue的各种打开方式以及一些你不知道的细节 优先队列的默认用法-从小到大排序 对String类用优先队列从大到小排序 通过自定义比较器对自定义的类进行从小到大 ...
- .NET 6 优先队列 PriorityQueue 实现分析
在最近发布的 .NET 6 中,包含了一个新的数据结构,优先队列 PriorityQueue, 实际上这个数据结构在隔壁 Java中已经存在了很多年了, 那优先队列是怎么实现的呢? 让我们来一探究竟吧 ...
- golang实现的简单优先队列
下面是golang实现的简单优先队列,参考信息可以查看https://golang.org/pkg/container/heap/或者https://golang.google.cn/pkg/cont ...
- 堆数据结构(heapq)简单应用
## 堆数据结构(heapq)简单应用 # 堆数据结构 heapq # 常用方法:nlargest(),nsmallest(),heapify(),heappop() # 如果需要的个数较小,使用nl ...
- Java的优先队列PriorityQueue详解
一.优先队列概述 优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序, 可以放基本数据类型的包装类(如:Integer,Long等)或自定义的类 对于基本数据类型的包装器 ...
- 学习javascript数据结构(三)——集合
前言 总括: 本文讲解了数据结构中的[集合]概念,并使用javascript实现了集合. 原文博客地址:学习javascript数据结构(三)--集合 知乎专栏&&简书专题:前端进击者 ...
- JSP学习笔记(三):简单的Tomcat Web服务器
注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...
随机推荐
- USB设备不能用。提示Windows 无法启动这个硬件设备。 (代码 19)
USB,由于其配置信息(注册表中的)不完整或已损坏, Windows 无法启动这个硬件设备. (代码 19) 原因:提示Windows 无法启动这个硬件设备. (代码 19) 处理解决方法: 1) r ...
- iOS面向编码|iOSVideoToolbox:读写解码回调函数CVImageBufferRef的YUV图像
iOS面向编码|iOSVideoToolbox:读写解码回调函数CVImageBufferRef的YUV图像 本文档基于H.264的解码,介绍读写Video Toolbox解码回调函数参数CVImag ...
- ASP.NET MVC 4 中Jquery上传插件Uploadify简单使用-版本:3.2.1
1.官网下载开发包:http://www.uploadify.com/download/,选择免费的Flash版本: 2.解压后,需要用到以下几个文件: 需要修改uploadify.css中取消上传按 ...
- IE6常见bug整理
By Diaoyude | 发布时间: 09-08 09:47 | Hits:1,253 | Post in: WEB前端 , Div-Css 针对IE6常见的一些ie6bug,ie6png,E6 ...
- LVS 单独完成--负载均衡
原文地址:http://blog.sina.com.cn/s/blog_5f54f0be0101eyiu.html LVS 是通过 IPVS 模块来实现的.IPVS是LVS集群的核心,主要用于完成用户 ...
- axTE3DWindowEx双屏对比控件白屏解决方法以及网上方法的校正(CreateControlOveride)
环境:vs2012,TE 6.5.1,winfrom C# 要做skyline的双屏显示功能,网上找到方法是用axTE3DWindowEx控件实现,把控件拖进去,运行,发现axTE3DWindow是正 ...
- 浅析C#基于TCP协议的SCOKET通信
TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP等等,所以要了解网络编程就必须了解基于TCP协议的编程.然而TCP协议是一个庞杂的体系,要彻底的弄清楚它的实 ...
- C++ Code_HotKey
Code::使用HotKeyCtrl定义一个系统热键 // 关联HotKeyCtrl控件变量 m_HotKey1 BEGIN_MESSAGE_MAP(CXyzDlg, CD ...
- 免费LInux主机资源
一.m-net.arbornet.org注冊 (1)telnet m-net.arbornet.org vista系统默认是关闭telnet的(由于不安全),须要开启.cmd->telnet(2 ...
- 仿Android网易新闻客户端,并增加水平图片滑动,改进阅读体验
仿网易新闻Android端APP 主要功能展示和代码实现 差不多花了一周的时间,目前实现的了新闻下的包括头条.体育.娱乐的一系列的新闻展示,以及点击后进入的新闻详情展示. 目前效果 目前效果请访问该网 ...