索引堆的构建

在这里插入图片描述
【注意】索引堆的实现是建立在堆排序的基础上,还不了解堆排序的柚子,可以参考我的这篇博客二叉堆(最大堆)之堆排序
【代码实现】

#include <iostream>
#include <cassert>
#include <algorithm>
#include <ctime>
#include <string>
#include <cmath>
#include <typeinfo>
#include <cstring>

using namespace std;

template<typename Item>
class HeapIndexMax
{
    private:
        Item *data;   //存放数据的数组
        int*index;  //存放索引的数组
        int count;	  //数据元素的个数
        int capacity; //初始化数组时的数组大小

        void shiftUp(int k)
        {
            while(k > 1 && data[index[k]] > data[index[k / 2]])
            {
                swap(index[k], index[k / 2]);
                k /= 2;
            }
        }
        void shiftDown(int k)
        {
            while(k * 2 <= count)
            {
                int j = k * 2;
                while(j + 1 <= count && data[index[j + 1]] > data[index[j]])
                {
                    j = j + 1;
                }
                if(data[index[k]] > data[index[j]])
                {
                    break;
                }
                swap(index[k], index[j]);
                k = j;
            }
        }
    public:
        HeapIndexMax(int capacity)
        {
            data = new Item[capacity + 1];
            index = new int[capacity + 1];
            count = 0;
            this->capacity = capacity;
        }
        //传入的 i 对于用户而言,是从0开始的
        void insert(int i, Item item)
        {
            assert(count + 1 <= capacity);
            assert(i + 1 >= 1 && i + 1 <= capacity);
            i += 1;
            index[count + 1] = i;
            data[i] = item;

            count++;
            shiftUp(count);
        }
        Item extractMax()
        {
            assert(count > 0);
            Item ret = data[index[1]];
            swap(index[1], index[count]);
            count--;
            shiftDown(1);
            return ret;
        }
        //返回最大元素的索引
        int extractIndexMax()
        {
            assert(count > 0);
            int ret = index[1] - 1;
            swap(index[1], index[count]);
            count--;
            shiftDown(count);
            return ret;
        }
        //返回索引为i的数据
        Item getItem(int i)
        {
            return data[i + 1];
        }
        //希望将索引为i的元素的值修改为 newItem
        void change(int i, Item newItem)
        {
            i += 1;
            data[i] = newItem;
            //要找到index[j] = i 的这个j,这个j表示data[i] 在堆中的位置
            //再shiftUp(j) 和shiftDown(j)
            for(int j = 1; j <= count; j++)
            {
                if(index[j] == i)
                {
                    shiftUp(j);
                    shiftDown(j);
                    return;
                }
            }

        }
        ~HeapIndexMax()
        {
            delete[] data;
            delete[] index;
        }
};

【算法分析】

 //希望将索引为i的元素的值修改为 newItem
        void change(int i, Item newItem)
        {
            i += 1;
            data[i] = newItem;
            //要找到index[j] = i 的这个j,这个j表示data[i] 在堆中的位置
            //再shiftUp(j) 和shiftDown(j)
            for(int j = 1; j <= count; j++)
            {
                if(index[j] == i)
                {
                    shiftUp(j);
                    shiftDown(j);
                    return;
                }
            }
        }

在上面的change函数中,我们来分析一下时间复杂度。一层for循环是O(n)级别的,一次shiftUp和shiftDown是O(logn)级别的,所以change函数的时间复杂度为O(n)。但是我们整个堆排序的时间复杂度为O(logn),那我们有没有办法将change函数的时间复杂度降为O(logn)呢?
请看下回讲解~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值