优先队列——C语言实现、python实现

9 篇文章 0 订阅
5 篇文章 0 订阅

优先队列

采用二叉堆实现,因其为完全二叉树结构,故堆中的节点可以用数组来存储,访问也可以使用数组下标而代替指针;
优先队列的插入和删除操作的最坏时间复杂度均为O(logN),而其队列中的最小值(或最大值)总是处于队列
前端,如果一直删除队列中的最小元素知道队列空,即可得到一个排序的数组,故优先队列用于排序的时间复杂度为O(NlogN)

C语言实现:
将数组的第一个元素利用来保存来保存当前队列中的元素个数,这样i, 2i 和2i+1即分别表示父节点下标、左子节点下标和右子节点下标:
而根据堆序性,处于父节点的元素 总是大于其两个子节点(最大堆)或者 总小于其两个子节点(最小堆),下面实现的最小堆,故最小的元素
总处于堆顶,而插入和删除操作也均是根据堆序性去调整堆中数据。
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>

typedef struct pri_queue_type pri_queue_t;

pri_queue_t *initialize(int capacity);
void destroy(pri_queue_t *priq);
int is_empty(pri_queue_t *priq);
int is_full(pri_queue_t *priq);
void insert(pri_queue_t *priq, int x);
int get_min(pri_queue_t *priq);
void delete_min(pri_queue_t *priq);

struct pri_queue_type {
    int capacity;
    int *elems;/*数组第一个元素来表示队列中当前元素个数*/
};

#define PARENT(i) ((i)>>1)//下标为i的节点的父节点下标i/2
#define LCHILD(i) ((i)<<1)//下标为i的节点的左儿子下标2*i

int main(int argc, char *argv[])
{
    pri_queue_t *priq;
    #define CAPACITY 50
    priq = initialize(CAPACITY);

    srand(time(NULL));
    int i;
    for (i = 0; i < CAPACITY; i ++) {
        insert(priq, rand()%100);
    }

    for (i = 0; i < CAPACITY; i ++) {
        printf("%3d", priq->elems[i+1]);
    }
    printf("\ndelete:\n");

    for (i = 0; i < CAPACITY; i ++) {
        printf("%3d", get_min(priq));
        delete_min(priq);
    }

    return 0;
}

pri_queue_t *initialize(int capacity)
{
    if (capacity < 1)
        return NULL;

    pri_queue_t *priq;

    priq = (pri_queue_t *)malloc(sizeof(pri_queue_t));
    assert(priq != NULL);

    priq->capacity = capacity;
    priq->elems = (int *)malloc(sizeof(int) * capacity);
    assert(priq->elems != NULL);

    priq->elems[0] = 0;

    return priq;
}

void destroy(pri_queue_t *priq)
{
    if (NULL == priq)
        return;
    free(priq->elems);
    free(priq);
}

int is_empty(pri_queue_t *priq)
{
    return (0 == priq->elems[0]);
}

int is_full(pri_queue_t *priq)
{
    return (priq->elems[0] == priq->capacity);
}

void insert(pri_queue_t *priq, int x)
{
    if (NULL == priq)
        return;
    if (is_full(priq)) {
        printf("full.\n");
        return;
    }

    int i = ++ priq->elems[0];
    for (; i!=1 && priq->elems[PARENT(i)]>x; i = PARENT(i)) {
        priq->elems[i] = priq->elems[PARENT(i)];
    }
    priq->elems[i] = x;
}

int get_min(pri_queue_t *priq)
{
    return priq->elems[1];
}

void delete_min(pri_queue_t *priq)
{
    assert(priq != NULL);

    if (is_empty(priq)) {
        printf("empty.\n");
        return;
    }

    int lastelem = priq->elems[priq->elems[0]--];

    int i, child;
    for (i = 1; LCHILD(i) <= priq->elems[0]; i = child) {
        child = LCHILD(i);
        if (child!=priq->elems[0] && priq->elems[child]>priq->elems[child+1])
            ++ child;
        if (lastelem > priq->elems[child])
            priq->elems[i] = priq->elems[child];
        else
            break;
    }
    priq->elems[i] = lastelem;
}

python 实现:
和上面略有不同的是,没有指定队列的capacity
class priority_queue:
    def __init__(self):
        self.priq = [0]

    def is_empty(self):
        return 0==self.priq[0]

    def min(self):
        assert False == self.is_empty()
        return self.priq[1]

    def insert(self, x):
        self.priq[0] += 1
        self.priq.append(x)

        i = self.priq[0]
        while i>1 and self.priq[i>>1]>x:
            self.priq[i] = self.priq[i>>1]
            i = i>>1
        self.priq[i] = x

    def delete_min(self):
        assert False == self.is_empty()

        last_index = self.priq[0]
        self.priq[0] -= 1
        last_element = self.priq[last_index]

        i = 1
        while (i<<1)<=self.priq[0]:
            child = i<<1
            if child!=self.priq[0] and self.priq[child]>self.priq[child+1]:
                child += 1

            if last_element > self.priq[child]:
                self.priq[i] = self.priq[child]
            else:
                break

            i = child

        self.priq[i] = last_element
        
def main():
    import random

    q = priority_queue()
    for i in random.sample([j for j in range(1000)], 50):
        q.insert(i)

    print 'priority queue:\n', q.priq[1:]

    print 'delete:'
    while False == q.is_empty():
        print q.min(),
        q.delete_min()
    #q.delete_min()


if __name__ == '__main__':
    main()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值