数据结构之“堆”及推排序

6 篇文章 1 订阅
4 篇文章 0 订阅

概述

堆是一种完全二叉树,高度为(高度为O(lgN))这种树结构的效率很高,多用于我们常说的堆排序以及优先队列,例如先入先出队列(FIFO)。

堆排序的时间复杂度为O(NlgN)。

ps:
完全二叉树的定义,若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,说白了,完全二叉树就是一棵数层数为h,则它的第1至h-1层没有空节点,第h层(也就是叶子结点层)有可能有空节点,节点的生成顺序是从左边开始,空节点始终在右边出现。

堆的分类

堆分为大顶堆和小顶堆。
大顶堆的特点是二叉树的父节点均大于它的左右孩子节点,堆排序之后得到的是升序数列。
小顶堆的特点与之相反,为二叉树的父节点均小于它的左右孩子节点,堆排序之后得到的是降序数列。

堆支持的操作

  • 去顶(deleteTop)
  • 堆排序(sort)
  • 优先出列(pop)
  • 堆的元素数量(size)

约定

我们用数组来表示堆中的数据,这里根据堆为完全二叉树的概念,我们认为下标为i的节点的父节点下标为 (i-1)/2,其左节点为下标2*i,右节点下标为2*i+1。
(以上i表示为数组的下标)

演示

接下来是代码实现堆的一系列操作(以大顶堆为例,C# in Unity)

  • Heap类
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

/// <summary>
///
///  大顶堆
///  2017/6/1
/// </summary>
public class Heap{

    public List<int> items;

    public Heap(){
        items = new List<int>();
    }
    /// <summary>
    /// 新增节点
    /// </summary>
    /// <param name="t"></param>
    public void Add(int t) {
        items.Add(t);
        Moveup(items.Count - 1);//下标
    }
    /// <summary>
    /// 去顶
    /// </summary>
    public void Deletetop() {
        if (items == null || items.Count == 0)
        {
            return;
        }
        int deepitem = items[items.Count - 1];
        items.RemoveAt(items.Count - 1);
        items[0] = deepitem;
        Shiftdown(0,items.Count - 1);
        Debug.Log("删除顶节点");
    }
    /// <summary>
    /// 上移操作
    /// </summary>
    /// <param name="index">上移的节点下标</param>
    private void Moveup(int index) {
        int item = items[index];
        while (index > 0)
        {
            int parentIndex = (index - 1) / 2;
            if (parentIndex < 0)
            {
                break;
            }
            int parent = items[parentIndex];
            if (item > parent)
            {
                items[index] = parent;
                index = parentIndex;
            }
            else 
            {
                break;
            }
        }
        items[index] = item;
    }
    /// <summary>
    /// 下沉操作
    /// </summary>
    /// <param name="index">下沉的节点下标</param>
    /// <param name="aimIndex">下沉截止节点下标</param>
    private void Shiftdown(int index,int aimIndex) {//0  9
        int item = items[index];
        while (index < aimIndex)
        {
            int preIndex = 2 * index + 1;
            if (preIndex >= aimIndex)
            {
                break;
            }
            if (preIndex + 1 < aimIndex && items[preIndex + 1] > items[preIndex])//找出孩子中最大的
            {
                preIndex++;
            }
            if (items[preIndex] < item)
            {
                break;
            }
            items[index] = items[preIndex];
            index = preIndex;

        }
        items[index] = item;

    }
    /// <summary>
    /// 优先出列
    /// </summary>
    /// <returns></returns>
    public int Pop()
    {
        if (items == null || items.Count == 0)
        {
            return default(int);
        }
        return items[0];
    }
    public bool isEmpty() {
        return items == null || items.Count == 0;
    }
    /// <summary>
    /// 堆排序
    /// </summary>
    public void HeapSort()
    {
        Debug.Log("---堆排序---");
        for (int i = items.Count - 1; i > 0;i-- )
        {
            Swap(i,0);
            Shiftdown(0,i);
        }

    }
    /// <summary>
    /// 输出
    /// </summary>
    public void OutPut() { 
        string str = "";
        for (int i = 0; i < items.Count;i++ )
        {
            str += items[i] + ",";
        }
        Debug.Log("OutPut(当前数列): " + str);
    }
    private void Swap(int i,int j) { 
        int preNum = items[i];
        items[i] = items[j];
        items[j] = preNum;
    }
}
  • 入口
void Start()
    {
        Heap heap = new Heap();
        string str = "";
        for (int i = 0; i < 11;i++ )
        {
            int random = UnityEngine.Random.Range(0,100);
            heap.Add(random);
            str += (random + ",");
        }
        print("初始化用的数列:"+str);
        heap.OutPut();
        print("优先节点:" + heap.Pop());
        heap.Deletetop();
        heap.OutPut();
        heap.HeapSort();
        heap.OutPut();

    }

运行结果

这里写图片描述

完,老铁,看完别忘记听我分享的音乐~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值