Prohledávání do šířky
Prohledávání do šířky (Breadth-first search, BFS) je jedním ze základních grafových algoritmů, který slouží k průchodu daného grafu. Jeho principy jsou základem pro další algoritmy, jako je například Jarník-Primův algoritmus nebo Dijkstrův algoritmus.
Princip
Při prohledávání do šířky začneme procházet graf z libovolného uzlu. Tento uzel zpracujeme a při objevení jeho dosud nenalezených potomků tyto potomky uložíme do fronty a postupně zpracováváme stejným způsobem. Takto postupujeme, dokud není fronta prázdná.
Díky ukládání do fronty dochází k procházení grafu po vlnách – uzly jsou zpracovávány v pořadí daném jejich vzdáleností od kořene.
Výstupem algoritmu je strom prohledávání do hloubky obsahující všechny uzly dosažitelné z výchozího uzlu - tzv. BF-strom. BF-strom je stromem nejkratších cest z daného uzlu ve smyslu počtu hran.
Složitost
Za předpokladu, že je složitost přístupu k potomkům daného uzlu konstantní, stejně jako složitost uložení a výběru z fronty, tak je asymptotická složitost celého algoritmu , protože každou hranu a každý uzel projde právě jednou.
Kód
/**
* Dosud neobjeveny uzel
*/
private static final int FRESH = 0;
/**
* Otevreny uzel
*/
private static final int OPENED = 1;
/**
* Uzavreny uzel
*/
private static final int CLOSED = 2;
/**
* Prohledavani do sirky
* @param graph graf k prohledani
* @param rootNr cislo uzlu, ktery je korenem
* @return pole predchudcu
*/
public static GraphNodeIface[] breadthFirstSearch(GraphIface graph, int rootNr){
GraphNodeIface[] predecessors = new GraphNodeIface[graph.getVertexCount()]; //pole predchudcu
int[] state = new int[graph.getVertexCount()];
for (int i = 0; i < state.length; i++) {
state[i] = FRESH;
}
state[rootNr] = OPENED; //koren je otevreny
predecessors[rootNr] = null; //koren nema predky
Queue<GraphNodeIface> l = new LinkedList<GraphNodeIface>(); //fronta - pokud zde frontu nahradime zasobnikem, tak ziskame prohledavani do hloubky
l.add(graph.getNode(rootNr));
while(!l.isEmpty()){
GraphNodeIface node = l.poll();
List<GraphNodeIface> successors = node.getSuccessors();
for(GraphNodeIface succ : successors){ //potomci zpracovavaneho uzlu
if(state[succ.getId()] == FRESH){ //byl prave objeven
l.add(succ); //pridame ke zpracovani
state[succ.getId()] = OPENED;
predecessors[succ.getId()] = node;
}
}
state[node.getId()] = CLOSED;
}
return predecessors;
}
/**
* Operace, ktere by mel splnovat graf
* @author Pavel Micka
*/
public interface GraphIface<ENTITY> {
/**
* Prida hranu do grafu
* @param from uzel, ze ktereho hrana vychazi
* @param to uzel, do ktereho hrana vede
*/
public void addEdge(int from, int to);
/**
* Vrati pocet hran grafu
* @return pocet hran grafu
*/
public int getEdgeCount();
/**
* Vrati uzel s danym identifikatorem
* @param id
* @return
*/
public GraphNodeIface getNode(int id);
/**
* Vrati pocet vrcholu grafu
* @return pocet vrcholu grafu
*/
public int getVertexCount();
/**
* Odstrani hranu, v pripade vicenasobneho vyskytu odstrani prvni vyskyt
* @param from uzel, ze ktereho hrana vychazi
* @param to uzel, do ktereho hrana vede
*/
public void removeEdge(int from, int to);
/**
* Operace, ktere by mel splnovat uzel grafu
* @param <ENTITY>
*/
public interface GraphNodeIface<ENTITY> {
/**
* @return the id
*/
public int getId();
/**
* @return the successors
*/
public List<GraphNodeIface> getSuccessors();
/**
* @return the value
*/
public ENTITY getValue();
/**
* @param value the value to set
*/
public void setValue(ENTITY value);
}
}
Literatura
- KOLÁŘ, Josef. Teoretická informatika. 2. vyd. Praha : Česká informatická společnost, 2004. 205 s. ISBN 80-900853-8-5.


