Dijkstra’s shortest path algorithm
思路:将顶点集分为两部分。集合 V1 表示已计算出到源顶点最短距离的顶点的集合,集合 V2 表示尚未计算出到源顶点最短距离的顶点的集合。
V1 初始化为源顶点S。算法每次从 V2 中选择一个顶点加入 V1 中,同时保持 V1 集合的性质: V1 中每个顶点都已知其到源顶点S的最短路径。 则经过 N−1 次循环, V1 = V , V2 = ∅ 算法终止。
每一次循环是依据什么来从 V2 中选择顶点加入 V1 的呢?
依据是首先找出所有的那些边( v , w ) ∈ E ,满足 v∈V1 且 w∈V2 , 再从这些边中找出使得 A[ v ] + lvw 最小的那条边( v∗ , w∗ ) , 将 w∗ 从 V2 中取出,加入 V1 。并计算:
A[ w∗ ] = A[ v∗ ] + lv∗w∗ .
B[ w∗ ] = B[ v∗ ] ∪ ( v∗ , w∗ ).
Heap
A heap is a container for a bunch of objects. And each of the objects should have a key, so that you can compare two objects.
Here we discuss about min heap.
Operations
Heap can support two basic operations:
- insertion : add a new object into a heap.
running time: O(logn) - extract_min: remove an object in heap with a minimum key value.[ties broken arbitrarily]
running time: O(logn) , n is the number of objects in heap.
Also, heap supports:
- heapify : initialize a heap in linear time O(n) .
- Delete : delete an arbitrary element from the heap in logarithmic time. O(logn) .
Canonical use of heap
fast way to do repeated minimum computations.
heap sort :
- insert all n array elements into a heap
- extract min to pluck out elements in sorted order.
running time: 2n heap operations = O(nlog(n)) time.
Optimal for a “comparison-based” sorting algorithm.
priority queue
median maintenance(use a max heap and a min heap)
Input: a sequance x1 , ⋯ , xn of numbers, one by one.
Output: at each time stamp i, the median of { x1,⋯,xi }.
Solution: Maintain two heaps:
Hlow:supportextractMax
Hhigh:supportextractMin
Key Idea: Maintain invariant that about
i2 smallest(largest) elements in
Hlow(Hhigh) .
Code in java
/** * <p>Description: The main procedure of the median maintenance algorithm</p> * <p> Compute the median of first i elements in the array, i range from 1 to array length.</p> * <p> The medians is stored in an array:m_medians. */
public void medianMaintenance(){
//initialize heap and median array
m_lowHeap = new PriorityQueue<Integer>();
m_highHeap = new PriorityQueue<Integer>();
m_medians = new int[m_array.length];
for(int i = 0; i < m_array.length; i ++){
if(m_lowHeap.isEmpty() || m_array[i] <= -m_lowHeap.peek()){
m_lowHeap.add(- m_array[i]);
//adjust heap
if(m_lowHeap.size() - m_highHeap.size() >= 2){
int max = - m_lowHeap.remove();
m_highHeap.add(max);
}
}
else if(m_highHeap.isEmpty() || m_array[i] > m_lowHeap.peek()){
m_highHeap.add(m_array[i]);
//adjust heap
if(m_highHeap.size() - m_lowHeap.size() >= 2){
int min = m_highHeap.remove();
m_lowHeap.add(-min);
}
}
//get median
int median;
if(m_lowHeap.size() == m_highHeap.size())
median = - m_lowHeap.peek();//caution for minus.
else if(m_lowHeap.size() > m_highHeap.size())
median = - m_lowHeap.peek();
else
median = m_highHeap.peek();
m_medians[i] = median;
}
}
Speeding up Dijkstra
Key Idea: store the vertex in a heap basing on each vertex’s distance to the source vertex. Each time pop a vertex(say w ) from the heap, add it to the chosen set. And adjust all the vertices in heap that connect with w . Loop until the heap is empty.
The heap property
conceptually : think of a heap as a tree.
– rooted, binary, as complete as possible.
heap property: at every node x , key[ x ] ≤ all keys of x′ children.
array implementation
references
[1] coursera standford algorithm part I