[Java数据结构]堆排序

一、堆(Heap)
概念

  • 堆逻辑上是一棵完全二叉树;
  • 堆物理上是保存在数组中;
  • 满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆;
  • 反之,则是小堆,或者小根堆,或者最小堆
  • 堆的基本作用是用来查找最值的,堆顶元素。

操作-向下调整
前提:左右子树必须已经是一个堆了,才能调整
调整过程(以小堆为例):

  • index:代表要调整位置的下标
  • array:代表存储堆的数组
  • size:代表数组中被视为堆元素的个数
  • left:代表index左孩子的下标
  • right:代表index右孩子的下标
  • minIndex:保存index最小孩子的下标

思路
(以小堆调整为例)
1.index如果是叶子结点,则调整结束
(1)判断 index 位置有没有孩子
(2)因为堆是完全二叉树,没有左孩子就一定没有右孩子,所以判断是否有左孩子
(3)因为堆的存储结构是数组,所以判断是否有左孩子即判断左孩子下标是否越界,即 left >= size 越界
2. 确定 left 或 right,谁是 index 的最小孩子 minIndex
(1)如果右孩子不存在,则 minIndex = left
(2) 否则,比较 array[left] 和 array[right] 值得大小,选择小的为 minIndex
3.比较 array[index] 的值 和 array[minIndex] 的值,如果 array[index] <=array[minIndex],则满足堆的性质,调整结束
4.否则,交换 array[index] 和 array[min] 的值
5.然后因为 minIndex 位置的堆的性质可能被破坏,所以把 minIndex 视作 index,继续循环执行以上操作

向上调整思路:
1.判断index是否为根节点(index==0),如果是则结束;
2.找到index的父亲节点,比较它的值和父亲节点的值,如果array[Index]<=array[parentIndex],则结束;否则,交换两者的值;
3.让index为父亲结点的值,继续循环。
思路整体简单一点,只需要和父亲节点比较即可。
建堆
建堆也是一个循环调整的过程,首先保证它在逻辑上是一棵二叉树,根据堆的定义和性质进行判断让它符合堆的性质。

堆的应用
优先级队列(堆):

public class MyPriorityQueue {
    
    
    private Integer[] array;
    private int size;
    
    public MyPriorityQueue(){
    
    
        array=new Integer[100];
        size=0;
        
    }
    //得到element下标的元素
    public Integer element(){
    
    
        if(size==0){
    
    
            throw new RuntimeException("空了");
        }
        return array[0];
    }

    //删除元素
    public Integer remove(){
    
    
        if(size==0){
    
    
            throw new RuntimeException("空的");
        }
        int e=array[0];
        array[0]=array[size-1];
        size--;
        adjustDown(0);
        return e;
    }
   public void adjustDown(int index){
    
    
        while(true){
    
    
            int leftIndex=2*index+1;
            if(array[leftIndex]>=size){
    
    
                break;
            }
            int minIndex=leftIndex;
            int rightIndex=leftIndex+1;
            if(rightIndex<size&&array[rightIndex]<array[leftIndex]){
    
    
                minIndex=rightIndex;
            }
            int t=array[index];
            array[index]=array[rightIndex];
            array[rightIndex]=t;

            index=minIndex;
        }
   }

    public void add(Integer e){
    
    
        array[size]=e;
        size++;
        adjustUp(size-1);
    }
    private void adjustUp(int index){
    
    
        while (true){
    
    
            if(index==0){
    
    
                break;
            }
            int parentIndex=(index-1)/2;
            if(array[parentIndex]<=array[index]){
    
    
                break;
            }
            int t=array[index];
            array[index]=array[parentIndex];
            array[parentIndex]=t;

            index=parentIndex;
        }

    }

    public static void main(String[] args) {
    
    
        MyPriorityQueue myPriorityQueue=new MyPriorityQueue();
        
        myPriorityQueue.add(1);
        myPriorityQueue.add(4);
        myPriorityQueue.add(3);
        myPriorityQueue.add(5);
        myPriorityQueue.add(6);
     }
 }

猜你喜欢

转载自blog.csdn.net/m0_46551861/article/details/109141622