优先队列C语言

介绍

自定义数据类型的优先队列,需要用户自己编写 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);
}

拓展

  • 在此基础上可以封装一个定时器,将定时任务保存在优先队列中。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言中的优先队列是一种特殊的队列数据结构,其中每个元素都有一个与之关联的优先级。优先级高的元素先被处理,而优先级相同的元素按照它们被插入的顺序进行处理。 在C语言中,可以使用以下几种方式来实现优先队列: 1. 数组实现:使用数组来存储元素,并根据元素的优先级进行排序。插入元素时,需要按照优先级找到合适的位置进行插入;删除元素时,直接删除数组中的第一个元素即可。这种实现方式简单直观,但插入和删除操作的时间复杂度较高。 2. 堆实现:使用堆这种数据结构来实现优先队列。堆是一种完全二叉树,满足堆序性质:对于每个节点i,其父节点的值小于等于节点i的值。在C语言中,可以使用数组来表示堆。插入元素时,将元素插入到堆的末尾,并通过上浮操作将其调整到合适的位置;删除元素时,将堆顶元素与最后一个元素交换,并通过下沉操作将其调整到合适的位置。这种实现方式的插入和删除操作的时间复杂度为O(log n),效率较高。 3. 链表实现:使用链表来存储元素,并根据元素的优先级进行排序。插入元素时,需要按照优先级找到合适的位置进行插入;删除元素时,直接删除链表中的第一个元素即可。这种实现方式相对于数组实现来说,插入和删除操作的时间复杂度较低,但查找操作的时间复杂度较高。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值