c语言队列优先级排序,C语言实现的优先级队列

昨日看了算法导论里讲解的堆排序和优先级队列,于是用C语言写了一个优先级队列的简单实现,该实现的最大特点是队列的元素类型是不确定的,可以对任意数据类型进行操作(甚至是自定义的结构体)。这种处理的核心思想是:队列元素的比较操作与赋值操作都由调用者实现并在优先级队列结构体初始化时传给结构体。具体代码如下:

//PriorityQueue.h

/*

* PriorityQueue.h

* The interface of PriorityQueue, support some basic operations of priority

* queue such as insert, maximum, extract_max and so on. And the priority

* queue element is not specifical, user can pass any type of element to it

* if the element's compare and copy function are implemented.

* wl861213@gmail.com

*/

#ifndef _PRIORITYQUEUE_H

#define _PRIORITYQUEUE_H

#define PQ_CAP100/* the initialize capability of the proioity queue. */

#define PQ_CAP_INC50/* the increment of the proioity queue occur

when the capability will be overflow. */

/* error numbers */

#define PQ_NOR_ERR-1

#define PQ_MEM_ERR1

#define PQ_UNDERFLOW_ERR2

/* compare fuction, if a > b, return 1, else return 0 */

typedef int (*compare_func) (void *a, void *b);

/* copy function, copy pq element *b to *a, if success, return 0, else return error number. */

typedef int (*copy_func) (void *a, void *b);

typedef struct priqueue_t

{

unsigned char *pbytes;

intlength;

int capability;

int elemsize; /* pq element size */

compare_func compare; /* compare function for pq element */

copy_funccopy; /* copy function for pq element */

void*compare_minimum; /* the minimum element for the compare element */

}priqueue;

/* initialize function, compare and copy function must be define first and passed to it */

int pq_init(priqueue *pq, compare_func compare, copy_func copy, void *compare_minimum, int elemsize);

int pq_insert(priqueue *pq, void *newelement);

int pq_maximum(priqueue *pq, void *max);

int pq_extract_max(priqueue *pq, void *max);

/* increase the key of index i to newkey */

int pq_increase_key(priqueue *pq, int i, void *newkey);

int pq_destroy(priqueue *pq);

#endif /* _PRIORITYQUEUE_H */

//PriorityQueue.c

#include

#include "PriorityQueue.h"

/*

* The follow tow macro were defined to index the element in priority queue.

* pbytes is the pointer to data area, which always be pq->pbytes.

* i is the index number.

* size is the priority queue elemnt size.

*/

#define INDEX_SIZE(size)((size)/sizeof(unsigned char))

#define INDEX(pbytes, i, size) ((pbytes)+(i)*INDEX_SIZE(size))

/* The follow three macros are used to traverse in binary heap */

#define left(i)((i+1<<1)-1)

#define right(i)(i+1<<1)

#define parent(i) (i-1>>1)

int pq_init(priqueue *pq, compare_func compare, copy_func copy, void *compare_minimum, int elemsize)

{

int ret;

pq->length = 0;

pq->capability = PQ_CAP;

pq->elemsize = elemsize;

pq->compare = compare;

pq->copy = copy;

if ((pq->compare_minimum = (unsigned char *) malloc(pq->elemsize)) == NULL)

return PQ_MEM_ERR;

if ((ret = (*pq->copy) (pq->compare_minimum, compare_minimum)) != 0)

return ret;

if ((pq->pbytes = (unsigned char *) malloc(pq->capability * pq->elemsize)) == NULL)

return PQ_MEM_ERR;

return 0;

}

int pq_insert(priqueue *pq, void *newelement)

{

int ret;

if (++pq->length == pq->capability)

{

pq->capability += PQ_CAP_INC;

if ((pq->pbytes =(unsigned char *) realloc(pq->pbytes, pq->capability * pq->elemsize)) == NULL)

return PQ_MEM_ERR;

}

if ((ret = (*pq->copy) (INDEX(pq->pbytes, pq->length-1, pq->elemsize), pq->compare_minimum)) != 0)

return ret;

pq_increase_key(pq, pq->length-1, newelement);

return 0;

}

int pq_maximum(priqueue *pq, void *max)

{

int ret;

if ((ret = (*pq->copy) (max, pq->pbytes)) != 0)

return ret;

return 0;

}

