数据结构与算法---复习:堆 优先队列

数据结构与算法—复习:堆 优先队列

优先队列的精髓:

  1. 插入算法:
    该算法从优先队列的序列去观察,比较直观。首先把要插入的元素放在队尾temp里。从队列的最后一个元素,逐次向前寻找父节点,空位随之移动,当到达队头,或者当前元素小于temp元素时,即可插入。

  2. 删除算法:
    删除最小元素,也就是最头的元素。当我们利用(当前元素数量)-1 这样的操作删除元素后,最后一个元素便被排空了出来,所以主要任务便是安排最后一个元素的落点。从队头开始,用两个指针,分别指向父结点和子结点,当子结点未到达队尾,循环条件成立。首先在子结点中挑选一个较小的。然后再判断,temp(放入队尾元素的)是否大于这个最小的子结点,如果是,则 指针2 -> 指针2 的子结点,指针1 -> 指针2。再次循环。如果temp小于这个最小的子结点,则说明发现合适的位置,可以直接插入。当循环结束,也未发现temp < 子结点 的位置时,循环结束,此时的指针1位置,便是最佳位置。

    堆序性:每个根结点<每个子结点 或 每个根结点>每个子结点

/**
 * 程序说明:复习 堆  优先队列
 * 优先队列---堆来存储
 * 1.插入
 */

#include <stdio.h>
#include <malloc.h>

/**
 * 优先队列定义
 * 与顺序存储的二叉树一致
 */
struct PriorityQueue{
    int MAXNUM;  //最大长度
    int n;  //当前数量
    int* val;  //数据类型
};
typedef struct PriorityQueue* PPriorityQueue;

/**
 * 优先队列 创建空的优先队列
 * @param m
 * @return
 */
PPriorityQueue createNullPriorityQueue(int m){
    PPriorityQueue papq = (PPriorityQueue)malloc(sizeof(struct PriorityQueue));
    if(papq != NULL){
        papq->val = (int*)malloc(sizeof(int)*m);
        if(papq->val){
            papq->n = 0;
            papq->MAXNUM = m;
            return papq;
        }
        printf("创建失败\n");
        return NULL;
    }
    printf("创建失败\n");
    return NULL;
}

/**
 * 给定数据,初始化优先队列
 * @param papq
 */
void init(PPriorityQueue papq){
    int datas[] = {2,3,5,9,10,7,8,14,12,11,16};
    if(papq->n == papq->MAXNUM){
        printf("优先队列已满\n");
        return;
    }
    int size = sizeof(datas) / sizeof(int);
    for (int i = 0; i < size; ++i) {
        papq->val[i] = datas[i];
        papq->n ++;
    }
    printf("初始化完毕\n");
}

/**
 * 优先队列打印方法
 * @param papq
 */
void printPQ(PPriorityQueue papq){
    if(papq->n == 0){
        printf("队列为空,无法打印\n");
        return;
    }
    for (int i = 0; i < papq->n; ++i) {
        if(i == papq->n - 1){
            printf("%d",papq->val[i]);
            printf("\n");
        }else{
            printf("%d,",papq->val[i]);
        }
    }
}

int isEmpty_heap(PPriorityQueue papq){
    return papq->n == 0;
}

/**
 * 优先队列 插入数据
 * @param papq
 * @param data
 */
void add_heap(PPriorityQueue papq,int data){
    if(papq->n == papq->MAXNUM){
        printf("优先队列已满,无法插入\n");
        return;
    }
    int i = 0;
    for (i = papq->n; i > 0 && papq->val[(i-1)/2] > data; i = (i-1)/2) {
        papq->val[i] = papq->val[(i-1) / 2];
    }
    papq->val[i] = data; papq->n++;
}

void removeMin_heap(PPriorityQueue papq){
    int i = 0,  //指向当前根节点
        child = 1,  //指向当前根节点的左子结点
        temp = 0,  //存放最后一个元素
        s = 0;  //对标当前优先队列中的元素数量
    s = --papq->n;  //先删除元素
    temp = papq->val[s];    //最后一个数据放在temp中
    while (child < s)   //当子节点还没超出队列范围时
    {
        if (child < s - 1 && papq->val[child] > papq->val[child+1]){  //选择较小的节点{
            child++;
        }
        if(temp > papq->val[child]){  //若最后一个元素大于当前子节点,那么令i =child child = 2*i + 1
            papq->val[i] = papq->val[child]; //去寻找下一个合适的位置
            i = child; child = 2*i + 1;
        } else break; //找到了合适的位置
    }
    papq->val[i] = temp;
}

int main() {
    PPriorityQueue papq = createNullPriorityQueue(100);
    init(papq);
    printPQ(papq);
    add_heap(papq,4);
    printPQ(papq);
    removeMin_heap(papq);
    printPQ(papq);
    removeMin_heap(papq);
    printPQ(papq);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值