zoukankan      html  css  js  c++  java
  • 数据结构Java版之堆&堆排序(九)

      堆分为大顶堆,和小顶堆。 什么是堆? 堆可以看成是一棵二叉树,二叉树的元素是一个数组不断的从左到右轮训放置。如果是大顶堆,则大的数放上面一层,小的数放下面一层。上一层的数,一定大于下一层的数。小顶堆则相反。

      那么,如何实现一个大顶堆?这里我用一个链表来实现。

    实现堆很简单,只要牢记他的原理就行了。

      添加新元素:添加至数组末尾。然后对这个末尾节点不断的向上层冒泡。直到找到一个合适的节点放置。

      删除元素:从数组末尾取出一个元素对当前要删除的元素进行覆盖,后删除末尾的元素。然后从当前节点不断的向下冒泡。就能找到一个合适的位置进行放置。

      上层元素和下层元素之间的关系:上层元素(索引为:index )和下层元素索引存在 2 * index + 1(左孩子节点) 2 * index + 2(右孩子节点)的关系。

    实现源码:

    package heap;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import org.junit.Test;
    
    public class Heap {
        private List<Integer> heapArray;
        public Heap() {
            super();
            this.heapArray = new ArrayList();
        }
        //添加元素进堆 
        public void Push(Integer x) {
            heapArray.add(x);
            trickleUp(heapArray.size()-1);
        }
        //删除元素
        public void Pop() {
            heapArray.set(0, heapArray.get(heapArray.size()-1));
            heapArray.remove(heapArray.size()-1);
            trickleDown(0);
        }
        //取出根数据
        public Integer Top() {
            return heapArray.get(0);
        }
        //判断是否为空
        public boolean isEmpty() {
            if(Top() == null) {
                return true;
            }
            return false;
        }
        //向上渗透
        public void trickleUp(int index) {
            int parent = (index-1) / 2;
            Integer bottom = heapArray.get(index);
            while(index > 0 && heapArray.get(parent) < bottom) {
                heapArray.set(index, heapArray.get(parent));
                index = parent;
                parent = (parent - 1) / 2;
            }
            heapArray.set(index, bottom);
        }
        //向下渗透
        public void trickleDown(int index) {
            Integer top = heapArray.get(0);
            int lagerChild;
            while(index < heapArray.size()/2) {
                int leftChild = index * 2 + 1;
                int rightChild = index * 2 + 2;
                if(rightChild < heapArray.size() && heapArray.get(leftChild) < heapArray.get(rightChild)) {
                    lagerChild = rightChild;
                }else {
                    lagerChild = leftChild;
                }
                if(top >= heapArray.get(lagerChild)) {
                    break;
                }
                heapArray.set(index, heapArray.get(lagerChild));
                index = lagerChild;
            }
            heapArray.set(index, top);
        }
    }

    测试程序:

    @Test
    public void fun() {
        Heap p = new Heap();
        p.Push(20);
        p.Push(30);
        p.Push(15);
        System.out.println(p.Top());
        p.Push(90);
        p.Push(35);
        System.out.println(p.Top());
        p.Pop();
        System.out.println(p.Top());
    }

    测试结果:

    30
    90
    35

      堆排序:

    堆排序非常简单,利用大顶堆的顶一定是堆元素里面的最大值。那么我们就可以将一系列数据存进去,再不断的取出顶元素。取除的元素就是一个排好序的元素。

    源码:

      

        public static void main(String[] args) {
            Heap h = new Heap();
            h.Push(2);
            h.Push(1);
            h.Push(4);
            h.Push(6);
            System.out.println(h.Top());
            h.Pop();
            System.out.println(h.Top());
            h.Pop();
            System.out.println(h.Top());
            h.Pop();
            System.out.println(h.Top());
        }

    结果:

    6
    4
    2
    1

    至此,堆排序就已经做好了。

  • 相关阅读:
    Set up width and height tcl tk main window
    makefile
    itk_component add
    android的各种*.img 文件
    Install Android 2.2.1 Froyo On Nook Color [Advanced Guide]
    Android开机启动流程初探
    编译MTK6516脚本
    调试MTK6516错误总结
    Android开机启动流程初探
    编译MTK6516脚本
  • 原文地址:https://www.cnblogs.com/ranter/p/9249956.html
Copyright © 2011-2022 走看看