zoukankan      html  css  js  c++  java
  • Java堆和优先队列

    普通队列:先进先出,后进后出

    优先队列:出队顺序和入队顺序无关,和优先级相关。

    堆中某个节点的值总是不对于其父节点的值,最大堆。

    public class Array<E> {
    
        private E[] data;
        private int size;
    
        // 构造函数,传入数组的容量capacity构造Array
        public Array(int capacity){
            data = (E[])new Object[capacity];
            size = 0;
        }
    
        // 无参数的构造函数,默认数组的容量capacity=10
        public Array(){
            this(10);
        }
    
        public Array(E[] arr){
        	data=(E[])new Object[arr.length];
        	for(int i=0;i<arr.length;i++)
        		data[i]=arr[i];
        	size=arr.length;
        }
        // 获取数组的容量
        public int getCapacity(){
            return data.length;
        }
    
        // 获取数组中的元素个数
        public int getSize(){
            return size;
        }
    
        // 返回数组是否为空
        public boolean isEmpty(){
            return size == 0;
        }
    
        // 在index索引的位置插入一个新元素e
        public void add(int index, E e){
    
            if(index < 0 || index > size)
                throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size.");
    
            if(size == data.length)
                resize(2 * data.length);
    
            for(int i = size - 1; i >= index ; i --)
                data[i + 1] = data[i];
    
            data[index] = e;
    
            size ++;
        }
    
        // 向所有元素后添加一个新元素
        public void addLast(E e){
            add(size, e);
        }
    
        // 在所有元素前添加一个新元素
        public void addFirst(E e){
            add(0, e);
        }
    
        // 获取index索引位置的元素
        public E get(int index){
            if(index < 0 || index >= size)
                throw new IllegalArgumentException("Get failed. Index is illegal.");
            return data[index];
        }
    
        // 修改index索引位置的元素为e
        public void set(int index, E e){
            if(index < 0 || index >= size)
                throw new IllegalArgumentException("Set failed. Index is illegal.");
            data[index] = e;
        }
    
        // 查找数组中是否有元素e
        public boolean contains(E e){
            for(int i = 0 ; i < size ; i ++){
                if(data[i].equals(e))
                    return true;
            }
            return false;
        }
    
        // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
        public int find(E e){
            for(int i = 0 ; i < size ; i ++){
                if(data[i].equals(e))
                    return i;
            }
            return -1;
        }
    
        // 从数组中删除index位置的元素, 返回删除的元素
        public E remove(int index){
            if(index < 0 || index >= size)
                throw new IllegalArgumentException("Remove failed. Index is illegal.");
    
            E ret = data[index];
            for(int i = index + 1 ; i < size ; i ++)
                data[i - 1] = data[i];
            size --;
            data[size] = null; // loitering objects != memory leak
    
            if(size == data.length / 4 && data.length / 2 != 0)
                resize(data.length / 2);
            return ret;
        }
    
        // 从数组中删除第一个元素, 返回删除的元素
        public E removeFirst(){
            return remove(0);
        }
    
        // 从数组中删除最后一个元素, 返回删除的元素
        public E removeLast(){
            return remove(size - 1);
        }
    
        // 从数组中删除元素e
        public void removeElement(E e){
            int index = find(e);
            if(index != -1)
                remove(index);
        }
        //交换i和j所在元素的位置
        public void swap(int i,int j){
        	if(i<0||i>=size||j<0||j>=size)
        		throw new IllegalArgumentException("Index is illegal.");
        	E t=data[i];
        	data[i]=data[j];
        	data[j]=t;
        }
    
        @Override
        public String toString(){
    
            StringBuilder res = new StringBuilder();
            res.append(String.format("Array: size = %d , capacity = %d
    ", size, data.length));
            res.append('[');
            for(int i = 0 ; i < size ; i ++){
                res.append(data[i]);
                if(i != size - 1)
                    res.append(", ");
            }
            res.append(']');
            return res.toString();
        }
    
        // 将数组空间的容量变成newCapacity大小
        private void resize(int newCapacity){
    
            E[] newData = (E[])new Object[newCapacity];
            for(int i = 0 ; i < size ; i ++)
                newData[i] = data[i];
            data = newData;
        }
    }
    

      

    package MaxHeap;
    
    public class MaxHeap<E extends Comparable<E>>{
    	private Array<E> data;
    	public MaxHeap(int capacity){
    		data=new Array<>(capacity);
    	}
    
    	public MaxHeap(){
    		data=new Array<>();
    	}
    	public MaxHeap(E[] arr){
    		data=new Array<>(arr);
    		for(int i=parent(arr.length-1);	i>=0;i--)
    			siftDown(i);
    	}
    	//返回堆中的元素
    	public int size(){
    		return data.getSize();
    	}
    	//返回一个布尔值,表示堆中是否为空
    	public boolean isEmpty(){
    		return data.isEmpty();
    	}
    	//返回完全二叉树的数组表示中,一个索引表示的元素的父节点的索引
    	private int parent(int index){
    		if(index==0)
    			throw new IllegalArgumentException("index-0 doesn't hava parent.");
    		return (index -1)/2;
    	}
    	//返回完全二叉树的数组表示中,一个索引表示的元素的左孩子节点的索引
    	private int leftChild(int index){
    		return index*2+1;
    	}
    	//返回完全二叉树的数组表示中,一个索引表示的元素的右孩子节点的索引
    	private int rightChild(int index){
    		return index*2+2;
    	}
    	//向堆中添加元素
    	public void add(E e){
    		data.addLast(e);
    		siftUp(data.getSize()-1);  //最后一个索引
    	}
    	private void siftUp(int k){
    		while(k>0&&data.get(parent(k)).compareTo(data.get(k))<0){//key所在的父亲元素和key元素进行比较
    			data.swap(k, parent(k));
    			k=parent(k);
    		}
    	}
    	//看堆中的最大元素
    	public E findMax(){
    		if(data.getSize()==0)
    			throw new IllegalArgumentException("Can not findMax when heap is empty.");
    		return data.get(0);
    	}
    	
    	//取出堆中最大元素
    	public E extractMax(){
    		E ret=findMax();
    		data.swap(0, data.getSize()-1);
    		data.removeLast();
    		siftDown(0);
    		return ret;
    	}
    	private void siftDown(int k){
    		while(leftChild(k)<data.getSize()){
    			int j=leftChild(k);
    			if(j+1<data.getSize()
    					&&data.get(	j+1).compareTo(data.get(j))>0)
    				j=rightChild(k);
    			//data[j] 是leftChild和rightChild中最大值
    			if(data.get(k).compareTo(data.get(j))>=0)
    				break;
    			data.swap(k, j);
    			k=j;
    		}
    	}
        
    	//取出堆中的最大元素,并且替换成元素e
    	public E replace(E e){
    		E ret=findMax();
    		data.set(0,e);
    		siftDown(0);
    		return ret;
    	}
    	//heapify:将任意数组整理成堆的形状
    	
    }
    

      测试

    package MaxHeap;
    
    import java.util.Random;
    
    public class Main {
    	private static double testHeap(Integer[] testData,boolean isHeapify){
    		long startTime=System.nanoTime();
    		MaxHeap<Integer> maxHeap;
    		if(isHeapify)
    			maxHeap=new MaxHeap<>(testData);
    		else {
    			maxHeap=new MaxHeap<>();
    			for(int num:testData)
    				maxHeap.add(num);
    		}
    		int[] arr = new int[testData.length];
    		for (int i = 0; i < testData.length; i++)
    			arr[i] = maxHeap.extractMax();
    		for (int i = 1; i < testData.length; i++)
    			if (arr[i - 1] < arr[i])
    				throw new IllegalArgumentException("Error");
    		System.out.println("Test MaxHeap completed");
    		long endTime=System.nanoTime();
    		return(endTime-startTime)/1000000000.0;
    	}
       public static void main(String[] args){
    	   int n=100000;
    	   MaxHeap<Integer> maxHeap=new MaxHeap<>();
    	   Random random=new Random();
    	   Integer[] testData=new Integer[n];
    	   for(int i=0;i<n;i++)
    		   testData[i]=random.nextInt(Integer.MAX_VALUE);
    	   
    	   double time1=testHeap(testData, false);
    	   System.out.println("Without heapify:"+time1+"s");
    	   
    	   double time2=testHeap(testData, true);
    	   System.out.println("With heapify:"+time2+"s");
    	   
    //	   for(int i=0;i<n;i++)
    //		   maxHeap.add(random.nextInt(Integer.MAX_VALUE));
    	   
    //	   int[] arr=new int[n];
    //	   for(int i=0;i<n;i++)
    //		   arr[i]=maxHeap.extractMax();
    //	   for(int i=1;i<n;i++)
    //		   if(arr[i-1]<arr[i])
    //			   throw new IllegalArgumentException("Error");
    //	   System.out.println("Test MaxHeap completed");
       }
    }
    

      

     给定一个非空整数的数组,返回其中出现频率前k高的元素

    public interface Queue <E>{
        int getSize();
        boolean isEmpty();
        void enqueue(E e);
        E dequeue();
        E getFront();	
    }
    

      

    package MaxHeap;
    
    public class PriorityQueue<E extends Comparable<E>> implements Queue<E> {
        private MaxHeap<E> maxHeap;
        public PriorityQueue(){
        	maxHeap=new MaxHeap<>();
        }
        @Override
        public int getSize(){
        	return maxHeap.size();
        }
        @Override
        public boolean isEmpty(){
        	return maxHeap.isEmpty();
        }
        @Override
        public E getFront(){
        	return maxHeap.findMax();
        }
        @Override
        public void enqueue(E e){
        	maxHeap.add(e);
        }
        @Override
        public E dequeue(){
        	return maxHeap.extractMax();
        }
    }
    

      

    package MaxHeap;
    
    import java.util.LinkedList;
    import java.util.List;
    import java.util.TreeMap;
    
    public class Solution {
    	private class Freq implements Comparable<Freq>{
    		public int e,freq;
    		public  Freq(int e,int freq) {
    			this.e=e;
    			this.freq=freq;
    		}
    		@Override
    		public int compareTo(Freq another){
    			if( this.freq<another.freq)
    				return 1;
    			else if(this.freq>another.freq)
    				return -1;
    			else return 0;
    		}
    	}
        public  List<Integer> topKFrequent(int[] nums,int k){
        	TreeMap<Integer, Integer> map=new TreeMap<>();
        	for(int num:nums){
        		if(map.containsKey(num))
        			map.put(num, map.get(num)+1);
        		else 
        			map.put(num, 1);
        	}
        	PriorityQueue<Freq>	pq=new PriorityQueue<>();
        	for(int key:map.keySet()){
        		if(pq.getSize()<k)
        			pq.enqueue(new Freq(key, map.get(key)));
        		else if(map.get(key)>pq.getFront().freq){
        			pq.dequeue();
        			pq.enqueue(new Freq(key, map.get(key)));
        		}	
        	}
        	LinkedList<Integer> res=new LinkedList<>();
            while (! pq.isEmpty())
            	res.add(pq.dequeue().e);
            return res;
        }
    }
    

      java自定义:

    import java.util.*;
    
    public class Solution5 {
    
        public List<Integer> topKFrequent(int[] nums, int k) {
    
            TreeMap<Integer, Integer> map = new TreeMap<>();
            for(int num: nums){
                if(map.containsKey(num))
                    map.put(num, map.get(num) + 1);
                else
                    map.put(num, 1);
            }
    
            PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
                @Override
                public int compare(Integer a, Integer b) {
                    return map.get(a) - map.get(b);
                }
            });
            PriorityQueue<Integer> pq = new PriorityQueue<>(
                    (a, b) -> map.get(a) - map.get(b)
            );
            for(int key: map.keySet()){
                if(pq.size() < k)
                    pq.add(key);
                else if(map.get(key) > map.get(pq.peek())){
                    pq.remove();
                    pq.add(key);
                }
            }
    
            LinkedList<Integer> res = new LinkedList<>();
            while(!pq.isEmpty())
                res.add(pq.remove());
            return res;
        }
    
        private static void printList(List<Integer> nums){
            for(Integer num: nums)
                System.out.print(num + " ");
            System.out.println();
        }
    
        public static void main(String[] args) {
    
            int[] nums = {1, 1, 1, 2, 2, 3};
            int k = 2;
            printList((new Solution()).topKFrequent(nums, k));
        }
    }
    

      

  • 相关阅读:
    XAML学习笔记之Layout(五)——ViewBox
    XAML学习笔记——Layout(三)
    XAML学习笔记——Layout(二)
    XAML学习笔记——Layout(一)
    从0开始搭建SQL Server 2012 AlwaysOn 第三篇(安装数据,配置AlwaysOn)
    从0开始搭建SQL Server 2012 AlwaysOn 第二篇(配置故障转移集群)
    从0开始搭建SQL Server 2012 AlwaysOn 第一篇(AD域与DNS)
    Sql Server 2012 事务复制遇到的问题及解决方式
    Sql Server 2008R2升级 Sql Server 2012 问题
    第一次ACM
  • 原文地址:https://www.cnblogs.com/sunliyuan/p/10706511.html
Copyright © 2011-2022 走看看