Chinaunix首页 | 论坛 | 博客
  • 博客访问: 493159
  • 博文数量: 41
  • 博客积分: 4007
  • 博客等级: 中校
  • 技术积分: 725
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-30 15:43
文章分类

全部博文(41)

文章存档

2011年(13)

2010年(14)

2009年(2)

2008年(12)

分类: C/C++

2008-03-26 12:33:42

按照《算法导论》中给出的操作来封装的,支持最大优先级和最小优先级队列,大部分添加在了头文件中,包含了各个接口的用法。
data_struct.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "data_struct.h"

/* 封装优先级队列(使用堆结构) */
/******************************/
static inline int LEFT_PQ(int index) //节点下标为index左孩子的下标

{
        return (index << 1) + 1;
}
static inline int RIGHT_PQ(int index) //节点下标为index的右孩子的下标

{
        return (index << 1) + 2;
}
static inline int PARENT_PQ(int index) //节点下标为index的父节点的下标

{
        return (index - 1) / 2;
}
/* 保持堆的性质,此函数实现将某个子树的根节点按照堆的性质下降到某个子孙节点 */
static void HEAPIFY_PQ(PQ *desc, int index)
{
        int left = LEFT_PQ(index);
        int right = RIGHT_PQ(index);
        int largest;
        PQ_element *tmp = NULL;

        for (; left < desc->heap_size || right < desc->heap_size;
                        left = LEFT_PQ(index), right = RIGHT_PQ(index)) {
                if (left < desc->heap_size &&
                                desc->compar(desc->base[left]->data, desc->base[index]->data) > 0)
                        largest = left;
                else largest = index;
                if (right < desc->heap_size &&
                                desc->compar(desc->base[right]->data, desc->base[largest]->data) > 0)
                        largest = right;
                if (largest == index)
                        break;
                tmp = desc->base[index];
                tmp->index = largest;
                desc->base[largest]->index = index;
                desc->base[index] = desc->base[largest];
                desc->base[largest]= tmp;
                index = largest;
        }
}
/* 分配一个节点 */
PQ_element *malloc_PQ(size_t size)
{
        PQ_element *e = NULL;
       
        e = malloc(sizeof(PQ_element));
        if (e == NULL)
                goto end;
        e->data = malloc(size);
        if (e->data == NULL) {
                free(e);
                e = NULL;
        }
        e->index = -1;
end:
        return e;
}

void free_PQ(PQ_element *ptr)
{
        PQ_element *e = (PQ_element *)ptr;
        if (!e)
                return;
        if (!(e->data)) {
                free(e);
                return;
        }
        free(e->data);
        free(e);
}

PQ *create_PQ(int nmemb, compar_t compar, change_key_t change_key)
{
        PQ *ret = NULL;
        PQ_element *t = NULL;

        ret = (PQ *)malloc(sizeof(PQ));
        if (ret == NULL) {
                goto end;
        }
        ret->compar = compar;
        ret->change_key = change_key;
        ret->heap_size = 0;
        ret->len = nmemb;
        t = malloc(sizeof(PQ_element *) * nmemb);
        if (t == NULL) {
                free(ret);
                ret = NULL;
                goto end;
        }
        memset(t, 0, sizeof(PQ_element *) * nmemb);
        ret->base = (PQ_element **)t;
end:
        return ret;
}

void destroy_PQ(PQ *desc)
{
        if (!desc)
                return;
        if (desc->base)
                free(desc->base);
        free(desc);
}

int insert_PQ(PQ *desc, PQ_element *x)
{
        PQ_element *tmp = NULL;
        int ret = -1, i;

        if (desc->heap_size >= desc->len) {
                tmp = realloc(desc->base, sizeof(PQ_element *) * (desc->len + 5));
                if (tmp == NULL) {
                        goto end;
                }
                memset(&tmp[desc->len], 0, sizeof(PQ_element *) * 5);
                desc->base = (PQ_element **)tmp;
                desc->len += 5;
        }
        x->index = desc->heap_size;
        desc->base[desc->heap_size] = x;
        desc->heap_size++;
        i = x->index;
        while (i > 0 && desc->compar(desc->base[PARENT_PQ(i)]->data, desc->base[i]->data) < 0) {
                tmp = desc->base[i];
                tmp->index = PARENT_PQ(i);
                desc->base[PARENT_PQ(i)]->index = i;
                desc->base[i] = desc->base[PARENT_PQ(i)];
                desc->base[PARENT_PQ(i)] = tmp;
                i = PARENT_PQ(i);
        }
        ret = 0;
end:
        return ret;
}

