【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;
}

全文完。

时间: 2024-08-11 09:57:52

【C语言】zz优先队列的实现的相关文章

优先队列C语言实现

优先队列利用堆实现,堆的实现在前面已经说过了,优先队列的一个重要的操作是: 1.  heap_max  O(1) 2. heap_extract_max  O(lgn) 3. heap_increase_key  O(lgn) 4, heap_insert  O(lgn) 下面是C语言实现 #define MIN -100000 int heap_max(struct heap *h) { return h->arr[1]; } int heap_extract_max(struct heap

【ZZ】C 语言中的指针和内存泄漏 &amp; 编写高效的C程序与C代码优化

C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 编写高效的C程序与C代码优化 http://www.cnblogs.com/archimedes/p/writing-efficient-c-and-code-optimization.html

深入浅出数据结构C语言版(15)——优先队列(堆)

在普通队列中,元素出队的顺序是由元素入队时间决定的,也就是谁先入队,谁先出队.但是有时候我们希望有这样的一个队列:谁先入队不重要,重要的是谁的"优先级高",优先级越高越先出队.这样的数据结构我们称之为优先队列(priority queue),其常用于一些特殊应用,比如操作系统控制进程的调度程序. 那么,优先队列该如何实现呢?我们可以很快给出三种解决方案. 1.使用链表,插入操作选择直接插入到表头,时间复杂度为O(1),出队操作则遍历整个表,找到优先级最高者,返回并删除该结点,时间复杂度

优先队列(堆) -数据结构(C语言实现)

数据结构与算法分析 优先队列 模型 Insert(插入) == Enqueue(入队) DeleteMin(删除最小者) == Dequeue(出队) 基本实现 简单链表:在表头插入,并遍历该链表以删除最小元 时间代价昂贵 二叉查找树 二叉查找树支持许多不需要的操作,实现麻烦,不值得 最合适:二叉堆 二叉堆 堆的两种性质 结构性 完全二叉树:除底层外完全填满,底层也是从左至右填 完全二叉树的高为 log N 分布很有规律可以用数组实现 左儿子 = 2i 右儿子 = 2i + 1 堆序性 树的最小

c语言优先队列的实现

优先队列即二叉堆,实现如下: #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> typedef int Element; #define MAX_BINHEAP_LENGTH 10 struct BinaryHeap { Element array[MAX_BINHEAP_LENGTH]; int length; }; int compare(const

战胜C语言中令人头疼的问题

C语言一共32个关键字,下面一一列出:   1.auto声明自动变量 在默认情况下,编译器默认所有变量都是auto 2.int声明整型变量 3.double声明双精度变量 4.long声明长整型变量 5.char声明字符型变量 6.float声明浮点型变量 7.short声明短整型变量 8.signed声明有符号类型变量 9.unsigned声明无符号类型变量 最高位如果是1,表明这个数是负数,其值为除最高位以外的剩余位的值添上这个“-”号: 如果最高位是0,表明这个数是正数,其值为除最高位以外

GO语言总结(2)——数值类型

上篇博文总结了Go语言的基础知识——GO语言总结(1)——基本知识  ,本篇 一.整型 go语言有13种整形,其中有2种只是名字不同,实质是一样的,所以,实质上go语言有11种整形.如下: (1)int : 依赖不同平台下的实现,可以是int32或int64 (2)int8 :  (-128 -> 127) (3)int16:  (-32768 -> 32767) (4)int32:  (-2 147 483 648 -> 2 147 483 647) (5)int64 : (-9 22

fcitx五笔的安装[zz]

Fcitx──小企鹅输入法:Free Chinese Input Toy for X是国产软件的精品,是一个以GPL方式发布的.基于XIM的简体中文输入法集合(原为G五笔),包括五笔.五笔拼音.二笔.仓颉.晚风.冰蟾全息.拼音(全拼和双拼).区位以及码表输入模块. 1.删除旧版或其它输入法(也可跳过此步)Ubuntu10.10 默认是安装了ibus.所以删除它(实际上,不用删除 ibus,在语言支持中切换一下输入法就好了)sudo apt-get remove ibus对于已经安装老版 的fci

GLSL语言基础(转)

转自:https://my.oschina.net/sweetdark/blog/208024 变量 GLSL的变量命名方式与C语言类似.变量的名称可以使用字母,数字以及下划线,但变量名不能以数字开头,还有变量名不能以gl_作为前缀,这个是GLSL保留的前缀,用于GLSL的内部变量.当然还有一些GLSL保留的名称是不能够作为变量的名称的. 基本类型 除了布尔型,整型,浮点型基本类型外,GLSL还引入了一些在着色器中经常用到的类型作为基本类型.这些基本类型都可以作为结构体内部的类型.如下表: 类型