int pq_extract_max(priqueue *pq, void *max)

{

int ret, l, r, i=0, largest = 0;

void *tmp = malloc(pq->elemsize);

if (pq->length < 1)

return PQ_UNDERFLOW_ERR;

if ((ret = (*pq->copy)(max, pq->pbytes)) != 0)

goto copy_err;

if ((ret = (*pq->copy) (pq->pbytes, INDEX(pq->pbytes, pq->length-1, pq->elemsize))) != 0)

goto copy_err;

pq->length--;

//max_heapify(pq, 0)

l = left(i);

r = right(i);

if (l < pq->length && (*pq->compare) (INDEX(pq->pbytes, l, pq->elemsize), INDEX(pq->pbytes, i, pq->elemsize)))

largest = l;

else

largest = i;

if (r < pq->length && (*pq->compare) (INDEX(pq->pbytes, r, pq->elemsize), INDEX(pq->pbytes, largest, pq->elemsize)))

largest = r;

while(largest != i)

{

if ((ret = (*pq->copy) (tmp, INDEX(pq->pbytes, i, pq->elemsize))) != 0)

goto copy_err;

if ((ret = (*pq->copy) (INDEX(pq->pbytes, i, pq->elemsize), INDEX(pq->pbytes, largest, pq->elemsize))) != 0)

goto copy_err;

if ((ret = (*pq->copy) (INDEX(pq->pbytes, largest, pq->elemsize), tmp)) != 0)

goto copy_err;

i = largest;

l = left(i);

r = right(i);

if (l < pq->length && (*pq->compare) (INDEX(pq->pbytes, l, pq->elemsize), INDEX(pq->pbytes, i, pq->elemsize)))

largest = l;

else

largest = i;

if (r < pq->length && (*pq->compare) (INDEX(pq->pbytes, r, pq->elemsize), INDEX(pq->pbytes, largest, pq->elemsize)))

largest = r;

}

free(tmp);

return 0;

copy_err:

free(tmp);

return ret;

}

int pq_increase_key(priqueue *pq, int i, void *newkey)

{

int ret;

void *tmp = malloc(pq->elemsize);

if ((*pq->compare) (INDEX(pq->pbytes, i, pq->elemsize), newkey))

return PQ_NOR_ERR;

if ((ret = (*pq->copy) (INDEX(pq->pbytes, i, pq->elemsize), newkey)) != 0)

goto copy_err;

while (i > 0 && (*pq->compare)(INDEX(pq->pbytes, i, pq->elemsize), INDEX(pq->pbytes, parent(i), pq->elemsize)))

{

if ((ret = (*pq->copy) (tmp, INDEX(pq->pbytes, i, pq->elemsize))) != 0)

goto copy_err;

if ((ret = (*pq->copy) (INDEX(pq->pbytes, i, pq->elemsize), INDEX(pq->pbytes, parent(i), pq->elemsize))) != 0)

goto copy_err;

if ((ret = (*pq->copy) (INDEX(pq->pbytes, parent(i), pq->elemsize), tmp)) != 0)

goto copy_err;

i = parent(i);

}

free(tmp);

return 0;

copy_err:

free(tmp);

return ret;

}

int pq_destroy(priqueue *pq)

{

free(pq->pbytes);

free(pq->compare_minimum);

return 0;

}

//testpq.c

#include

#include

#include

#include

#include "PriorityQueue.h"

#define ARR_SIZE 10

int compare(void *a, void *b)

{

return *(int *)a > *(int *)b;

}

int copy(void *a, void *b)

{

*(int *)a = *(int *)b;

return 0;

}

int main(void)

{

int a[ARR_SIZE];

int i, tmp, minimum = INT_MIN;

priqueue pq;

pq_init(&pq, &compare, ©, &minimum, sizeof(int));

srand((int) time(0));

for (i = 0; i < ARR_SIZE; i++)

a[i] = rand()%1000;

printf("Befor sort:/n");

for (i = 0; i < ARR_SIZE; i++)

{

printf("%d ", a[i]);

}

printf("/n");

printf("After sort:/n");

for (i = 0; i < ARR_SIZE; i++)

pq_insert(&pq, &a[i]);

for (i = 0; i < ARR_SIZE; i++)

{

pq_extract_max(&pq, &tmp);

printf("%d ", tmp);

}

printf("/n");

pq_destroy(&pq);

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值