java源码分析-优先队列
2015-11-19 09:14
691 查看
愿她好!
优先队列PriorityQueue
2.优先队列分析
主要是怎么确定优先级
首先我们来看下add(E)方法
从上述代码可以看出:第一,add方法实际上是调用offer方法;第二,加入的元素不能为空,都在抛出空指向异常,这类问题在有序的集合中都会存在;第三,若队列满了,则采用grow方法扩容;第四,通过siftUp来重整队列,如果没有从外部传入比较器,采用siftUpUsingComparator方法来重整;否则,利用传入的比较器以及siftUpComparable来重整队列。
怎么比较优先级的?以自带的比较器为例子
关键代码在于parent的确定:int parent=(k-1)>>>1; 不断地找到中值,并利用比较器比较,直到比较器判断为true
java中有三种移位运算符
<< : 左移运算符,num << 1,相当于num乘以2
>> : 右移运算符,num >> 1,相当于num除以2
>>> : 无符号右移,忽略符号位,空位都以0补齐
无符号右移的规则只记住一点:忽略了符号位扩展,0补最高位 无符号右移运算符>>> 只是对32位和64位的值有意义
扩容
分为两种情况:如果原有容量小于64,扩容方式为加倍再加2;否则,每次增加原有容量的一半
最大容量
数组可能保留一些特殊字段
查找
poll方法说明:第一,首先判断size是否为0;其次,弹出下标为0的元素,然后将下标为size-1的值放入下标为0的地方,并且重新排序
优先队列PriorityQueue
1.类结构
2.优先队列分析
主要是怎么确定优先级
首先我们来看下add(E)方法
public boolean add(E e) { return offer(e); }
public boolean offer(E e) { if (e == null) throw new NullPointerException(); modCount++; int i = size; if (i >= queue.length) grow(i + 1); size = i + 1; if (i == 0) queue[0] = e; else siftUp(i, e); return true; }
private void siftUp(int k, E x) { if (comparator != null) siftUpUsingComparator(k, x); else siftUpComparable(k, x); }
private void siftUpComparable(int k, E x) { Comparable<? super E> key = (Comparable<? super E>) x; while (k > 0) { int parent = (k - 1) >>> 1; Object e = queue[parent]; if (key.compareTo((E) e) >= 0) break; queue[k] = e; k = parent; } queue[k] = key; } private void siftUpUsingComparator(int k, E x) { while (k > 0) { int parent = (k - 1) >>> 1; Object e = queue[parent]; if (comparator.compare(x, (E) e) >= 0) break; queue[k] = e; k = parent; } queue[k] = x; }
从上述代码可以看出:第一,add方法实际上是调用offer方法;第二,加入的元素不能为空,都在抛出空指向异常,这类问题在有序的集合中都会存在;第三,若队列满了,则采用grow方法扩容;第四,通过siftUp来重整队列,如果没有从外部传入比较器,采用siftUpUsingComparator方法来重整;否则,利用传入的比较器以及siftUpComparable来重整队列。
怎么比较优先级的?以自带的比较器为例子
关键代码在于parent的确定:int parent=(k-1)>>>1; 不断地找到中值,并利用比较器比较,直到比较器判断为true
java中有三种移位运算符
<< : 左移运算符,num << 1,相当于num乘以2
>> : 右移运算符,num >> 1,相当于num除以2
>>> : 无符号右移,忽略符号位,空位都以0补齐
无符号右移的规则只记住一点:忽略了符号位扩展,0补最高位 无符号右移运算符>>> 只是对32位和64位的值有意义
扩容
private void grow(int minCapacity) { int oldCapacity = queue.length; // Double size if small; else grow by 50% int newCapacity = oldCapacity + ((oldCapacity < 64) ? (oldCapacity + 2) : (oldCapacity >> 1)); // overflow-conscious code if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); queue = Arrays.copyOf(queue, newCapacity); }
分为两种情况:如果原有容量小于64,扩容方式为加倍再加2;否则,每次增加原有容量的一半
最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
数组可能保留一些特殊字段
查找
public E peek() { if (size == 0) return null; return (E) queue[0]; }
private int indexOf(Object o) { if (o != null) { for (int i = 0; i < size; i++) if (o.equals(queue[i])) return i; } return -1; }
public E poll() { if (size == 0) return null; int s = --size; modCount++; E result = (E) queue[0]; E x = (E) queue[s]; queue[s] = null; if (s != 0) siftDown(0, x); return result; }
poll方法说明:第一,首先判断size是否为0;其次,弹出下标为0的元素,然后将下标为size-1的值放入下标为0的地方,并且重新排序
private void siftDown(int k, E x) { if (comparator != null) siftDownUsingComparator(k, x); else siftDownComparable(k, x); } private void siftDownComparable(int k, E x) { Comparable<? super E> key = (Comparable<? super E>)x; int half = size >>> 1; // loop while a non-leaf while (k < half) { int child = (k << 1) + 1; // assume left child is least Object c = queue[child]; int right = child + 1; if (right < size && ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0) c = queue[child = right]; if (key.compareTo((E) c) <= 0) break; queue[k] = c; k = child; } queue[k] = key; } private void siftDownUsingComparator(int k, E x) { int half = size >>> 1; while (k < half) { int child = (k << 1) + 1; Object c = queue[child]; int right = child + 1; if (right < size && comparator.compare((E) c, (E) queue[right]) > 0) c = queue[child = right]; if (comparator.compare(x, (E) c) <= 0) break; queue[k] = c; k = child; } queue[k] = x; }
相关文章推荐
- MyEclipse 8.5 注册--取消MyEclipse Trial Expired解决办法
- Java正则表达式
- Myeclipse10注册码
- Spring 使用注解集成Log
- java学习笔记#从控制台输入整数,输出最大最小值,直到输入0结束
- 浅谈 java中ArrayList、Vector、LinkedList的区别联系
- 迅速掌握Java容器中常用的ArrayList类与Vector类用法
- Myeclipse中使用Myeclipse Hibernate工作模式创建数据库连接详细流程
- Java API(一)
- 【并发编程】Java中断机制——协作式中断含义及应用
- 笔试题(2)【Java 】
- Java 基础入门随笔(9) JavaSE版——文档注释
- Java String是不可变的(immutable)
- java Process 流导致的错误
- Quartz使用-入门使用(java定时任务实现)
- Java内存模型解惑--观深入理解Java内存模型系列文章有感(二)
- Java基础03 构造器与方法重载
- clojure引入另一个clojure实现的Java类
- JAVA知识回顾-2(四种引用、HashCode、List实现类的区别、字符的处理、各集合特点)
- 10016---JavaWeb基础--JSP指令