MaxHeap实现

237 阅读2分钟

floyd建堆法

介绍:通过找到最后一个非叶子结点的方法 执行下潜操作 一直到根节点

1、建堆

2、找到最后一个非叶子节点

3、下潜

实现堆最重要的几个方法:

下潜

思路:

当前节点:parent

子节点:child

rightChild = parent * 2 + 1

leftChild = right + 1

1、parent依次和左右子节点进行比较

2、如果parent处的节点小于左右子节点 则进行交换 继续下潜

3、如果都parent比左右子节点都大 停止下潜

这里通过递归实现

 private void down(int parent){
        int rightChild = parent * 2 + 1;
        int leftChild = rightChild + 1;
        int max = parent;
        if(rightChild < size && array[rightChild] > array[max]){
            max = rightChild;
        }
        if(leftChild < size && array[leftChild] > array[max]){
            max = leftChild;
        }
​
        if(max != parent){
            swap(parent, max);
            down(max);
        }
​
    }    
​

上浮

思路:

当前节点:child 父节点:parent

parent = (child-1)/2

1、每次child处的值 和 parent处的值进行比较

2、大于 则将parent处的值赋值给child 继续上浮 否则执行步骤3

3、将值赋值给最后的child

private void up(int element){
        int child = size;
        
        //为了避免parent越界 判断child
        while(child > 0){
            int parent = (child-1)/2;
            if(array[parent] <= element){
                array[child] = array[parent];
                child = parent; 
            }else{
                break;
            }
           
        }
**        **array[child] = element;
    }

交换:

通过临时变量接收来交换

上代码

    int temp = arr[left];
    arr[left] = arr[right];
    arr[right] = temp;

其他方法:

删除弹出元素 poll

堆顶 指定索引出删除

思路:

从当前结点开始 执行下潜操作

 public int poll(){
        if(isEmpty()){
            return -1;
        }
        int removed = array[0];
        swap(0,size-1);
        size--;
        down(0);
​
        return removed;
    }
​
    
    public int poll(int index){
        if(index >= size){
            return -1;
        }
        int removed = array[index];
        swap(index,size-1);
        size--;
        down(index);
​
        return removed;
​
    }

弹出元素 peek

    public int peek() throws Exception{
        if(isEmpty()){
            throw new Exception("list is null");
        }

        return array[0];
    }
​

尾部添加 offer

从当前节点开始 执行上浮操作

 public boolean offer(int element){
        if(isFull()){
            return false;
        }
        up(element);
        size++;

        return false;
    }
​

堆顶替换 replace

替换堆顶元素,执行下潜操作

 //替换堆顶的元素
    public void replace(int element){
        //当堆顶为空时,直接添加
        if(isEmpty()){
            offer(element);
        }
​
        array[0] = element;
        down(0);
    }

结论:以后遇到边界问题,优先判断离边界更近的一段,这样可避免大多数越界问题。

比如上面的下潜先判断孩子索引 上浮判断parent索引

可能结论有误,等到以后有新的结果才来推翻。