堆(插入删除)

Posted S-Mustard

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆(插入删除)相关的知识,希望对你有一定的参考价值。

用堆实现优先级队列,插入和删除都很快o(logN)
编程语言中的内存堆与这里的数据结构是不一样的
堆:一种树(特殊的二叉树)
特点:它是完全二叉树,除了树的最后一层节点不需要是满,其他的每一层从左到右都完全是满的。
它常常是用一个数组实现
堆中的每一个节点都满足堆的条件,父节点的关键字要大于所有子节点。
堆是弱序(遍历不适合)
插入:获取一个节点,放入完全二叉树中。与其父节点作比较,替换(完成父节点的关键字要大于子节点)
删除:删除顶端节点,将最后一个叶子节点赋值为顶点节点。然后移动 完成父节点的关键字要大于子节点。
改变节点优先级:将该节点的值更换。然后将它放在合适的位置(完成父节点的关键字要大于子节点)
(父节点的关键字要大于所有子节点,即三个点之间选取最大的与临时父节点替换)

public class Node {
    private int iData;//既是关键字,又是数值
    public Node(int key) {//初始化
        iData=key;
        
    }
    public int getKey() {//访问关键字
        return iData;
    }
    public void setKey(int id) {//改变关键字
        iData=id;
    }

}
//建立堆
public class Heap {
    private Node[] heapArray;//存储节点的数组
    private int maxSize;//总大小
    private int currentSize;//当前堆的大小
    public Heap(int mx) {
        maxSize=mx;//初始化总大小
        currentSize=0;//初始化当前数据大小0
        heapArray=new Node[maxSize];
    }
    //判断是否为空
    public boolean isEmpty() {
        return currentSize==0;
    }
    //增加(判断为满,则不能新增)    
    public boolean insert(int key) {
        if(currentSize==maxSize)
            return false;
        Node newNode=new Node(key);//建立key节点
        heapArray[currentSize]=newNode;//将key节点插入数组的最末
        //(向上调整)完成堆的规则(父节点大于子节点)
        trickleUP(currentSize);
        currentSize++;//增加成功,数量加1
        return true;
    }
    //向上调整(只需要跟父节点做比较就行了,因为开始的时候父节点就是最大值)
    public void trickleUP(int index) {
        //取父节点
        int parent=(index-1)/2;
        //比较,交换
        Node bottom=heapArray[index];
        while(index>0 && heapArray[parent].getKey()<bottom.getKey())
        {//寻找需要替换的位置
            heapArray[index]=heapArray[parent];
            index=parent;
            parent=(parent-1)/2;
            
        }
        heapArray[index]=bottom;
    }
    //删除(删除根,将最后一个数据项移到根上,然后做调整)
    public Node remove() {
        Node root=heapArray[0];
        heapArray[0]=heapArray[--currentSize];//将最后一个数据项移到根上
        //向下调整
        trickleDown(0);
        return root;
        
        
    }
    //向下调整
    public void trickleDown(int index) {
        int largeChild;//记录大的子节点
        Node top=heapArray[index];
        while(index<currentSize/2) {//指针到了最后一层才停止循环
            int leftChild=2*index+1;//左子节点
            int rightChile=leftChild+1;    //右子节点
            if(rightChile<currentSize && heapArray[leftChild].getKey()<heapArray[rightChile].getKey())//有右子节点
                largeChild=rightChile;
            else
                largeChild=leftChild;
            if(top.getKey()>=heapArray[largeChild].getKey())
                break;
            heapArray[index]=heapArray[largeChild];//将大的关键字调整
            index=largeChild;
            
        }
        //最后定位Node top=heapArray[index]
        heapArray[index]=top;
        
    }
    //更改关键字
    public boolean change(int index, int newValue) {
        if(index<0 || index >=currentSize)
            return false;//非正常索引
        int oldValue=heapArray[index].getKey();
        heapArray[index].setKey(newValue);//改变数据项
        //如果新的数据项大于旧的数据项,就向上调整。如果小于旧的数据项,就向下调整
        if(oldValue<newValue) {
            trickleUP(index);
        }else
            trickleDown(index);
        return true;
        
    }
    //显示堆
    public void displayHeap() {
        //以数组的方式
        System.out.println("堆数组");
        for(int m=0;m<currentSize;m++)
            if(heapArray[m]!=null)
                System.out.print(heapArray[m].getKey()+" ");
            else
                System.out.print("-- ");
        System.out.println();
        //以树状的形式
        int nBlanks=32;//控制空格
        int itemsPerRow=1;//当前层的个数
        int column=0;//当前层的数量
        int j=0;
        String dots="...............................";
        System.out.println(dots+dots);
        while(currentSize>0) {
            if(column==0) {
                for(int k=0;k<nBlanks;k++)
                    System.out.print(‘ ‘);
            }
            System.out.print(heapArray[j].getKey());
            if(++j==currentSize)//全部打印完成
                break;
            if(++column==itemsPerRow) {//当前层打印完
                nBlanks/=2;
                itemsPerRow*=2;
                column=0;
                System.out.println();
            }else
                for(int k=0;k<nBlanks*2-2;k++)
                    System.out.print(‘ ‘);
                
        }
        
        System.out.println("\n"+dots+dots);
        
    }
    
    

}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {
    public static void main(String[] agrs) throws IOException{
        int value,value2;
        Heap theHeap =new Heap(31);
        boolean success;
        theHeap.insert(70);
        theHeap.insert(40);
        theHeap.insert(50);
        theHeap.insert(20);
        theHeap.insert(60);
        theHeap.insert(100);
        theHeap.insert(80);
        theHeap.insert(30);
        theHeap.insert(10);
        theHeap.insert(90);
        while(true) {
            System.out.println("Enter first letter of show ,insert,remove,change:");
            int choice=getChar();
            switch(choice){
                case ‘s‘:
                    theHeap.displayHeap();
                    break;
                case ‘i‘:
                    System.out.print("enter value");
                    value=getInt();
                    success=theHeap.insert(value);
                    if(!success)
                        System.out.println("man le");
                    break;
                case ‘r‘:
                    if(!theHeap.isEmpty())
                        theHeap.remove();
                    else
                        System.out.println("不能删除");
                    break;
                case ‘c‘:
                    System.out.println("输入要改变的索引");
                    value=getInt();
                    System.out.println("输入要改变的值");
                    value2=getInt();
                    success=theHeap.change(value, value2);
                    if(!success)
                        System.out.println("无效的索引");
                    break;
                default :
                        System.out.println("无效的输入");
                    
            }
                    
        }
        
    }
    public static String getString() throws IOException{
        InputStreamReader isr=new InputStreamReader(System.in);
        BufferedReader br=new BufferedReader(isr);
        return br.readLine();
    }
    public static char getChar() throws IOException{
        return getString().charAt(0);
    }
    public static int getInt() throws IOException{
        return Integer.parseInt(getString());
    }

}

 

以上是关于堆(插入删除)的主要内容,如果未能解决你的问题,请参考以下文章

(透彻理解)最精锐代码::堆的三种基本操作新建-插入-删除

正确地将片段插入和删除到 viewpager

最小堆的建立 插入 与删除

堆(插入删除)

时间复杂度最小的堆插入和删除

堆+建堆插入删除排序+java实现