堆(优先队列)C/C++、C#代码实现

堆是一颗被完全填满的二叉树,它的任一结点的关键字是其子树所有结点的最大值或最小值,
最大值的则是最大堆,也称大顶堆,最小值的则是最小堆,也称小顶堆。
比如:
在这里插入图片描述

最小堆C/C++实现

#pragma once
#include <vector>
#include <initializer_list>
template <typename Comparable>
class MinHeap
{
public:
	explicit MinHeap(int capacity = 100) :array(capacity + 10), currentSize(0) {}
	explicit MinHeap(const std::vector<Comparable> & items);
	bool isEmpty()const { return array.size() == 0; }
	const Comparable & findMin()const { return array[1]; }
	void insert(const Comparable & x);
	void insert(std::initializer_list<Comparable>t);
	void deleteMin();
	void deleteMin(Comparable & minItem);
	void makeEmpty() { array.swap(vector<Comparable>()); }
private:
	int currentSize;
	std::vector<Comparable>array;
	void buildHeap();
	void Sink(int hole);//下沉
};



template<typename Comparable>
MinHeap<Comparable>::MinHeap(const std::vector<Comparable>& items):array(items.size()+10),currentSize(items.size())
{
	for (int i = 0; i < items.size(); i++)
		array[i + 1] = items[i];
	buildHeap();

}


template<typename Comparable>
void MinHeap<Comparable>::insert(const Comparable & x)
{
	if (currentSize == array.size() - 1)
	{
		array.resize(array.size() * 2);
	}
	int hole = ++currentSize;
	Comparable copy = x;
	array[0] = std::move(copy);//保存原来的值
	for (; x < array[hole / 2]; hole /= 2)//如果x更小,就一直上浮
	{
		array[hole] = std::move(array[hole / 2]);//交换
	}
	array[hole] = std::move(array[0]);//空穴找到了合适的位置,把原来的值放进去.
}

template<typename Comparable>
 void MinHeap<Comparable>::insert(std::initializer_list<Comparable>t)
{
	 for (auto p = t.begin(); p != t.end(); p++)
	 {
		 insert(*p);
	 }
}

template<typename Comparable>
void MinHeap<Comparable>::deleteMin()
{
	if (isEmpty())
	{
		std::cout << "Heap Is Empty!" << std::endl;
		return;
	}

	array[1] = std::move(array[currentSize--]);
	Sink(1);
}

template<typename Comparable>
void MinHeap<Comparable>::deleteMin(Comparable & minItem)
{
	if (isEmpty())
	{
		std::cout << "Heap Is Empty!" << std::endl;
		return;
	}

	minItem = std::move(array[1]);
	array[1] = std::move(array[currentSize--]);//从数组顶端删去最小的元素,并将数组最后的一个元素放到顶端
	Sink(1);//然后让这个元素下沉
}



template<typename Comparable>
void MinHeap<Comparable>::buildHeap()
{
	for (int i = currentSize / 2; i > 0; --i)
	{
		Sink(i);
	}
}

template<typename Comparable>
 void MinHeap<Comparable>::Sink(int hole)//下沉
{
	 int child;
	 Comparable temp = std::move(array[hole]);
	 for (; hole * 2 <= currentSize; hole = child)
	 {
		 child = hole * 2;
		 if (child != currentSize && array[child + 1] < array[child])//右边更小,往右沉
			 ++child;
		 if (array[child] < temp)//比目标值小,当前child上浮
			 array[hole] = std::move(array[child]);
		 else  //比目标值大,或相等,找到合适的位置,退出循环
			 break;

	 }
	 array[hole] = std::move(temp);
}

最大堆C#实现

    public class MaxHeap<T> where T : IComparable<T>
    {
        private T[] array;
        private int CurrentSize { set; get; }
        public MaxHeap(int capacity = 100)
        {
            array = new T[capacity];
            CurrentSize = 0;
  
        }
        public MaxHeap(T[] items)
        {
            array = new T[items.Length + 10];
            for (int i = 0; i < items.Length; i++)
            {
                array[i + 1] = items[i];
            }
        }
        public bool IsEmpty(){ return array.Length == 0; }
        public T Max() { return array[1]; }
        public void Insert( T x)
        {
            if(CurrentSize == array.Length -1)
            {
                T[] temp = array;
                array = new T[array.Length * 2];
                for(int i = 0; i < temp.Length;i++)
                {
                    array[i + 1] = temp[i + 1];
                }
                temp = null;
            }
            int hole = ++CurrentSize;
            array[0] = x;
            for (; array[hole / 2].CompareTo(x) < 0;hole /=2)
            {
                array[hole] = array[hole / 2];
            }

            array[hole] = array[0];

        }
        public void Insert(params T[] paramList)
        {
            foreach (T temp in paramList)
            {
                Insert(temp);
            }
        }
        public void DeleteMax()
        {
            if(IsEmpty())
            {
                throw new Exception("Heap Is Empty!\n");
            }
            array[1] = array[CurrentSize--];
            Sink(1);
        }
        public void DeleteMax(out T temp)
        {
            if (IsEmpty())
            {
                throw new Exception("Heap Is Empty!\n");
            }
            temp = array[1];
            array[1] = array[CurrentSize--];
            Sink(1);
            return;
        }

        private void BuildHeap()
        {
            for (int i = CurrentSize / 2; i > 0; --i)
            {
                Sink(i);
            }
        }
        private void Sink(int hole)
        {
            int child;
            T temp = array[hole];
            for(; hole *2 <= CurrentSize; hole = child)
            {
                child = hole * 2;
                if (child != CurrentSize && array[child].CompareTo(array[child + 1]) < 0)
                    ++child; //child指向左右子节点的较大者
                if (temp.CompareTo(array[child]) < 0)
                    array[hole] = array[child];
                else
                    break;
            }
            array[hole] = temp;
        }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值