zoukankan      html  css  js  c++  java
  • 堆(插入删除)

    用堆实现优先级队列,插入和删除都很快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("
    "+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());
        }
    
    }
  • 相关阅读:
    vue实现简单的点击切换颜色
    Controller层注解详解
    分布式数据库系统的透明性概念
    utf8和utf8mb64的关系
    数据库设计的四个阶段
    IDEA自定义启动图
    编译过程划分
    Linux 之 CentOS 7 安装Tomcat9
    Linux 之 CentOS 7 安装JDK1.8
    Linux 之 CentOS 7安装MySQL5.7
  • 原文地址:https://www.cnblogs.com/S-Mustard/p/7710705.html
Copyright © 2011-2022 走看看