堆排代码笔记

搞了个HeapSort类,有个类变量type确定是大顶堆还是小顶堆。

注意,用堆的时候处理的数组是0元素不用的!!

上代码:

package www.com.leetcode.specificProblem;

/**
 * 数组的0元素不用
 * @author 85060
 *
 */
public class HeapSort {
    
    private int heapType;//0表示大顶堆,其他都是小顶堆
    
    public HeapSort(int heapType) {
        this.heapType = heapType;
    }
    
    public void heapSort(int[] num) {
        makeHeap(num);
        
        for(int i = num.length - 1; i >= 2; i--) {//这个i可以理解成,要和堆顶元素交换的那个index,肯定到2就结束了
            shiftDown(num, 1, i);
            
            //堆顶和堆最后的元素交换
            int temp = num[1];
            num[1] = num[i];
            num[i] = temp;
        }
    }
    
    /**
     * 这个方法把传进来的数组变成堆
     * @param num
     */
    public void makeHeap(int[] num) {
        for(int i = (num.length - 1)/2; i >= 1; i--) {//从最后一个有孩子的结点开始,做筛选操作,直到根节点也就是1号元素(0号不用)
            shiftDown(num, i, num.length - 1);
        }
    }
    
    
    /**
     * 将一颗树从上到下筛选成堆的方法,前提这个根的两个子树都已经是堆了
     * @param heap
     * @param root 开始的结点,也就是根
     * @param last 结束的结点,或者说是完全二叉树最后的那个结点
     */
    public void shiftDown(int[] heap, int root, int last) {
        int rootIndexTemp = root;
        int leftIndexTemp, rightIndexTemp, priorChildIndexTemp;
        
        while(2 * rootIndexTemp <= last) {//保证temp表示的树的左孩子在范围之内
            leftIndexTemp = 2 * rootIndexTemp;
            rightIndexTemp = 2 * rootIndexTemp + 1;
            
            if(rightIndexTemp > last)priorChildIndexTemp = leftIndexTemp;//没有右孩子,那么孩子之间的优先者就直接左孩子
            else priorChildIndexTemp = prior(heap[leftIndexTemp], heap[rightIndexTemp]) ? leftIndexTemp : rightIndexTemp;
            
            if(prior(heap[rootIndexTemp], heap[priorChildIndexTemp])) return;//比孩子结点优先,筛选结束
            else {
                //交换操作
                int temp = heap[rootIndexTemp];
                heap[rootIndexTemp] = heap[priorChildIndexTemp];
                heap[priorChildIndexTemp] = temp;
                rootIndexTemp = priorChildIndexTemp;//指针向下走,直到指定的last范围内的叶节点为止
            }
        }
    }
    
    
    /**
     * 看是大顶堆还是小顶堆,决定是大于优先还是小于优先
     * @param a
     * @param b
     * @return
     */
    private boolean prior(int a, int b) {
        if(heapType == 0)return a >= b;
        else return a <= b;
    }
    
    public static void main(String[] args) {
        int[] a = {0,3,6,1,8,12,55};//注意0号元素不用
        HeapSort heapSort = new HeapSort(0);//大顶堆,按正序排列
        heapSort.heapSort(a);
        show(a);
    }
    
    public static void show(int[] array) {
        for(int i= 1; i < array.length; i ++) {
            System.out.print(array[i] + "	");
        }
        System.out.println();
    }
    
    /**
     * 插入后调整堆的算法
     * @param heap 
     * @param newEleIndex 新元素的序号
     */
    public void adjustHeapAfterInsert(int[] heap, int newEleIndex) {
        int indexTemp = newEleIndex;
        while(indexTemp > 1 && prior(heap[indexTemp], heap[indexTemp / 2])) {//还没到根节点&&比双亲结点的优先级大——就要交换和指针上移
            int temp = heap[indexTemp];
            heap[indexTemp] = heap[indexTemp / 2];
            heap[indexTemp / 2] = temp;
            indexTemp = indexTemp / 2;
        }
    }
    
    
}
原文地址:https://www.cnblogs.com/wangshen31/p/10648807.html