CO trzeba umieć:
//////////////////////////////////////////////////////////////////
PRZESZUKIWANIE GRAFU
Przeszukiwanie
grafu to jest nic innego, jak przejście po grafie tak, aby przejść
wszystkie wierzchołki (pod warunkiem że graf jest spójny). Ja
omówię przechodzenie grafu w głąb(DFS) i w szerz(BFS), ponieważ
to nam do szczęścia może być potrzebne.
PRZESZUKIWANIE
W GŁĄB (DFS)
Nasz
graf i jego macierz przejść.
0
|
1
|
2
|
3
|
|
1
|
0
|
3
|
||
2
|
0
|
3
|
4
|
|
3
|
0
|
1
|
2
|
5
|
4
|
2
|
6
|
||
5
|
3
|
|||
6
|
4
|
Będą nam teraz potrzebne dwie listy, identyczne co do implementacji. Do jednej będziemy dodawać element które odwiedziliśmy (nazwiemy ją Visit) oraz nasz stos, w którym będziemy umieszczać wierzchołki grafu do których będziemy przechodzić (nazwiemy ją Stos).
Na
początku wybieramy sobie wierzchołek początkowy (wybieramy 0 dla
wygody) i dodajemy go do listy Visit. Następnie na Stos dodajemy
wierzchołki przyległe do naszego wierzchołka 0.
Visit: [0]
Stos:
[1,2,3]
Teraz
bierzemy kolejny wierzchołek, ale teraz naszym następnym
wierzchołkiem jest ostatni element Stosu (u nas 3). Więc musimy
przejść do wierzchołka 3 (dodać do Visit), ale i usunąć
wierzchołek 3 (ostatni element stosu) ze Stosu. Następnie dodać
wierzchołki sąsiadujące z naszym wierzchołkiem 3. Są to elementy
1,2,5.
Visit:
[0,3]
Stos:
[1,2,1,2,5]
Teraz ponownie bierzemy wierzchołek ze Stosu (ostatni – 5) dodajemy do Visit, a wierzchołki przyległe dodajemy do Stosu. Tutaj mamy taką sytuację, że wierzchołkiem przyległy do wierzchołka jest wierzchołek 3. Tego wierzchołka już na stosie nie ma, ale ten wierzchołek jest na liście Visit, więc nie dodajemy go na Stos, bo już w 3 byliśmy. Czyli nic nie dodajemy na stos.
Visit:
[0,3,5]
Stos:
[1,2,1,2]
Teraz
ponownie bierzemy ostatni element stosu. Jest to wierzchołek 2.
Zdejmujemy element ze Stosu i dodajemy wierzchołki przyległe do 2
ale takie, w których nie byliśmy, czyli wierzchołek 4.
Stos:
[1,2,1,4]
Visit: [0,3,5,2,4]
Stos:
[1,2,1,6]
Teraz
kolejny element, czyli 6 do Visit. I zdejmujemy go ze stosu.
Visit:[0,3,5,2,4,6]
Stos:
[1,2,1]
Teraz ponownie bierzemy ostatni element ze Stosu. Dodajemy do Visit 1.
Visit: [0,3,5,2,4,6,1]
Stos:
[1,2]
My
już zauważyliśmy, że przeszliśmy cały graf, ale program tego
jeszcze nie wie, więc kontynuuje swoją prace, ale wierzchołek 2
był już odwiedzony, więc zostaje zdjęty ze stosu i nic się z nim
nie robi. Następnie wierzchołek 1 również był odwiedzony i
zdejmujemy go ze Stosu. Nasz Stos teraz jest pusty, więc program
kończy swoje działanie. Jeśli nasz graf był grafem spójnym to w
liście Visit powinny znajdować się wszystkie wierzchołki.
Kolejność przechodzenia wierzchołków może być trochę inna, ale
zawsze po przejściu DFS powinniśmy otrzymać graf acykliczny
(zielony zaznaczony). Możemy zrobić tak, że nie będziemy dodawać
zdublowanych elementów na Stos co może przyspieszyć nasz program.
Ale spowoduje to, że troszeczkę inaczej będziemy przez graf
przechodzić.
KOD:
////////////////////////////////////////////////////////////////////////////////
///............................DFS.............(w
głąb)......................///
////////////////////////////////////////////////////////////////////////////////
void
add_queue(struct graf **root,struct graf *top){
//
dodawanie na koniec naszych list
//
argumentami funkcj jest głowa listy (Stos/Visit) i wierzchołek
struct
graf *new_elem=(struct graf*)malloc(sizeof(struct
graf));
struct
graf *w=*root,*y;
new_elem->next=new_elem->prev=NULL;
new_elem->top=top->top;
new_elem->branch=top->branch;
if(!w)*root=new_elem;
else{
while(w->next){
w=w->next;
}
w->next=new_elem;
new_elem->prev=w;
}
}
/////////////////////////////////////////////////////////////////////////////////////
void write_queue(struct graf *root){
//
funkcja wypisuje naszą listę
while(root){
printf("
%d ", root->top);
root=root->next;
}
}
////////////////////////////////////////////////////////////////////////////////
void pop(struct graf **Stos){
//
funkcja kasuje ostatni element ze Stosu
struct graf *w=*Stos;
if(!(*Stos)->next){
free(*Stos);
*Stos=NULL;
}else{
while(w->next->next)w=w->next;
free(w->next);
w->next=NULL;
}
}
////////////////////////////////////////////////////////////////////////////////
void DFS(struct graf *root, struct graf **Stos, struct graf **Visit){
// funkcja główna naszego przeszukiwania
//
pierwszy argument to wierzchołek który odwiedzamy
if(!find(*Visit,root->top))
add_queue(Visit,root);
//
dodajemy wierzchołek do Visit jeżeli o tam już nie ma
if(*Stos) pop(Stos); // zdejmujemy element ze stosu
struct
branch *w=root->branch; // zmienna pomocnicza
while(w){ // pętla przechodzi po wierzchołkach sąsiednich z naszym
//
warunek jeżli chcemy aby nie dodawało zdublowanych elementów na
stos
if( !find(*Visit,w->top) &&
!find(*Stos,w->top))
add_queue(Stos,w->adress);
// dodwanie wierzchołka na stos
// dodwanie wierzchołka na stos
w=w->next;
}
//
wypisanie naszych list
printf("VISIT:
");
write_queue(*Visit);
printf("
STOS: ");
write_queue(*Stos);
printf("\n");
//
if(*Stos){
// jeżeli stos istnieje to wykonujemy jeszcze raz wszystko
struct
graf *p=*Stos;
while(p->next)p=p->next;
// p – ostatni element stosu
DFS(p,Stos,Visit);
}
}
//
*find – to funkcja ta sama której używałem przy grafie do
szukania elementu
Jak
widzimy tu też wszystko opiera się o listy i działania na nich.
Sama funkcja DFS jest tylko
ich wykorzystaniem. Czyli dodajemy do Visit, zdejmujemy ze Stosu,
dodajemy na stos nowe wierzchołki. Możemy wypisać aby widzieć jak
się to nam zmienia, a następnie wywołujemy ponownie, dopóki
są elementy na stosie.

Brak komentarzy:
Prześlij komentarz