import java.util.ArrayList;
import java.util.List;
publicclassEdgeWeightedGraph
{privatestaticfinal String NEWLINE = System.getProperty("line.separator");
privatefinalint V;
privateint E;
private List<Edge>[] adj;
@SuppressWarnings("unchecked")
publicEdgeWeightedGraph(int V)
{
if (V < 0)
{
thrownew IllegalArgumentException("顶点数必须是非负数");
}
this.V = V;
this.E = 0;
adj = (List<Edge>[]) new ArrayList[V];
for (int v = 0; v < V; v++)
{
adj[v] = new ArrayList<Edge>();
}
}
publicEdgeWeightedGraph(EdgeWeightedGraph G)
{
this(G.V());
this.E = G.E();
for (int v = 0; v < G.V(); v++)
{
List<Edge> li = new ArrayList<Edge>();
for (Edge e : G.adj[v])
{
li.add(e);
}
for (Edge e : li)
{
adj[v].add(e);
}
}
}
publicintV()
{
return V;
}
publicintE()
{
return E;
}
privatevoidvalidateVertex(int v)
{
if (v < 0 || v >= V)
{
thrownew IllegalArgumentException("顶点序号 " + v + " 不在 0 和 " + (V - 1) + "之间");
}
}
/**
* 添加边到无向非赋权图中
*
* @param e
* @author lhever 2017年2月19日 下午5:34:00
* @since v1.0
*/publicvoidaddEdge(Edge e)
{
int v = e.either();
int w = e.other(v);
validateVertex(v);
validateVertex(w);
adj[v].add(e);
adj[w].add(e);
E++;
}
/**
* 返回顶点v的临接边
*
* @param v
* @return
* @author lhever 2017年2月19日 下午5:35:09
* @since v1.0
*/public Iterable<Edge> adj(int v)
{
validateVertex(v);
return adj[v];
}
/**
* 返回顶点v的度(邻接顶点数)
*
* @param v
* @return
* @author lhever 2017年2月19日 下午5:36:08
* @since v1.0
*/publicintdegree(int v)
{
validateVertex(v);
return adj[v].size();
}
/**
* 返回无向赋权图中的所有边
*
* @return
* @author lhever 2017年2月19日 下午5:38:55
* @since v1.0
*/public Iterable<Edge> edges()
{
List<Edge> list = new ArrayList<Edge>();
for (int v = 0; v < V; v++)
{
int selfLoops = 0;
for (Edge e : adj(v))
{
// 无向图中,同一条边会出现在这条边的两个端点的邻接列表中,此处的条件 > 目的是避免重复查找if (e.other(v) > v)
{
list.add(e);
}
// 对于自环,比如(5, 5, 0.8),添加边的时候会添加两次,但实际上只算一条边,所以此处只添加一条elseif (e.other(v) == v)
{
if (selfLoops % 2 == 0)
{
list.add(e);
}
selfLoops++;
}
}
}
return list;
}
public String toString()
{
StringBuilder s = new StringBuilder();
s.append(V + " " + E + NEWLINE);
for (int v = 0; v < V; v++)
{
s.append(v + ": ");
for (Edge e : adj[v])
{
s.append(e + " ");
}
s.append(NEWLINE);
}
return s.toString();
}
publicstaticvoidmain(String[] args)
{
// 0——————6// /| \ | // / | \ | // / 1 2 | // / | // 5———————————4 // \ / // \ / // \ /// \ /// 3
EdgeWeightedGraph g = new EdgeWeightedGraph(7);
Edge e1 = new Edge(0, 1, 0.7);
g.addEdge(e1);
Edge e2 = new Edge(0, 2, 4.5);
g.addEdge(e2);
Edge e3 = new Edge(0, 5, 5.0);
g.addEdge(e3);
Edge e4 = new Edge(0, 6, 3.1);
g.addEdge(e4);
Edge e5 = new Edge(5, 4, 2.9);
g.addEdge(e5);
Edge e6 = new Edge(6, 4, 7.8);
g.addEdge(e6);
Edge e7 = new Edge(3, 4, 9.7);
g.addEdge(e7);
Edge e8 = new Edge(3, 5, 6.0);
g.addEdge(e8);
System.out.println(g);
EdgeWeightedGraph g1 = new EdgeWeightedGraph(g);
System.out.println(g1);
}
}
3 prim算法的延迟实现(添加新的横切边到树中的时候才能识别出失效的边)
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
/**
* 求无向非赋权图最小生成树的prim算法(延迟实现)
* @author xxx 2017年2月19日 下午6:20:21
* @version v1.0
*/publicclassLazyPrimMST
{privatestaticfinaldouble FLOATING_POINT_EPSILON = 1E-12;
privatedouble weight; // 最小生成树的权重private List<Edge> mst; // 最小生成树的所有边privateboolean[] marked; // 如果顶点v已经被加入到最小生成树中, 则marked[v] = trueprivate PriorityQueue<Edge> pq;
publicLazyPrimMST(EdgeWeightedGraph G)
{
mst = new ArrayList<Edge>();
pq = new PriorityQueue<Edge>();
marked = newboolean[G.V()];
for (int v = 0; v < G.V(); v++)
{
if (!marked[v])
{
prim(G, v);
}
}
assert check(G);
}
privatevoidprim(EdgeWeightedGraph G, int s)
{
scan(G, s);
while (!pq.isEmpty())
{ // 当最小生成树含有v- 1 条边的时候最好停止// 取出权值最小的边
Edge e = pq.poll();
int v = e.either(), w = e.other(v);
assert marked[v] || marked[w];
if (marked[v] && marked[w])
{
continue;
}
mst.add(e); // 边e属于最小生成树的边
weight += e.weight();
// 在运算过程中,最小生成树是逐渐生成的,此处将v添加到当前最小树中if (!marked[v])
{
scan(G, v);
}
// 在运算过程中,最小生成树是逐渐生成的,此处将v添加到当前最小树中if (!marked[w])
{
scan(G, w);
}
}
}
/**
* 将顶点v的所有满足条件的邻接边添加到优先队列中,
* 条件是: 这些邻接边的另外一个顶点还没有添加到当前的最小生成树中(还未被访问)
* @param G
* @param v
* @author xxx 2017年2月19日 下午6:27:26
* @since v1.0
*/privatevoidscan(EdgeWeightedGraph G, int v)
{
assert !marked[v];
marked[v] = true;
for (Edge e : G.adj(v))
{
if (!marked[e.other(v)])
{
pq.add(e);
}
}
}
public Iterable<Edge> edges()
{
return mst;
}
publicdoubleweight()
{
return weight;
}
privatebooleancheck(EdgeWeightedGraph G)
{
// 验证权重是否一致double totalWeight = 0.0;
for (Edge e : edges())
{
totalWeight += e.weight();
}
if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON)
{
System.err.printf("最小生成树的所有边的权值之和与 weight()方法计算的结果不一致: %f vs. %f\n", totalWeight, weight());
returnfalse;
}
// 利用连通查找算法判断是否是无环图
UnionFind UnionFind = new UnionFind(G.V());
for (Edge e : edges())
{
int v = e.either(), w = e.other(v);
if (UnionFind.connected(v, w))
{
System.err.println("不是一个树森林");
returnfalse;
}
UnionFind.union(v, w);
}
// 判断是否是一颗生成树for (Edge e : G.edges())
{
int v = e.either(), w = e.other(v);
if (!UnionFind.connected(v, w))
{
System.err.println("不是一棵生成树");
returnfalse;
}
}
// 判断是否是一棵最小生成树for (Edge e : edges())
{
// 最小生成树中除e以外的所有边
UnionFind = new UnionFind(G.V());
for (Edge f : mst)
{
int x = f.either(), y = f.other(x);
if (f != e)
{
UnionFind.union(x, y);
}
}
// check that e is min weight edge in crossing cutfor (Edge f : G.edges())
{
int x = f.either(), y = f.other(x);
if (!UnionFind.connected(x, y))
{
if (f.weight() < e.weight())
{
System.err.println("边 " + f + "违背了切分条件");
returnfalse;
}
}
}
}
returntrue;
}
publicstaticvoidmain(String[] args)
{
// 0——————6// /| \ | // / | \ | // / 1 2 | // / | // 5———————————4 // \ / // \ / // \ /// \ /// 3
EdgeWeightedGraph g = new EdgeWeightedGraph(7);
Edge e1 = new Edge(0, 1, 0.7);
g.addEdge(e1);
Edge e2 = new Edge(0, 2, 4.5);
g.addEdge(e2);
Edge e3 = new Edge(0, 5, 5.0);
g.addEdge(e3);
Edge e4 = new Edge(0, 6, 3.1);
g.addEdge(e4);
Edge e5 = new Edge(5, 4, 2.9);
g.addEdge(e5);
Edge e6 = new Edge(6, 4, 7.8);
g.addEdge(e6);
Edge e7 = new Edge(3, 4, 9.7);
g.addEdge(e7);
Edge e8 = new Edge(3, 5, 6.0);
g.addEdge(e8);
LazyPrimMST mst = new LazyPrimMST(g);
for (Edge e : mst.edges())
{
System.out.println(e);
}
System.out.printf("%.5f\n", mst.weight());
}
}
///算法中用于连通查找的类的代码如下///import java.util.Arrays;
publicclassUnionFind {privateint[] parent; // parent[i]的值为节点 i的父节点(或根节点)privatebyte[] rank; // rank[i]的值为以i为根节点的子树的秩 privateint count; // 连通分量数/**
* 初始化一个连通-查找算法的数据结构,N表示该数据结构中的节点(或称顶点、或称触电),并且,刚初始化
* 的数据结构中,各个节点都位于各自的连通分量当中,也即N个连通分量
* @param N
* @author xxx 2017年2月28日 上午12:14:48
* @since v1.0
*/publicUnionFind(int N)
{
if (N < 0)
{
thrownew IllegalArgumentException();
}
count = N;
parent = newint[N];
rank = newbyte[N];
for (int i = 0; i < N; i++)
{
parent[i] = i;
rank[i] = 0;
}
}
/**
* 返回包含节点p的连通分量的id(或者是identifier)
* @param p
* @return
* @author xxx 2017年2月28日 上午12:26:19
* @since v1.0
*/publicintfind(int p)
{
validate(p);
while (p != parent[p])
{
parent[p] = parent[parent[p]]; // 路径压缩
p = parent[p];
}
return p;
}
/**
* 返回连通分量的总数
* @return
* @author xxx 2017年2月28日 上午12:21:16
* @since v1.0
*/publicintcount()
{
return count;
}
/**
* 如果节点p和节点q位于同一个连通分量中,则返回true
* @param p
* @param q
* @return
* @author xxx 2017年2月28日 上午12:20:35
* @since v1.0
*/publicbooleanconnected(int p, int q)
{
return find(p) == find(q);
}
/**
* 将包含节点p的连通分量与包含节点q的连通分量合并
* @param p
* @param q
* @author xxx 2017年2月28日 上午12:19:24
* @since v1.0
*/publicvoidunion(int p, int q)
{
int rootP = find(p);
int rootQ = find(q);
if (rootP == rootQ)
{
return;
}
// make root of smaller rank point to root of larger rankif (rank[rootP] < rank[rootQ])
{
parent[rootP] = rootQ;
} elseif (rank[rootP] > rank[rootQ])
{
parent[rootQ] = rootP;
} else
{
parent[rootQ] = rootP;
rank[rootP]++;
}
count--;//合并之后连通分量减一
}
privatevoidvalidate(int p)
{
int N = parent.length;
if (p < 0 || p >= N)
{
thrownew IndexOutOfBoundsException("节点的大小必须位于0和 " + (N - 1) + "之间");
}
}
publicstaticvoidmain(String[] args) {
UnionFind uf = new UnionFind(4);
if(!uf.connected(0, 3)) {
uf.union(0, 3);
}
System.out.println(0 + " " + 3);
System.out.println(uf.count() + " components");
if(!uf.connected(0, 2)) {
uf.union(0, 2);
}
System.out.println(0 + " " + 2);
System.out.println(uf.count() + " components");
System.out.println(Arrays.toString(uf.parent));
}
}
4 Prim算法的即时实现
import java.util.ArrayList;
import java.util.List;
/**
* 无向非赋权图的最小生成树算法
* @author xxx 2017年2月19日 下午7:43:11
* @version v1.0
*/publicclassPrimMST {privatestaticfinaldouble FLOATING_POINT_EPSILON = 1E-12;
private Edge[] edgeTo;
privatedouble[] distTo;
privateboolean[] marked;
private IndexMinPQ<Double> pq;
publicPrimMST(EdgeWeightedGraph G)
{
edgeTo = new Edge[G.V()];
distTo = newdouble[G.V()];
marked = newboolean[G.V()];
pq = new IndexMinPQ<Double>(G.V());
for (int v = 0; v < G.V(); v++)
{
distTo[v] = Double.POSITIVE_INFINITY;
}
for (int v = 0; v < G.V(); v++)
{
if (!marked[v])
{
prim(G, v);
}
}
assert check(G);
}
privatevoidprim(EdgeWeightedGraph G, int s)
{
distTo[s] = 0.0;
pq.insert(s, distTo[s]);
while (!pq.isEmpty())
{
int v = pq.delMin();
scan(G, v);
}
}
privatevoidscan(EdgeWeightedGraph G, int v)
{
marked[v] = true;
for (Edge e : G.adj(v))
{
int w = e.other(v);
if (marked[w]) {
continue; // v-w is obsolete edge
}
if (e.weight() < distTo[w])
{
distTo[w] = e.weight();
edgeTo[w] = e;
if (pq.contains(w)) {
pq.decreaseKey(w, distTo[w]);
}
else {
pq.insert(w, distTo[w]);
}
}
}
}
public Iterable<Edge> edges()
{
List<Edge> mst = new ArrayList<Edge>();
for (int v = 0; v < edgeTo.length; v++)
{
Edge e = edgeTo[v];
if (e != null)
{
mst.add(e);
}
}
return mst;
}
publicdoubleweight()
{
double weight = 0.0;
for (Edge e : edges())
{
weight += e.weight();
}
return weight;
}
privatebooleancheck(EdgeWeightedGraph G)
{
double totalWeight = 0.0;
for (Edge e : edges())
{
totalWeight += e.weight();
}
if (Math.abs(totalWeight - weight()) > FLOATING_POINT_EPSILON)
{
System.err.printf("最小生成树中所有边的权值和与weight()方法计算结果不一致");
returnfalse;
}
UnionFind UnionFind = new UnionFind(G.V());
for (Edge e : edges())
{
int v = e.either(), w = e.other(v);
if (UnionFind.connected(v, w))
{
System.err.println("不是一个树森林");
returnfalse;
}
UnionFind.union(v, w);
}
for (Edge e : G.edges())
{
int v = e.either(), w = e.other(v);
if (!UnionFind.connected(v, w))
{
System.err.println("不是最小生成树");
returnfalse;
}
}
for (Edge e : edges())
{
UnionFind = new UnionFind(G.V());
for (Edge f : edges())
{
int x = f.either(), y = f.other(x);
if (f != e)
{
UnionFind.union(x, y);
}
}
for (Edge f : G.edges())
{
int x = f.either(), y = f.other(x);
if (!UnionFind.connected(x, y))
{
if (f.weight() < e.weight())
{
System.err.println("边 " + f + " 违背了切分定理");
returnfalse;
}
}
}
}
returntrue;
}
publicstaticvoidmain(String[] args)
{
// 0——————6// /| \ | // / | \ | // / 1 2 | // / | // 5———————————4 // \ / // \ / // \ /// \ /// 3
EdgeWeightedGraph g = new EdgeWeightedGraph(7);
Edge e1 = new Edge(0, 1, 0.7);
g.addEdge(e1);
Edge e2 = new Edge(0, 2, 4.5);
g.addEdge(e2);
Edge e3 = new Edge(0, 5, 5.0);
g.addEdge(e3);
Edge e4 = new Edge(0, 6, 3.1);
g.addEdge(e4);
Edge e5 = new Edge(5, 4, 2.9);
g.addEdge(e5);
Edge e6 = new Edge(6, 4, 7.8);
g.addEdge(e6);
Edge e7 = new Edge(3, 4, 9.7);
g.addEdge(e7);
Edge e8 = new Edge(3, 5, 6.0);
g.addEdge(e8);
PrimMST mst = new PrimMST(g);
for (Edge e : mst.edges())
{
System.out.println(e);
}
System.out.printf("%.5f\n", mst.weight());
}
}
///算法中使用到的IndexMinPQ.java代码如下//import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* The <tt>IndexMinPQ</tt> class represents an indexed priority queue of generic keys.
* It supports the usual <em>insert</em> and <em>delete-the-minimum</em>
* operations, along with <em>delete</em> and <em>change-the-key</em>
* methods. In order to let the client refer to keys on the priority queue,
* an integer between 0 and maxN-1 is associated with each key—the client
* uses this integer to specify which key to delete or change.
* It also supports methods for peeking at the minimum key,
* testing if the priority queue is empty, and iterating through
* the keys.
* <p>
* This implementation uses a binary heap along with an array to associate
* keys with integers in the given range.
* The <em>insert</em>, <em>delete-the-minimum</em>, <em>delete</em>,
* <em>change-key</em>, <em>decrease-key</em>, and <em>increase-key</em>
* operations take logarithmic time.
* The <em>is-empty</em>, <em>size</em>, <em>min-index</em>, <em>min-key</em>, and <em>key-of</em>
* operations take constant time.
* Construction takes time proportional to the specified capacity.
* <p>
* For additional documentation, see <a href="http://algs4.cs.princeton.edu/24pq">Section 2.4</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*
* @param <Key> the generic type of key on this priority queue
*/publicclassIndexMinPQ<KeyextendsComparable<Key>> implementsIterable<Integer> {privateint maxN; // maximum number of elements on PQprivateint N; // number of elements on PQprivateint[] pq; // binary heap using 1-based indexingprivateint[] qp; // inverse of pq - qp[pq[i]] = pq[qp[i]] = iprivate Key[] keys; // keys[i] = priority of i/**
* Initializes an empty indexed priority queue with indices between <tt>0</tt>
* and <tt>maxN - 1</tt>.
* @param maxN the keys on this priority queue are index from <tt>0</tt>
* <tt>maxN - 1</tt>
* @throws IllegalArgumentException if <tt>maxN</tt> < <tt>0</tt>
*/publicIndexMinPQ(int maxN) {
if (maxN < 0) thrownew IllegalArgumentException();
this.maxN = maxN;
keys = (Key[]) new Comparable[maxN + 1]; // make this of length maxN??
pq = newint[maxN + 1];
qp = newint[maxN + 1]; // make this of length maxN??for (int i = 0; i <= maxN; i++)
qp[i] = -1;
}
/**
* Returns true if this priority queue is empty.
*
* @return <tt>true</tt> if this priority queue is empty;
* <tt>false</tt> otherwise
*/publicbooleanisEmpty() {
return N == 0;
}
/**
* Is <tt>i</tt> an index on this priority queue?
*
* @param i an index
* @return <tt>true</tt> if <tt>i</tt> is an index on this priority queue;
* <tt>false</tt> otherwise
* @throws IndexOutOfBoundsException unless 0 ≤ <tt>i</tt> < <tt>maxN</tt>
*/publicbooleancontains(int i) {
if (i < 0 || i >= maxN) thrownew IndexOutOfBoundsException();
return qp[i] != -1;
}
/**
* Returns the number of keys on this priority queue.
*
* @return the number of keys on this priority queue
*/publicintsize() {
return N;
}
/**
* Associates key with index <tt>i</tt>.
*
* @param i an index
* @param key the key to associate with index <tt>i</tt>
* @throws IndexOutOfBoundsException unless 0 ≤ <tt>i</tt> < <tt>maxN</tt>
* @throws IllegalArgumentException if there already is an item associated
* with index <tt>i</tt>
*/publicvoidinsert(int i, Key key) {
if (i < 0 || i >= maxN) thrownew IndexOutOfBoundsException();
if (contains(i)) thrownew IllegalArgumentException("index is already in the priority queue");
N++;
qp[i] = N;
pq[N] = i;
keys[i] = key;
swim(N);
}
/**
* Returns an index associated with a minimum key.
*
* @return an index associated with a minimum key
* @throws NoSuchElementException if this priority queue is empty
*/publicintminIndex() {
if (N == 0) thrownew NoSuchElementException("Priority queue underflow");
return pq[1];
}
/**
* Returns a minimum key.
*
* @return a minimum key
* @throws NoSuchElementException if this priority queue is empty
*/public Key minKey() {
if (N == 0) thrownew NoSuchElementException("Priority queue underflow");
return keys[pq[1]];
}
/**
* Removes a minimum key and returns its associated index.
* @return an index associated with a minimum key
* @throws NoSuchElementException if this priority queue is empty
*/publicintdelMin() {
if (N == 0) thrownew NoSuchElementException("Priority queue underflow");
int min = pq[1];
exch(1, N--);
sink(1);
assert min == pq[N+1];
qp[min] = -1; // delete
keys[min] = null; // to help with garbage collection
pq[N+1] = -1; // not neededreturn min;
}
/**
* Returns the key associated with index <tt>i</tt>.
*
* @param i the index of the key to return
* @return the key associated with index <tt>i</tt>
* @throws IndexOutOfBoundsException unless 0 ≤ <tt>i</tt> < <tt>maxN</tt>
* @throws NoSuchElementException no key is associated with index <tt>i</tt>
*/public Key keyOf(int i) {
if (i < 0 || i >= maxN) thrownew IndexOutOfBoundsException();
if (!contains(i)) thrownew NoSuchElementException("index is not in the priority queue");
elsereturn keys[i];
}
/**
* Change the key associated with index <tt>i</tt> to the specified value.
*
* @param i the index of the key to change
* @param key change the key associated with index <tt>i</tt> to this key
* @throws IndexOutOfBoundsException unless 0 ≤ <tt>i</tt> < <tt>maxN</tt>
* @throws NoSuchElementException no key is associated with index <tt>i</tt>
*/publicvoidchangeKey(int i, Key key) {
if (i < 0 || i >= maxN) thrownew IndexOutOfBoundsException();
if (!contains(i)) thrownew NoSuchElementException("index is not in the priority queue");
keys[i] = key;
swim(qp[i]);
sink(qp[i]);
}
/**
* Change the key associated with index <tt>i</tt> to the specified value.
*
* @param i the index of the key to change
* @param key change the key associated with index <tt>i</tt> to this key
* @throws IndexOutOfBoundsException unless 0 ≤ <tt>i</tt> < <tt>maxN</tt>
* @deprecated Replaced by {@link #changeKey(int, Key)}.
*/publicvoidchange(int i, Key key) {
changeKey(i, key);
}
/**
* Decrease the key associated with index <tt>i</tt> to the specified value.
*
* @param i the index of the key to decrease
* @param key decrease the key associated with index <tt>i</tt> to this key
* @throws IndexOutOfBoundsException unless 0 ≤ <tt>i</tt> < <tt>maxN</tt>
* @throws IllegalArgumentException if key ≥ key associated with index <tt>i</tt>
* @throws NoSuchElementException no key is associated with index <tt>i</tt>
*/publicvoiddecreaseKey(int i, Key key) {
if (i < 0 || i >= maxN) thrownew IndexOutOfBoundsException();
if (!contains(i)) thrownew NoSuchElementException("index is not in the priority queue");
if (keys[i].compareTo(key) <= 0)
thrownew IllegalArgumentException("Calling decreaseKey() with given argument would not strictly decrease the key");
keys[i] = key;
swim(qp[i]);
}
/**
* Increase the key associated with index <tt>i</tt> to the specified value.
*
* @param i the index of the key to increase
* @param key increase the key associated with index <tt>i</tt> to this key
* @throws IndexOutOfBoundsException unless 0 ≤ <tt>i</tt> < <tt>maxN</tt>
* @throws IllegalArgumentException if key ≤ key associated with index <tt>i</tt>
* @throws NoSuchElementException no key is associated with index <tt>i</tt>
*/publicvoidincreaseKey(int i, Key key) {
if (i < 0 || i >= maxN) thrownew IndexOutOfBoundsException();
if (!contains(i)) thrownew NoSuchElementException("index is not in the priority queue");
if (keys[i].compareTo(key) >= 0)
thrownew IllegalArgumentException("Calling increaseKey() with given argument would not strictly increase the key");
keys[i] = key;
sink(qp[i]);
}
/**
* Remove the key associated with index <tt>i</tt>.
*
* @param i the index of the key to remove
* @throws IndexOutOfBoundsException unless 0 ≤ <tt>i</tt> < <tt>maxN</tt>
* @throws NoSuchElementException no key is associated with index <t>i</tt>
*/publicvoiddelete(int i) {
if (i < 0 || i >= maxN) thrownew IndexOutOfBoundsException();
if (!contains(i)) thrownew NoSuchElementException("index is not in the priority queue");
int index = qp[i];
exch(index, N--);
swim(index);
sink(index);
keys[i] = null;
qp[i] = -1;
}
/***************************************************************************
* General helper functions.
***************************************************************************/privatebooleangreater(int i, int j) {
return keys[pq[i]].compareTo(keys[pq[j]]) > 0;
}
privatevoidexch(int i, int j) {
int swap = pq[i];
pq[i] = pq[j];
pq[j] = swap;
qp[pq[i]] = i;
qp[pq[j]] = j;
}
/***************************************************************************
* Heap helper functions.
***************************************************************************/privatevoidswim(int k) {
while (k > 1 && greater(k/2, k)) {
exch(k, k/2);
k = k/2;
}
}
privatevoidsink(int k) {
while (2*k <= N) {
int j = 2*k;
if (j < N && greater(j, j+1)) j++;
if (!greater(k, j)) break;
exch(k, j);
k = j;
}
}
/***************************************************************************
* Iterators.
***************************************************************************//**
* Returns an iterator that iterates over the keys on the
* priority queue in ascending order.
* The iterator doesn't implement <tt>remove()</tt> since it's optional.
*
* @return an iterator that iterates over the keys in ascending order
*/public Iterator<Integer> iterator() { returnnew HeapIterator(); }
privateclassHeapIteratorimplementsIterator<Integer> {// create a new pqprivate IndexMinPQ<Key> copy;
// add all elements to copy of heap// takes linear time since already in heap order so no keys movepublicHeapIterator() {
copy = new IndexMinPQ<Key>(pq.length - 1);
for (int i = 1; i <= N; i++)
copy.insert(pq[i], keys[pq[i]]);
}
publicbooleanhasNext() { return !copy.isEmpty(); }
publicvoidremove() { thrownew UnsupportedOperationException(); }
public Integer next() {
if (!hasNext()) thrownew NoSuchElementException();
return copy.delMin();
}
}
/**
* Unit tests the <tt>IndexMinPQ</tt> data type.
*/publicstaticvoidmain(String[] args) {
// insert a bunch of strings
String[] strings = { "it", "was", "the", "best", "of", "times", "it", "was", "the", "worst" };
IndexMinPQ<String> pq = new IndexMinPQ<String>(strings.length);
for (int i = 0; i < strings.length; i++) {
pq.insert(i, strings[i]);
}
// delete and print each keywhile (!pq.isEmpty()) {
int i = pq.delMin();
StdOut.println(i + " " + strings[i]);
}
StdOut.println();
// reinsert the same stringsfor (int i = 0; i < strings.length; i++) {
pq.insert(i, strings[i]);
}
// print each key using the iteratorfor (int i : pq) {
StdOut.println(i + " " + strings[i]);
}
while (!pq.isEmpty()) {
pq.delMin();
}
}
}
/******************************************************************************
* Copyright 2002-2015, Robert Sedgewick and Kevin Wayne.
*
* This file is part of algs4.jar, which accompanies the textbook
*
* Algorithms, 4th edition by Robert Sedgewick and Kevin Wayne,
* Addison-Wesley Professional, 2011, ISBN 0-321-57351-X.
* http://algs4.cs.princeton.edu
*
*
* algs4.jar is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* algs4.jar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with algs4.jar. If not, see http://www.gnu.org/licenses.
******************************************************************************/
1.带权重的边的数据结构/** * 该类对象可以表示图中的一条边 * @author lhever 2017年2月19日 下午5:10:49 * @version v1.0 */public class Edge implements Comparable<Edge>{ private int v; private int w; private final do