BinaryHeap(二叉堆) & HeapSort)(

2018-08-23  本文已影响65人  须臾之北

HeapSort

转载自:链接:https://www.jianshu.com/p/719b0de606a7 作者:Geek5Nan

侵删

主要内容概述

什么是二叉堆

一、当二叉树满足满足如下条件时,我们说这个二叉树是堆有序的:

  1. 每一个父结点的值都比它的子结点大(称为大顶堆)或小(称为小顶堆)
  2. 子结点的大小与其左右位置无关

二、二叉堆的两种实现方式

  1. 堆有序的二叉树,也可称为二叉堆。

  2. 二叉堆是最常见的堆结构,因此也常将二叉堆直接称为堆,可以采用如下两种方式来表示二叉堆

    • 使用指针

      • 二叉树的每个结点需存储三个指针,分别指向其父结点和两个子结点
    • 使用数组

      a. indices start at 1 下标从1开始
      b. Take nodes in level order(层序遍历)
      c. parent of node at k is at k/2
      d. children of node at k are 2k and 2k+1

  3. 堆的数组表示

    image

二叉堆的有序化

1. 由下至上的堆有序化(上浮-swim)

2. 由上至下的堆有序化(下沉-sink)

二叉堆实现优先队列(priority queue)

    /*
     *  此程序是一个优先队列(priority queue)数据结构的实现
     *  适用于我们无法保存大量的数据时候
     * 
     *  此时我们使用的是二叉堆——数组实现
     *  我们的下标是从1-N
     * 
     *  1. 插入数据——insert
     *  2. 返回最大值
     *  3. 判断队列是否空
     *  4. 当前队列长度
     * */
    
    public class MaxPQ<Key extends Comparable<Key>> {
        private Key[] pq;
        private int N = 0;
        
        //创建固定大小的优先队列
        public MaxPQ(int maxN){
            pq = (Key[]) new Comparable[maxN+1];
        }
        
        public boolean isEmpty() {
            return N == 0;
        }
        
        //插入数据
        public void insert(E e) {
            
            //插入到末尾
            pq[++N] = e;
            
            //swim
            swim(N);
        }   
    
        //删除最大值
        public Key delMax() throws Exception{
    
            if(isEmpty()) {
                throw new Exception("pq is empty");
            }
            
            //保存最大值
            Key max = pq[1];
            
            //交换最后一个和最大值
            exch(1,N--);
            
            //下沉交换上去的值
            sink(1);
            
            pq[++N] = null;
            
            return max;
        }
    
        //sink
        private void sink(int k) {
            // TODO Auto-generated method stub
            //将i下沉
            while(2 * k <= N) {
                int j = 2 * k;
                
                if(j < N && less(j, j+1)) j++;          //j指向较大的孩子的下标
                if(!less(k, j)) break;  
                
                exch(k,j);                              //交换父节点与较大的子孩子
                
                k = j;                                  //继续向下判断
            }
        }   
        
        //swim
        private void swim(int k) {
            // TODO Auto-generated method stub
            while(k > 1 && less(k/2,k)) {           //父小于子,则交换父子
                exch(k/2, k);
                k = k/2;
            }
        }
        
        private void exch(int i, int j) {
            // TODO Auto-generated method stub
            Key tmp = pq[i];
            pq[i] = pq[j];
            pq[j] = tmp;
        }   
    
        private boolean less(int i, int j) {
            // TODO Auto-generated method stub
            return pq[i].compareTo((E) pq[j]) < 0;
        }
    }

HeapSort的实现

image

小结

堆排序算法也是一种选择排序算法,每一次删除一个最大(delMax)或最小(delMin)

整体由堆的构建、堆的交换与下沉两个步骤组成。

上一篇 下一篇

猜你喜欢

热点阅读