栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

初识数据结构之堆

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

初识数据结构之堆

  • 特点
  1. 堆是一棵完全二叉树,即除了最下边一层其余都是满的状态,最下边一层满足最后一个元素的左侧都是满状态。
  2. 堆有别于二叉树的一个特点就是其父节点是大于两个子节点的,两个子节点的左右分步没有硬性要求
  3. 堆通常以数组进行实现,常见的规律有 假设一个节点所在的索引为k,则其父节点所在的索引为k/2,两个子节点的索引分别为2k和2k+1

自己实现堆

public class Heap> {

    // 用来存储元素的数组
    private T[] items;
    // 用来存储堆中元素的个数
    private int size;

    public Heap(int capacity) {
        this.items = (T[]) new Comparable[capacity + 1];
        this.size = 0;
    }

    
    private void exchange(int i, int j) {
        T temp = this.items[i];
        this.items[i] = this.items[j];
        this.items[j] = temp;
    }


    
    public T deleteMax() {
        // 交换最大的元素和最大索引处的值
        T maxItem = items[1];
        exchange(1, size);
        // 删除最大的元素,让完全二叉树中最右侧的元素变为临时的根节点
        items[size] = null;
        this.size --;
        // 通过下沉算法调整堆,让根节点重新处于正确的位置,让堆重新有序
        this.sink(1);
        return maxItem;
    }

    
    public void insert(T t) {
        items[++ size] = t;
        swim(size);
    }

    
    private void swim(int index) {
        while (index > 1) {
            // 与父节点进行比较
            if (items[index].compareTo(items[index/2]) > 0) {
                exchange(index, index/2);
            }
            index = index / 2;
        }
    }

    
    private void sink(int index) {
        // 通过循环弊端的遍历当前索引的两个子节点
        while (2*index <= size) {
            // 获取两个子节点中较大的那个
            int maxChildIndex;
            if (2*index+1 <= size) {
                maxChildIndex = items[2*index].compareTo(items[2*index+1]) > 0 ? 2*index : 2*index+1;
            } else {
                maxChildIndex = 2*index;
            }

            // 比较当前索引处的值和两个子节点最大的值的关系
            if (items[index].compareTo(items[maxChildIndex]) < 0) {
                // 当前索引比子节点的最大值小,就往两个子节点的最大者底下沉
                exchange(index, maxChildIndex);
                index = maxChildIndex;
            } else {
                break;
            }
        }
    }

    
    public static void sort(Comparable[] source) {
        // 1. 构建堆
        // 将source数组中的元素拷贝到堆数组中,形成一个无序待排序的堆
        Comparable[] heap = new Comparable[source.length + 1];
        System.arraycopy(source, 0, heap, 1, source.length);
        // 对堆中的元素做下沉调整(从堆长度的一般开始,往索引1处进行扫描)
        for (int i=(heap.length)/2; i>0; i--) {
            sinkSort(heap, i, source.length);
        }

        // 2. 堆排序
        // 记录未排序的数组最大索引
        int maxIndex = source.length;
        while (maxIndex != 1) {
            // 交换1索引处和未排序的最大索引处的值
            Comparable temp = heap[1];
            heap[1] = heap[maxIndex];
            heap[maxIndex] = temp;
            maxIndex --;
            // 对交换之后的索引1处元素进行下沉调整,调整的区域为未排序区域
            sinkSort(heap, 1, maxIndex);
        }

        // 3. 将排序好的数组转到原数组中
        System.arraycopy(heap, 1, source, 0, source.length);
    }

    
    private static void sinkSort(Comparable[] heap, int targetIndex, int range) {
        while (2*targetIndex <= range) {
            int maxChildIndex;
            if (2*targetIndex+1 < range) {
                maxChildIndex = heap[2*targetIndex].compareTo(heap[2*targetIndex+1])>0 ? 2*targetIndex : 2*targetIndex+1;
            } else {
                maxChildIndex = 2*targetIndex;
            }

            if (heap[targetIndex].compareTo(heap[maxChildIndex]) >= 0) break;

            // 元素位置交换
            Comparable temp = heap[targetIndex];
            heap[targetIndex] = heap[maxChildIndex];
            heap[maxChildIndex] = temp;

            targetIndex = maxChildIndex;
        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/859980.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号