1. 程式人生 > >《演算法導論》習題解答 Chapter 22.1-4(去除重邊)

《演算法導論》習題解答 Chapter 22.1-4(去除重邊)

思路:重開一個新圖,按著鄰接列表的順序從上到下遍歷,每遍歷一行連結串列前,清空visited陣列,如果沒有訪問過這個元素,則加入新圖,如果已經訪問過了(重邊),則不動。

虛擬碼:

複雜度:O(V+E)

for each u 屬於 Vertex
    visited[u] = false;
for u 屬於 Vertex
	visited[u] = true;
	for v 屬於 Adj[u]
		if(!visited[v])
			Adj1[u].insert(v);
			visited[v] = true;
	for v 屬於 Adj[u]
            visited[v]=false;
        visited[u] = false;


證明演算法正確性:


命題:給定一條邊(u,v),此邊為有向邊,visited[v]=false 當且僅當 (u,v)需加入E'.

=>已知起點為u,visited[v]=false,則說明v曾經並沒有被u訪問到,因為如果訪問到,則visited[v]被置為true,則如果當訪問邊(u,v)時,visited[v]==false,則會將(u,v)加入E'中.
<=已知(u,v)需要加入E',如果visited[v]=true,則不會執行if裡的語句,則說明(u,v)不會加入E',與條件矛盾。

輸入:

3 8
a b
a b
a b
b c
b c
b c 
c a
c c


原始碼:

package C22;

import java.util.Iterator;
/**
 * 化簡多重圖
 * @author xiazdong
 *
 */
public class C1_4 {
	static Adjacent_List g;
	public static void main(String[] args) throws Exception {
		Adjacent_List adjacent_list = GraphFactory.getAdjacentListInstance("input\\22.1-4.txt");	
		C1_4.g = adjacent_list;
		Adjacent_List new_adj = remove_multiedge(adjacent_list);
		adjacent_list.printAllEdges();
		System.out.println("==============");
		new_adj.printAllEdges();
	}
	/**
	 * 去掉重邊的函式
	 * @param g
	 * @return
	 */
	public static Adjacent_List remove_multiedge(Adjacent_List g){
		int size = g.getSize();
		Adjacent_List adj1 = new Adjacent_List(size);
		boolean visited[] = new boolean[size];
		for(int i=0;i<visited.length;i++) visited[i] = false;//O(V)
		for(int i=0;i<size;i++){		//O(V+E)
			visited[i] = true;
			Iterator<String> iter = g.getListByVertexIndex(i).iterator();
			while(iter.hasNext()){	
				String vstr = iter.next();
				int v = g.getVertexIndex(vstr);
				if(!visited[v]){
					visited[v] = true;
					adj1.addEdge(g.getVertexValue(i), vstr);
				}
			}
			/*下面一句話 對新圖遍歷比較快,雖然速度只會提升常數級別。
			 較快:iter = adj1.getListByVertexValue(g.getVertexValue(i)).iterator();
			 較慢:iter = g.getListByVertexIndex(i).iterator(); 因為重邊
			 */
			iter = adj1.getListByVertexValue(g.getVertexValue(i)).iterator();	
			while(iter.hasNext()){	//再一次遍歷這個連結串列,並對這些元素清除陣列 O(E)
				String vstr = iter.next();
				int v = g.getVertexIndex(vstr);
				visited[v] = false;
			}
			visited[i] = false;
		}
		return adj1;
	}
}


原文點此索引目錄。感謝xiazdong君 && Google醬。這裡是偶爾做做搬運工的水果君(^_^) )