【C语言】zz优先队列的实现
做一个题目时,看见解法中使用了优先队列,http://hawstein.com/posts/3.6.html 。
颇为好奇,找资料学习了一下,顺便做个摘要。
c++的用法:
转自:http://blog.chinaunix.net/uid-21712186-id-1818266.html
#include <iostream>
#include <vector>
#include <queue>
#include <stdio.h>
#include <functional>
struct cmp1{
bool operator ()(int &a,int &b){
return a>b;//最小值优先
}
};
struct cmp2{
bool operator ()(int &a,int &b){
return a<b;//最大值优先
}
};
//定义结构,使用运算符重载,自定义优先级2
struct number1{
int x;
bool operator < (const number1 &a) const {
return x>a.x;//最小值优先
}
};
struct number2{
int x;
bool operator < (const number2 &a) const {
return x<a.x;//最大值优先
}
};
int a[]={14,10,56,7,83,22,36,91,3,47,72,0};
number1 num1[]={14,10,56,7,83,22,36,91,3,47,72,0};
number2 num2[]={14,10,56,7,83,22,36,91,3,47,72,0};
int main()
{
std::cout << "hello world" << std::endl;
std::priority_queue<int> que;
std::priority_queue<int, std::vector<int>, cmp1>que1;
std::priority_queue<int, std::vector<int>, cmp2> que2;
std::priority_queue<int, std::vector<int>, std::greater<int> > que3;
std::priority_queue<int, std::vector<int>, std::less<int> > que4;
std::priority_queue<number1> que5;
std::priority_queue<number2> que6;
int i ;
for(i = 0; a[i]; i++)
{
que.push(a[i]);
que1.push(a[i]);
que2.push(a[i]);
que3.push(a[i]);
que4.push(a[i]);
}
for(i=0;num1[i].x;i++)
que5.push(num1[i]);
for(i=0;num2[i].x;i++)
que6.push(num2[i]);
printf("采用默认优先关系:\n(priority_queue<int>que;)\n");
printf("Queue 0:\n");
while(!que.empty()){
printf("%3d",que.top());
que.pop();
}
puts("");
puts("");
printf("采用结构体自定义优先级方式一:\n(priority_queue<int,vector<int>,cmp>que;)\n");
printf("Queue 1:\n");
while(!que1.empty()){
printf("%3d",que1.top());
que1.pop();
}
puts("");
printf("Queue 2:\n");
while(!que2.empty()){
printf("%3d",que2.top());
que2.pop();
}
puts("");
puts("");
printf("采用头文件\"functional\"内定义优先级:\n(priority_queue<int,vector<int>,greater<int>/less<int> >que;)\n");
printf("Queue 3:\n");
while(!que3.empty()){
printf("%3d",que3.top());
que3.pop();
}
puts("");
printf("Queue 4:\n");
while(!que4.empty()){
printf("%3d",que4.top());
que4.pop();
}
puts("");
puts("");
printf("采用结构体自定义优先级方式二:\n(priority_queue<number>que)\n");
printf("Queue 5:\n");
while(!que5.empty()){
printf("%3d",que5.top());
que5.pop();
}
puts("");
printf("Queue 6:\n");
while(!que6.empty()){
printf("%3d",que6.top());
que6.pop();
}
puts("");
system("pause");
return 0;
}
c实现:
转自http://hi.baidu.com/gropefor/blog/item/7d958eb68359cbe230add14e.html
优先队列(priority_queue)和一般队列(queue)的函数接口一致,不同的是,优先队列每次出列的是整个队列中
最小(或者最大)的元素。
本文简要介绍一种基于数组二叉堆实现的优先队列,定义的数据结构和实现的函数接口说明如下:
一、键值对结构体:KeyValue
// =============KeyValue Struct==================================
typedef struct key_value_struct KeyValue;
struct key_value_struct
{
int _key;
void *_value;
};
KeyValue *key_value_new(int key, void *value);
void key_value_free(KeyValue *kv, void (*freevalue)(void *));
键值对作为优先队列的中数据的保存形式,其中key用于保存优先级,_value用于指向实际的数据。
key_value_new用于创建一个KeyValue结构体;key_value_free用于释放一个KeyValue结构体的内存,
参数freevalue用于释放数据指针_value指向的内存。
二、优先队列结构体:PriorityQueue
// =============PriorityQueue Struct==============================
#define PRIORITY_MAX 1
#define PRIORITY_MIN 2
typedef struct priority_queue_struct PriorityQueue;
struct priority_queue_struct
{
KeyValue **_nodes;
int _size;
int _capacity;
int _priority;
};
PriorityQueue *priority_queue_new(int priority);
void priority_queue_free(PriorityQueue *pq, void (*freevalue)(void *));
const KeyValue *priority_queue_top(PriorityQueue *pq);
KeyValue *priority_queue_dequeue(PriorityQueue *pq);
void priority_queue_enqueue(PriorityQueue *pq, KeyValue *kv);
int priority_queue_size(PriorityQueue *pq);
int priority_queue_empty(PriorityQueue *pq);
void priority_queue_print(PriorityQueue *pq);
1) 其中nodes字段是二叉堆数组,_capacity是nodes指向的KeyValue*指针的个数,_size是nodes中实际存储的元素个数。
_priority可以是PRIORITY_MAX或PRIORITY_MIN,分别表示最大元素优先和最小元素优先。
2) priority_queue_new和priority_queue_free分别用于创建和释放优先队列。
3) priority_queue_top用于取得队列头部元素,
4)priority_queue_dequeue用于取得队列头部元素并将元素出列。
其实现的基本思路,以最大优先队列说明如下:
①将队列首部nodes[0]保存作为返回值
②将队列尾部nodes[_size-1]置于nodes[0]位置,并令_size=_size-1
③令当前父节点parent(nodes[i])等于新的队列首部(i=0)元素,
parent指向元素的儿子节点为left = nodes[2 * i + 1]和rigth = nodes[2 * i + 2],
比较left和right得到优先级高的儿子节点,设为nodes[j](j = 2 *i + 1或2 *i + 2),
④如果当前父节点parent的优先级高于nodes[j],交换nodes[i]和nodes[j],并更新当前父节点,
即令i=j,并循环 ③;
如果当前父节点的优先级低于nodes[j],处理结束。
5)priority_queue_enqueue用于将KeyValue入列
其实现的基本思路,以最大优先队列说明如下:
①设置nodes[_size] 为新的KeyValue,并令_size++
②令当前儿子节点child(nodes[i])为新的队列尾部节点(i=_size-1),child的父节点parent为nodes[j],
其中j= (i - 1) / 2
③如果当前儿子节点child的优先级高于parent, 交换nodes[i]和nodes[j],并更新当前儿子节点
即令i = j,并循环③;
如果当前儿子节点的优先级低于parent,处理结束。
6) priority_queue_size用于取得队列中元素个数,priority_queue_empty用于判断队列是否为空。
7)priority_queue_print用于输出队列中的内容。
文件pq.h给出了数据结构和函数的声明,文件pq.c给出了具体实现,main.c文件用于测试。虽然是使用
过程化编程的C语言,可以看到具体的编码中应用了基于对象的思想,我们对数据结构和相关函数做了一定程度的
聚集和封装。
/*
*File: pq.h
*purpose: declaration of priority queue in C
*Author:puresky
*Date:2011/04/27
*/
#ifndef _PRIORITY_QUEUE_H
#define _PRIORITY_QUEUE_H
// =============KeyValue Struct==================================
typedef struct key_value_struct KeyValue;
struct key_value_struct
{
int _key;
void *_value;
};
KeyValue *key_value_new(int key, void *value);
void key_value_free(KeyValue *kv, void (*freevalue)(void *));
// =============PriorityQueue Struct==============================
#define PRIORITY_MAX 1
#define PRIORITY_MIN 2
typedef struct priority_queue_struct PriorityQueue;
struct priority_queue_struct
{
KeyValue **_nodes;
int _size;
int _capacity;
int _priority;
};
PriorityQueue *priority_queue_new(int priority);
void priority_queue_free(PriorityQueue *pq, void (*freevalue)(void *));
const KeyValue *priority_queue_top(PriorityQueue *pq);
KeyValue *priority_queue_dequeue(PriorityQueue *pq);
void priority_queue_enqueue(PriorityQueue *pq, KeyValue *kv);
int priority_queue_size(PriorityQueue *pq);
int priority_queue_empty(PriorityQueue *pq);
void priority_queue_print(PriorityQueue *pq);
#endif
/*
*File:pq.c
*purpose: definition of priority queue in C
*Author:puresky
*Date:2011/04/27
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pq.h"
//Private Functions
static void priority_queue_realloc(PriorityQueue *pq);
static void priority_queue_adjust_head(PriorityQueue *pq);
static void priority_queue_adjust_tail(PriorityQueue *pq);
static int priority_queue_compare(PriorityQueue *pq,
int pos1,
int pos2);
static void priority_queue_swap(KeyValue **nodes,
int pos1,
int pos2);
//Functions of KeyValue Struct
KeyValue *key_value_new(int key,
void *value)
{
KeyValue *pkv = (KeyValue *)malloc(sizeof(KeyValue));
pkv->_key = key;
pkv->_value = value;
return pkv;
}
void key_value_free(KeyValue *kv,
void (*freevalue)(void *))
{
if(kv)
{
if(freevalue)
{
freevalue(kv->_value);
}
free(kv);
}
}
//Functions of PriorityQueue Struct
PriorityQueue *priority_queue_new(int priority)
{
PriorityQueue *pq = (PriorityQueue *)malloc(sizeof(PriorityQueue));
pq->_capacity = 11; //default initial value
pq->_size = 0;
pq->_priority = priority;
pq->_nodes = (KeyValue **)malloc(sizeof(KeyValue *) * pq->_capacity);
return pq;
}
void priority_queue_free(PriorityQueue *pq,
void (*freevalue)(void *))
{
int i;
if(pq)
{
for(i = 0; i < pq->_size; ++i)
key_value_free(pq->_nodes[i], freevalue);
free(pq->_nodes);
free(pq);
}
}
const KeyValue *priority_queue_top(PriorityQueue *pq)
{
if(pq->_size > 0)
return pq->_nodes[0];
return NULL;
}
KeyValue *priority_queue_dequeue(PriorityQueue *pq)
{
KeyValue *pkv = NULL;
if(pq->_size > 0)
{
pkv = pq->_nodes[0];
priority_queue_adjust_head(pq);
}
return pkv;
}
void priority_queue_enqueue(PriorityQueue *pq,
KeyValue *kv)
{
printf("add key:%d\n", kv->_key);
pq->_nodes[pq->_size] = kv;
priority_queue_adjust_tail(pq);
if(pq->_size >= pq->_capacity)
priority_queue_realloc(pq);
}
int priority_queue_size(PriorityQueue *pq)
{
return pq->_size;
}
int priority_queue_empty(PriorityQueue *pq)
{
return pq->_size <= 0;
}
void priority_queue_print(PriorityQueue *pq)
{
int i;
KeyValue *kv;
printf("data in the pq->_nodes\n");
for(i = 0; i < pq->_size; ++i)
printf("%d ", pq->_nodes[i]->_key);
printf("\n");
printf("dequeue all data\n");
while(!priority_queue_empty(pq))
{
kv = priority_queue_dequeue(pq);
printf("%d ", kv->_key);
}
printf("\n");
}
static void priority_queue_realloc(PriorityQueue *pq)
{
pq->_capacity = pq->_capacity * 2;
pq->_nodes = realloc(pq->_nodes, sizeof(KeyValue *) * pq->_capacity);
}
static void priority_queue_adjust_head(PriorityQueue *pq)
{
int i, j, parent, left, right;
i = 0, j = 0;
parent = left = right = 0;
priority_queue_swap(pq->_nodes, 0, pq->_size - 1);
pq->_size--;
while(i < (pq->_size - 1) / 2)
{
parent = i;
left = i * 2 + 1;
right = left + 1;
j = left;
if(priority_queue_compare(pq, left, right) > 0)
j++;
if(priority_queue_compare(pq, parent, j) > 0)
{
priority_queue_swap(pq->_nodes, i, j);
i = j;
}
else
break;
}
}
static void priority_queue_adjust_tail(PriorityQueue *pq)
{
int i, parent, child;
i = pq->_size - 1;
pq->_size++;
while(i > 0)
{
child = i;
parent = (child - 1) / 2;
if(priority_queue_compare(pq, parent, child) > 0)
{
priority_queue_swap(pq->_nodes, child, parent);
i = parent;
}
else
break;
}
}
static int priority_queue_compare(PriorityQueue *pq,
int pos1,
int pos2)
{
int adjust = -1;
int r = pq->_nodes[pos1]->_key - pq->_nodes[pos2]->_key;
if(pq->_priority == PRIORITY_MAX)
r *= adjust;
return r;
}
static void priority_queue_swap(KeyValue **nodes,
int pos1,
int pos2)
{
KeyValue *temp = nodes[pos1];
nodes[pos1] = nodes[pos2];
nodes[pos2] = temp;
}
/*
*File: main.c
*purpose: tesing priority queue in C
*Author:puresky
*Date:2011/04/27
*/
#include <stdio.h>
#include <stdlib.h>
#include "pq.h"
int main(int argc, char **argv)
{
int i;
PriorityQueue *pq = priority_queue_new(PRIORITY_MAX);
int a[]={1, 9, 7, 8, 5, 4, 3, 2, 1, 100, 50, 17};
for(i = 0; i < sizeof(a)/ sizeof(int); ++i)
{
KeyValue *kv = key_value_new(a[i], NULL);
priority_queue_enqueue(pq, kv);
}
priority_queue_print(pq);
priority_queue_free(pq, NULL);
system("pause");
return 0;
}
全文完。
【C语言】zz优先队列的实现的更多相关文章
- [zz]如何在C语言程序中处理汉字
学习过C语言的人也许有时会遇到这样一个问题:如何用变量存储汉字以及对这些变量进行操作.目前许多C语言参考书中都没涉及到这个问题,程序中多为处理英文变量和英文字符串,涉及到汉字的情况也大都是在print ...
- 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化
C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...
- 深入浅出数据结构C语言版(15)——优先队列(堆)
在普通队列中,元素出队的顺序是由元素入队时间决定的,也就是谁先入队,谁先出队.但是有时候我们希望有这样的一个队列:谁先入队不重要,重要的是谁的"优先级高",优先级越高越先出队.这样 ...
- R语言-编写自定义函数 ZZ
一.函数构造器 每一个R函数都包括三个部分:函数名,程序主体以及参数集合,在编写自定义R函数时,需要将三个部分各自储存在一个R对象中.这里需要使用function函数,形如: my_function& ...
- 【ZZ】堆和堆的应用:堆排序和优先队列
堆和堆的应用:堆排序和优先队列 https://mp.weixin.qq.com/s/dM8IHEN95IvzQaUKH5zVXw 堆和堆的应用:堆排序和优先队列 2018-02-27 算法与数据结构 ...
- Java语言:JAVA8 十大新特性详解(zz)
关键词: Lambda表达式.函数式接口.方法与构造函数引用.接口的默认方法 原文地址: http://www.jb51.net/article/48304.htm 本教程将Java8的新特新逐一列出 ...
- 【ZZ】各类程序开发语言概述 | 菜鸟教程
http://www.runoob.com/w3cnote/programming-intro.html 各类程序开发语言概述, 点击查看大图:
- 优先队列(堆) -数据结构(C语言实现)
数据结构与算法分析 优先队列 模型 Insert(插入) == Enqueue(入队) DeleteMin(删除最小者) == Dequeue(出队) 基本实现 简单链表:在表头插入,并遍历该链表以删 ...
- 利用日期、经纬度求日出日落时间 C语言程序代码(zz)
先贴在这了,后面应该用得着 http://zhidao.baidu.com/link?url=iw-hcd_tLpRtf4r2Kh-NmDPaQ10UdlunBQUWaz14J-eNEq5fw-y83 ...
随机推荐
- spring-mvc.xml报错cvc-complex-type.2.4.c
添加 <!-- 定义请求处理映射HandlerMapping --> <bean id = "handlerMapping" class = "org. ...
- jQuery实现左移右移
<html> <head> <meta charset="utf-8"> <title>完成左移右移</title> & ...
- java生成竖排文字图片
package com.kadang.designer.web.action;import java.awt.Color;import java.awt.Font;import java.awt.Fo ...
- INFO - InstallShield中的InstallScript工程Setup.exe /s的使用细节
在InstallShield的各种工程类型中,Basic MSI工程Build出的安装包基于Windows Installer标准,所以默认就支持静默安装(至于如何静默安装,请自行补充相关知识).而对 ...
- Windows Server 2008 R2 备份和恢复 (转)
Windows Server Backup : 1.安装Windows Server Backup的方法: 通过"服务器管理器"中的"添加功能"向导进行安装. ...
- Search-ADaccount
查询被锁定用户 Search-ADAccount -LockedOut | FT Name,ObjectClass -A Search-ADAccount Search-ADAccount Gets ...
- Java和Android文件操作
File这是文件基类,抽象地代表一个文件实体,它有四个不同的构造方法: File(File dir, String name) File(String path) File(String dir ...
- VS2012中数据库架构的比较
在进行项目进行开发或维护时,经常会改动使用的数据库,或增加.修改字段,或加表,改存储过程等,而且会出现多个类似的数据库同时在用(比如过个类似的项目,要使用稍有不同的数据库),这个时候就可能需要进行数据 ...
- 转:TinyXM--优秀的C++ XML解析器
读取和设置xml配置文件是最常用的操作,试用了几个C++的XML解析器,个人感觉TinyXML是使用起来最舒服的,因为它的API接口和Java的十分类似,面向对象性很好. TinyXML是一个开源的解 ...
- Oracle中Kill session的研究(转 出自eagle)
itpub link: http://www.itpub.net/235873.html 我们知道,在Oracle数据库中,可以通过kill session的方式来终止一个进程,其基本语法结构为: a ...