优先队列(堆)

本文介绍二叉堆的基本概念,包括最大堆和最小堆,并详细解释了如何使用数组来实现二叉堆。文中提供了关键的操作方法,如插入与删除元素的具体步骤及对应的C语言代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.cnblogs.com/skywang12345/p/3610187.html二叉堆的C语言实现

http://www.cnblogs.com/skywang12345/p/3610382.html二叉堆的C++实现


二叉堆分为两种:最大堆和最小堆

最大堆:父节点的键值总是大于或等于任何一个子节点的键值

最小堆:父节点的键值总是小于或等于任何一个子节点的键值

二叉堆一般都通过数组来实现:

将二叉堆的第一个节点放在数组索引0的位置上,则:

1)索引为i的左孩子的索引为 2*i+1

2)索引为i的右孩子的索引为 2*i+2

3)索引为i的父亲的索引为 floor((i-1)/2)

将二叉堆的第一个节点放在数组索引1的位置上,则:

1)索引为i的左孩子的索引为 2*i

2)索引为i的右孩子的索引为 2*i+1

3)索引为i的父亲的索引为 floor(i/2)

后文采用将二叉堆第一个节点放在数组索引0的位置上实现:

1.添加:(最大堆的插入代码)

1)将值插入最大堆末尾

2)若插入值大于父节点的值,则将它与父节点交换

3)直到挪不动为止

void push_up(int start) {//从start开始向上直到0,调整堆
    int c = start;//当前节点的位置
    int p = (c-1)/2;//当前节点的父节点
    int t = m_heap[c];//当前节点的值
    while(c > 0) {
        if(m_heap[p] >= m_heap[c]) {
            break;
        }
        m_heap[c] = m_heap[p];
        c = p;
        p = (c-1)/2;
    }
    m_heap[c] = t;
}
int Insert(int n) {//成功返回0,失败返回-1
    if(m_size == MAX_SIZE) {
        return -1;
    }
    m_heap[m_size] = n;//将要插入的值放在数组末尾
    push_up(m_size);//向上调整堆
    m_size++;//堆的大小加1
    return 0;
}

2.删除(从最大堆中删除元素)

1)删除该数据

2)用最大堆的最后一个元素插入这个空位

3)把这个“空位”尽量上挪,直到剩下的元素变成一个最大堆

int get_index(int data) {
    //寻找data,找到则返回下标值,找不到,返回-1
    for(int i = 0; i < m_size; i++) {
        if(m_heap[i] == data) {
            return i;
        }
    }
    return -1;
}
void push_down(int start, int end) {
    //start 被下调节点的起始位置
    //end 截止范围,一般为数组最后一个元素的索引
    int c = start;//当前位置
    int l = c*2+1;//当前位置的左孩子
    int t = m_heap[c];//当前位置的值
    while(l <= end) {
        //l为左孩子, l+1为右孩子
        if(l < end && m_heap[l] < m_heap[l+1]) {
            l++;//选取左右孩子中的较大者
        }
        if(t >= m_heap[l]) {
            break;
        }
        c = l;
        l = c*2+1;
    }
    m_heap[c] = t;
}
int delete(int data) {//成功返回0, 失败返回-1
    if(m_size == 0) return -1;
    int index = get_index(data);
    if(index == -1) return -1;
    m_heap[index] = m_heap[--m_size];//用最后元素填补
    push_down(index, m_size-1);//从index位置从上到下调整为最大堆
    return 0;
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值