数组实现的大根堆

  • 一种树状的数据结构

大根堆

  • 根节点是所有节点中数值最大的节点
  • 父节点的值总比子节点大
  • 基本操作
    • Insert 向堆中插入一个值
    • Update 更新
    • Heapify 堆化
    • RemoveTop 删除堆顶元素
    • GetTop 获得堆顶元素
  • 辅助操作
    • 获得父节点
    • 获得左孩子
    • 获得右孩子
    • 获得当前容量
    • 判断一个节点是否是叶子节点
    • 交换2个节点的位置

数组大根堆

  • 用数组实现的大根堆
  • 作用
    • 堆排序
    • 求最大值
    • 求第n大的值
  • 基本操作
    • Insert 向堆中插入一个值
    • Update 从指定的节点开始把较大的值和父节点交换直到处理到根节点
    • Heapify 从指定的节点开始把较小的节点和子节点中较大的那个交换直到处理到叶子节点
    • RemoveTop 删除堆顶元素
      • 把堆尾部的元素换到堆顶,堆大小-1
      • 从堆顶开始执行堆化
    • GetTop 获得堆顶元素
  • 辅助操作
    • 获得父节点
      • 父节点和子节点的关系
        • leftChildIndex = parentIndex * 2 + 1
        • rightChildIndex = parentIndex * 2 + 2
        • parentIndex = (childIndex - 1) / 2
    • 获得左孩子
    • 获得右孩子
    • 获得当前容量
    • 判断一个节点是否是叶子节点
      • 如果一个节点的孩子index超过当前容量说明这个节点没有子节点,故为叶子节点
    • 交换2个节点的位置
    • 获得最大容量
    • 根据index判断一个节点是否在堆中
  • 实现代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DataStructure
{

  public class ArrayMaxHeap
  {
    int[] array;
    int size;
    int maxSize;

    public void Build(int maxSize)
    {
      array = new int[maxSize];
      this.maxSize = maxSize;
      size = 0;
    }

    public int GetSize()
    {
      return size;
    }

    public int GetMaxSize()
    {
      return maxSize;
    }

    //尾部追加再更新
    public void Insert(int value)
    {
      if (size == maxSize)
      {
        throw new Exception("size must <= max size");
      }
      array[size] = value;
      size++;
      Update(size - 1);
    }

    //把大的值往堆顶放
    //把一个大的值从下面换到父节点,直到堆顶
    void Update(int index)
    {
      if (index == 0) return;
      if (index < 0) throw new ArgumentException("index must >= 0");
      if (array[index] > array[ParentIndex(index)])
      {
        Swape(index, ParentIndex(index));
        Update(ParentIndex(index));
      }
    }

    public int LeftChildIndex(int index)
    {
      return index * 2 + 1;
    }

    public int RightChildIndex(int index)
    {
      return index * 2 + 2;
    }

    public int ParentIndex(int index)
    {
      return (index - 1) / 2;
    }

    public bool IsLeaf(int index)
    {
      return !IsInHeap(LeftChildIndex(index));
    }

    public bool IsInHeap(int index)
    {
      return 0 <= index && index < size;
    }

    private void Swape(int index1, int index2)
    {
      var temp = array[index1];
      array[index1] = array[index2];
      array[index2] = temp;
    }

    public int GetTop()
    {
      return array[0];
    }

    void Heapify(int index)
    {
      if (IsLeaf(index))
      {
        return;
      }
      //找到左边和右边最大的那个子节点,如果子节点更大,交换,对子节点执行堆化,把小的值往堆底放
      //左子节点更大
      if (array[LeftChildIndex(index)] > array[RightChildIndex(index)])
      {
        if (array[index] < array[LeftChildIndex(index)])
        {
          Swape(index, LeftChildIndex(index));
          Heapify(LeftChildIndex(index));
        }
      }
      //右孩子更大,比较右孩子
      else if (array[index] < array[RightChildIndex(index)])
      {
        Swape(index, RightChildIndex(index));
        Heapify(RightChildIndex(index));
      }

    }

    //取出堆顶,把尾部放到堆顶,执行堆化
    public int RemoveTop()
    {
      if (size == 0) throw new Exception("no element in heap");
      var top = array[0];
      array[0] = array[size - 1];
      size--;
      Heapify(0);
      return top;
    }

    public static void Test()
        {
            var array = new int[] { 2, 4, 6, 7, 8, 3, 2, 5 };
            var solution = new ArrayMaxHeap();
            solution.Build(array.Length);
            foreach (var num in array)
            {
                solution.Insert(num);
                BaseSolution.print(solution.GetTop());
                BaseSolution.print(',');
            }
            BaseSolution.println();
            while (solution.GetSize() > 0)
            {
                BaseSolution.print(solution.RemoveTop());
                BaseSolution.print(',');
            }
        }

  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值