int delete_PQ(PQ *desc, const PQ_element *x)
{
        int i = x->index;

        desc->base[i] = desc->base[desc->heap_size - 1];
        desc->base[desc->heap_size - 1] = NULL;
        desc->base[i]->index = i;
        desc->heap_size--;
        HEAPIFY_PQ(desc, i);
        return 0;
}

PQ_element *root_PQ(PQ *desc)
{
        if (desc && desc->base)
                return desc->base[0];
        return NULL;
}

PQ_element *extract_PQ(PQ *desc)
{
        if (!desc || !(desc->base))
                return NULL;
        if (desc->heap_size <= 0)
                return NULL;
        PQ_element *max = desc->base[0];
        desc->base[0] = desc->base[desc->heap_size - 1];
        desc->base[desc->heap_size - 1] = NULL;
        if (desc->base[0])
                desc->base[0]->index = 0;
        desc->heap_size--;
        HEAPIFY_PQ(desc, 0);
        return max;
}

void change_key_PQ(PQ *desc, PQ_element *x, const void *key)
{
        int i = x->index;
        PQ_element *tmp = NULL;

        desc->change_key(x->data, key);
        while (i > 0 && desc->compar(desc->base[PARENT_PQ(i)]->data, desc->base[i]->data) < 0) {
                tmp = desc->base[i];
                tmp->index = PARENT_PQ(i);
                desc->base[PARENT_PQ(i)]->index = i;
                desc->base[i] = desc->base[PARENT_PQ(i)];
                desc->base[PARENT_PQ(i)] = tmp;
                i = PARENT_PQ(i);
        }
}
/******************************/


data_struct.h

#ifndef DATA_STRUCT___H
#define DATA_STRUCT___H

/* 用户自定义比较函数 */
typedef int (*compar_t)(const void *, const void *);
/* 用户自定义修改关键字函数,
* 前者参数为用户自定义数据结构,
* 后者参数为要修改的key值
*/

typedef void (*change_key_t)(void *, const void *);

/* 队列元素结构 */
typedef struct pq_element
{
        void *data;
        int index; //用于记录该节点所位于数组中的下标值

}PQ_element;

typedef struct PQ_desc
{
        compar_t compar;
        change_key_t change_key;
        int heap_size; /* 堆的大小 */
        int len; /* 当前优先级队列数组中可容纳的最大长度 */
        PQ_element **base;
}PQ;

/* 创建优先级队列,nmemb为队列中包含元素的个数,compar为比较函数,change_key为修改关键字函数 */
PQ *create_PQ(int nmemb, compar_t compar, change_key_t change_key);
void destroy_PQ(PQ *desc); //销毁优先级队列

int insert_PQ(PQ *desc, PQ_element *x); //向队列中插入一个元素,元素为前面定义的元素结构

int delete_PQ(PQ *desc, const PQ_element *x); //删除队列中的一个元素,该元素由x引用

PQ_element *root_PQ(PQ *desc); //得到优先级队列的对头元素

PQ_element *extract_PQ(PQ *desc); //得到优先级队列的对头元素并将对头元素从优先级队列中删除

/*
* 将key指向的用户结构赋值给x指向的用户结构,并改变x在队列中的位置
* 这里将调用用户自定义的change_key函数,
* 并将key和x做为change_key函数的参数传递
*/

void change_key_PQ(PQ *desc, PQ_element *x, const void *key); //将优先级队列desc中的元素x中的关键字修改为key

PQ_element *malloc_PQ(size_t size); //申请节点空间

void free_PQ(PQ_element *ptr); //释放由malloc_PQ申请的节点空间.


#define ELEMENT_DATA(pq_element) ((pq_element)->data) //返回节点元素中用户自定义数据结构的指针

#define CLEAN_ELEMENT(pq_element) ((pq_element)->data = NULL) //将节点元素中的用户数据指针清除

#define INDEX_ELEMENT(pq_element) ((pq_element)->index) //返回节点元素在堆中的索引值

#define PQ_SIZE(desc) ((desc)->heap_size) //优先级队列中队列的长度

#define PQ_LEN(desc) ((desc)->len) //目前能容纳的元素的最大个数


#endif

阅读(2024) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~