介绍
自定义数据类型的优先队列,需要用户自己编写 compare 比较函数用来排序。
代码
priority_queue.h
#ifndef _PRIORITY_QUEUE_H__
#define _PRIORITY_QUEUE_H__
typedef enum{
big_top = 1,
small_top
} select_enum;
typedef void priority_queue_t;
/*
return value:
0 a == b;
>0 a > b;
<0 a < b
*/
typedef int (*compare)(void *key1, void *key2);
priority_queue_t *priority_queue_init(int que_size, compare cmp, select_enum who);
int priority_queue_push(priority_queue_t *que, void *data);
int priority_queue_pop(priority_queue_t *que);
void *priority_queue_top(priority_queue_t *que);
void priority_queue_destroy(priority_queue_t *que);
#endif
qriority_queue.c
#include <stdio.h>
#include <stdlib.h>
#include "./priority_queue.h"
typedef struct priority_queue_st{
void **arr;
int size;
select_enum who;
int capacity;
compare cmp;
}p_que_t;
priority_queue_t *priority_queue_init(int que_size, compare cmp, select_enum who){
p_que_t *que = malloc(sizeof(*que));
if(que == NULL){
return NULL;
}
que->capacity = que_size;
que->cmp = cmp;
que->who = who;
que->arr = malloc(sizeof(*(que->arr)) * que->capacity);
if(que->arr == NULL){
return NULL;
}
que->size = 0;
return que;
}
int priority_queue_push(priority_queue_t *que, void *data){
p_que_t *me = que;
if(me->size >= me->capacity){
return -1;
}
int end = me->size;
int pos_father;
while(end > 0){
pos_father = (end-1) / 2;
if(me->who == big_top){ // big_top
if(me->cmp(me->arr[pos_father], data) >= 0){
break;
}
me->arr[end] = me->arr[pos_father];
end = pos_father;
}else{ // small_top
if(me->cmp(me->arr[pos_father], data) <= 0){
break;
}
me->arr[end] = me->arr[pos_father];
end = pos_father;
}
}
me->arr[end] = data;
me->size++;
return 0;
}
int priority_queue_pop(priority_queue_t *que){
p_que_t *me = que;
int end = me->size;
if(end <= 0){
return -1;
}else if(end == 1){
me->arr[0] = NULL;
me->size--;
return 0;
}
int idx_left, idx_right, idx_cur;
int pos = 0;
void *key = me->arr[end-1];
while(pos*2 + 1 < end){
idx_left = pos * 2 + 1;
idx_right = pos * 2 + 2;
idx_cur = idx_left;
if(me->who == small_top){ // small_top
if (idx_right < end && (me->cmp(me->arr[idx_right], me->arr[idx_cur]) < 0)){
idx_cur = idx_right;
}
if(me->cmp(me->arr[idx_cur], key) >= 0){
break;
}
me->arr[pos] = me->arr[idx_cur];
pos = idx_cur;
}else{ // big_top
if (idx_right < end && (me->cmp(me->arr[idx_right], me->arr[idx_cur]) > 0)){
idx_cur = idx_right;
}
if(me->cmp(me->arr[idx_cur], key) <= 0){
break;
}
me->arr[pos] = me->arr[idx_cur];
pos = idx_cur;
}
}
me->arr[pos] = key;
me->size--;
me->arr[me->size] = NULL;
return 0;
}
void *priority_queue_top(priority_queue_t *que){
p_que_t *me = que;
if(me->size == 0){
return NULL;
}
return me->arr[0];
}
void priority_queue_destroy(priority_queue_t *que){
p_que_t *me = que;
for(int i = 0; i < me->size; i++){
if(me->arr[i] != NULL){
free(me->arr[i]);
}
}
free(me->arr);
free(me);
que = NULL;
return ;
}
test.c
#include <stdio.h>
#include <stdlib.h>
#include "./priority_queue.h"
int my_compare(void *a, void *b){
int *A = a;
int *B = b;
return (*A) - (*B);
}
int main(){
priority_queue_t *que = priority_queue_init(1024, my_compare, big_top);
if(que == NULL){
fprintf(stderr, "qriority_queue_init() false!\n");
exit(1);
}
int *key = NULL;
int i;
for(i = 0; i < 20; i++){
key = malloc(sizeof(*key));
if(key == NULL){
priority_queue_destroy(que);
perror("malloc()");
exit(1);
}
*key = i;
priority_queue_push(que, key);
}
for(i = 0; i < 20; i++){
key = priority_queue_top(que);
printf("key = %d\n", *key);
priority_queue_pop(que);
}
priority_queue_destroy(que);
exit(0);
}
拓展
- 在此基础上可以封装一个定时器,将定时任务保存在优先队列中。