• Nie Znaleziono Wyników

Ćwiczenie 67. Napisać algorytmy porządkowania wierzchołków grafu spójnego w po- rządku preorder i w porządku postorder (użyć pseudokodu lub jakiegokolwiek języka programowania).

N/A
N/A
Protected

Academic year: 2021

Share "Ćwiczenie 67. Napisać algorytmy porządkowania wierzchołków grafu spójnego w po- rządku preorder i w porządku postorder (użyć pseudokodu lub jakiegokolwiek języka programowania)."

Copied!
7
0
0

Pełen tekst

(1)

Ćwiczenie 67.

Napisać algorytmy porządkowania wierzchołków grafu spójnego w po- rządku preorder i w porządku postorder (użyć pseudokodu lub jakiegokolwiek języka programowania).

Rozwiązanie

Program, którego kod źródłowy został załączony, został napisany w ję- zyku C++.

Odczytuje on ze standardowego wejścia dane w następującym formacie:

• Rozdzielone spacją liczby |V | oraz |E| zapisane w pierwszej linii.

• |V | oddzielonych spacjami nazw wierzchołków w drugiej linii.

• W następnych |E| liniach - pary nazw wierzchołków, które są połączone krawędziami.

• W ostatniej linii - typ przeszukiwania (”PREORDER” albo ”PO- STORDER”) oraz nazwa wierzchołka, od którego przeszukiwanie zo- stanie rozpoczęte.

Kolejność podawania wierzchołków oraz krawędzi nie ma znaczenia. Do- konano następujących założeń: wierzchołki mają różne nazwy, dla każdej krawędzi oba jej końce są istniejącymi wierzchołkami, wierzchołek od któ- rego ma być rozpoczęte przeszukiwanie istnieje, oraz graf jest spójny. Ze- staw testowy jest przykładem grafu mającym na celu zademonstrowanie, że program prawidłowo obsługuje krawędzie wielokrotne i pętle, oraz że po- za numerami preorder lub postorder zaznaczane jest wybrane drzewo prze- szukiwania. Drzewo to jest zdefiniowane jednoznacznie - relacją porządku w zbiorze sąsiadów każdego wierzchołka jest porównywanie nazw jako napi- sów.

Program wypisuje w odpowiedzi opis grafu w formacie dot, który pozwo-

lił na wyrenderowanie wizualizacji grafów zawartych w opisie rozwiązania za

pomocą narzędzia graphviz.

(2)

Przykład pliku do wczytania:

12 19

a b c d e f g h i j k l

j f j k g e e l d k d h h d d a h c b f g f d j g l b k a j a g l e i i i k

PREORDER a

Wyjście programu w języku dot:

gr aph G {

a [ l a b e l =”a : 1 ” , p e r i p h e r i e s = 2 ] ; d [ l a b e l =”d : 2 ” ] ;

h [ l a b e l =”h : 3 ” ] ; c [ l a b e l =”c : 4 ” ] ; h −− c ;

d −− h ;

d −− h [ s t y l e =”d a s h e d ” ] ; j [ l a b e l =” j : 5 ” ] ;

f [ l a b e l =” f : 6 ” ] ; b [ l a b e l =”b : 7 ” ] ; k [ l a b e l =”k : 8 ” ] ; i [ l a b e l =” i : 9 ” ] ;

i −− i [ s t y l e =”d a s h e d ” ] ; k −− i ;

b −− k ; f −− b ;

g [ l a b e l =”g : 1 0 ” ] ; e [ l a b e l =”e : 1 1 ” ] ; l [ l a b e l =” l : 1 2 ” ] ; e −− l ;

e −− l [ s t y l e =”d a s h e d ” ] ; g −− e ;

g −− l [ s t y l e =”d a s h e d ” ] ; f −− g ;

j −− f ;

j −− k [ s t y l e =”d a s h e d ” ] ; d −− j ;

d −− k [ s t y l e =”d a s h e d ” ] ; a −− d ;

a −− g [ s t y l e =”d a s h e d ” ] ; a −− j [ s t y l e =”d a s h e d ” ] ;

} ;

(3)

Oraz wygenerowana na podstawie tego wyjścia wizualizacja grafu:

a:1

d:2

j:5

g:10 h:3

k:8

c:4 f:6

b:7

i:9

e:11

l:12

Zmieniając ostatnią linijkę, dla tego samego grafu mogę ponumerować wierzchołki w kolejności postorder:

c:1 h:2

d:11

k:4 j:10

i:3 b:5 f:9

g:8

l:6 e:7 a:12

(4)

Albo preorder (po lewej) oraz postorder (po prawej), zaczynając od wierzchołka i (wizualizacje różnią się w granicach dopuszczalnych dla na- rzędzia do ich tworzenia - drzewo przeszukiwania jest w obu przypadkach takie samo):

i:1

k:2

b:3

f:4

g:5

j:10 a:6 e:11

l:12 d:7

h:8

c:9

i:12

k:11

c:1 h:2 d:4

j:3 b:10

a:5 g:8

l:6 e:7 f:9

Kod źródłowy w języku C++

#i n c l u d e < c s t d l i b >

#i n c l u d e <c a s s e r t >

#i n c l u d e <i o s t r e a m >

#i n c l u d e <s t r i n g >

#i n c l u d e <v e c t o r >

#i n c l u d e <s e t >

#i n c l u d e <map>

// W i e r z c h o l e k s t r u c t V e r t e x {

// R e l a c j a p o r z a d k u pomiedzy w i e r z c h o l k a m i ( p o r z a d e k l e k s y k o g r a f i c z n y nazw ) s t r u c t PointerCompare {

b o o l o p e r a t o r( ) ( V e r t e x ∗ c o n s t &l e f t , V e r t e x ∗ c o n s t &r i g h t ) c o n s t { r e t u r n l e f t −>name < r i g h t −>name ;

} } ;

// Typ do p r z e c h o w y w a n i a uporzadkowanego z b i o r u s a s i a d o w t y p e d e f s t d : : m u l t i s e t <V e r t e x ∗ , PointerCompare> n e i g h b o u r s S e t ;

i n t i d ; // numer w p a m i e c i

s t d : : s t r i n g name ; // nazwa w i e r z c h o l k a

n e i g h b o u r s S e t n e i g h b o u r s ; // uporzadkowany z b i o r s a s i a d o w // K o n s t r u k t o r i d e s t r u k t o r

(5)

V e r t e x ( s t d : : s t r i n g c o n s t & name , i n t c o n s t & i d ) { name = name ; i d = i d ; }

˜ V e r t e x ( ) { }

// Dodawanie s a s i a d a

v o i d addNeighbour ( V e r t e x ∗ c o n s t &nPtr ) { n e i g h b o u r s . i n s e r t ( nPtr ) ;

} } ;

// G r a f

s t r u c t Graph {

// P o r z a d k i numerowania p r z y p r z e s z u k i w a n i u DFS enum V i s i t i n g O r d e r { PREORDER, POSTORDER } ;

// Wektor z danymi k o l e j n o u m i e s z c z a n y c h w g r a f i e w i e r z c h o l k o w s t d : : v e c t o r <Vertex> V ;

// T a b l i c a p o z w a l a j a c a u s t a l i c p o z y c j e w i e r z c h o l k a w w e k t o r z e w e g l u g nazwy s t d : : map<s t d : : s t r i n g , i n t> vertexIdByName ;

// Dodawanie w i e r z c h o l k a

v o i d a d d V e r t e x ( s t d : : s t r i n g c o n s t &name ) { i n t v e r t e x I d = V . s i z e ( ) ;

// A s e r c j a − w i e r z c h o l k i maja r o z n e nazwy

a s s e r t ( vertexIdByName . f i n d ( name ) == vertexIdByName . end ( ) ) ; V . p u s h b a c k ( V e r t e x ( name , v e r t e x I d ) ) ;

vertexIdByName [ name ] = v e r t e x I d ; }

// Dodawanie k r a w e d z i

v o i d addEdge ( s t d : : s t r i n g c o n s t &uName , s t d : : s t r i n g c o n s t &vName ) {

// A s e r c j a − w i e r z c h o l k i , k t o r e maja byc p o l a c z o n e k r a w e d z i a − i s t n i e j a a s s e r t ( vertexIdByName . f i n d ( uName ) != vertexIdByName . end ( ) ) ;

a s s e r t ( vertexIdByName . f i n d ( vName ) != vertexIdByName . end ( ) ) ;

i n t uId = vertexIdByName [ uName ] ;

i n t v I d = vertexIdByName [ vName ] ; V [ uId ] . addNeighbour (&(V [ v I d ] ) ) ;

i f( uId != v I d ) { // warunek z a p o b i e g a j a c y d o d a n i u p e t l i dwa r a z y V [ v I d ] . addNeighbour (&(V [ uId ] ) ) ;

} }

// Metoda d f s p r z y j m u j a c a p o r z a d e k p r z e s z u k i w a n i a i nazwe k o r z e n i a v o i d d f s ( V i s i t i n g O r d e r c o n s t &vm, s t d : : s t r i n g c o n s t &rootName ) {

// A s e r c j a − k o r z e n budowanego drzewa p r z e s z u k i w a n i a w s z e r z i s t n i e j e a s s e r t ( vertexIdByName . f i n d ( rootName ) != vertexIdByName . end ( ) ) ; i n t c o u n t e r = 0 ;

b o o l ∗ v i s i t e d = new b o o l[ V . s i z e ( ) ] ; // i n i c j a l i z a c j a : n i c n i e o d w i e d z o n o d f s (vm, v i s i t e d , c o u n t e r , &(V [ vertexIdByName [ rootName ] ] ) ) ;

a s s e r t ( c o u n t e r == (i n t) V . s i z e ( ) ) ; // G r a f s p o j n y d e l e t e[ ] v i s i t e d ;

}

// Wewnetrzna metoda s t a n o w i a c a r e k u r e n c y j n a i m p l e m e n e t a c j e p r z e b i e g u d f s v o i d d f s ( V i s i t i n g O r d e r c o n s t &vm, b o o l ∗ c o n s t &v i s i t e d , i n t &c o u n t e r ,

V e r t e x ∗ c o n s t &vPtr , V e r t e x ∗ c o n s t &p a r e n t=NULL) { V e r t e x &v = ∗ vPtr ;

v i s i t e d [ v . i d ] = t r u e;

// J e s l i p r e o r d e r , t o n a d a j numerek w i e r z c h o l k o w i t u t a j

i f(vm == PREORDER) v i s i t V e r t e x ( v . name , c o u n t e r , p a r e n t==NULL ) ; // P r z e s z u k i w a n i e s a s i a d o w

(6)

// Uwaga − p o j e d y n c z a i t e r a c j a miedzy k o l e j n y m i s a s i a d a m i ma z l o z o n o s c // p e s y m i s t y c z n a O( l o g ( n ) ) , g d z i e n − r o z m i a r z b i o r u s a s i a d o w , j e d n a k // k o s z t i t e r a c j i po calym z b i o r z e a m o r t y z u j e s i e do O( n ) ( m u l t i s e t t o // drzewo czerwono−c z a r n e ) . D l a t e g o z l o z o n o s c c a l e j p r o c e d u r y d f s t o // O ( | E | ) .

f o r( V e r t e x : : n e i g h b o u r s S e t : : i t e r a t o r i t = v . n e i g h b o u r s . b e g i n ( ) ; i t != v . n e i g h b o u r s . end ( ) ; i t ++) {

i f( ∗ i t != p a r e n t ) { // d l a s a s i a d o w poza ojcem i f(n o t v i s i t e d [ ( ∗ i t )−> i d ] ) {

// J e z e l i n i e o d w i e d z o n y − z a g l a b s i e w n i e g o r e k u r e n c y j n i e d f s (vm, v i s i t e d , c o u n t e r , ∗ i t , vPtr ) ;

// I d o d a j do o p i s u w y s w i e t l a n i a krawedz j a k o n a l e z a c a do // drzewa p r z e s z u k i w a n i a

d i s p l a y E d g e ( v . name , ( ∗ i t )−>name , t r u e) ; } e l s e i f( v . name <= ( ∗ i t )−>name ) {

// J e z e l i od wi e dz on y i n i e j e s t p o p r z e d n i k i e m wedlug // p o r z a d k u w i e r z c h o l k o w ( z a p o b i e g a n i e r y s o w a n i u k r a w e d z i // dwa r a z y ) − d o d a j do o p i s u w y s w i e t l a n i a krawedz j a k o // n i e n a l e z a c a do drzewa p r z e s z u k i w a n i a

d i s p l a y E d g e ( v . name , ( ∗ i t )−>name , f a l s e) ; }

} }

// J e s l i p o s t o r d e r , t o n a d a j numerek w i e r z c h o l k o w i t u t a j

i f(vm == POSTORDER) v i s i t V e r t e x ( v . name , c o u n t e r , p a r e n t==NULL ) ; }

// O d w i e d z a n i e w i e r z c h o l k a

v o i d v i s i t V e r t e x ( s t d : : s t r i n g c o n s t &name , i n t &c o u n t e r , b o o l c o n s t &i s R o o t=f a l s e) {

c o u n t e r ++; // p o d b i j numer o 1 ( z a c z y n a s i e od 0 ) // Dodaj do w y s w i e t l a n i a w i e r z c h o l e k z b i e z a c y m numerem d i s p l a y V e r t e x ( name , c o u n t e r , i s R o o t ) ;

}

// W y s w i e t l a n i e w i e r z c h o l k a ( j e z y k d o t )

v o i d d i s p l a y V e r t e x ( s t d : : s t r i n g c o n s t &name , i n t &c o u n t e r , b o o l c o n s t &i s R o o t=f a l s e) {

i f( i s R o o t ) { // k o r z e n b e d z i e w podwojnym obramowaniu

s t d : : c o u t << name << ” [ l a b e l =\”” << name << ” : ” << c o u n t e r

<< ” \ ” , p e r i p h e r i e s = 2 ] ; \ n”; } e l s e {

s t d : : c o u t << name << ” [ l a b e l =\”” << name << ” : ” << c o u n t e r

<< ” \ ” ] ; \ n”; }

}

// W y s w i e t l a n i e k r a w e d z i ( j e z y k d o t )

v o i d d i s p l a y E d g e ( s t d : : s t r i n g c o n s t &uName , s t d : : s t r i n g c o n s t &vName , b o o l c o n s t &i n T r e e ) {

s t d : : c o u t << uName << ” −− ” << vName ;

i f(n o t i n T r e e ) { // krawedz s p o z a drzewa b e d z i e l i n i a p r z e r y w a n a s t d : : c o u t << ” [ s t y l e =\” d a s h e d \ ” ] ”;

}

s t d : : c o u t << ” ; \ n”; }

} ;

// P r o c e d u r a glowna i n t main ( ) {

Graph G;

(7)

i n t v , e ;

// Wczytaj l i c z b e w i e r z c h o l k o w i k r a w e d z i s t d : : c i n >> v >> e ;

// Wczytaj nazwy w i e r z c h o l k o w i d o d a j w i e r z c h o l k i do g r a f u f o r(i n t i = 0 ; i < v ; i ++) {

s t d : : s t r i n g name ; s t d : : c i n >> name ; G. a d d V e r t e x ( name ) ; }

// O d c z y t a j i n f o r m a c j e o k r a w e d z i a c h i d o d a j k r a w e d z i e do g r a f u f o r(i n t i = 0 ; i < e ; i ++) {

s t d : : s t r i n g uName , vName ; s t d : : c i n >> uName >> vName ; G. addEdge ( uName , vName ) ; }

// Wczytaj r o d z a j p r z e s z u k i w a n i a i nazwe k o r z e n i a s t d : : s t r i n g rootName , orderName ;

s t d : : c i n >> orderName >> rootName ;

// A s e r c j a − wskazany p o r z a d e k p r z e s z u k i w a n i a j e s t p r a w i d l o w y a s s e r t ( orderName == ”PREORDER” o r orderName == ”POSTORDER”) ;

// Wypisuj o p i s g r a f u w j e z y k u dot , p r z e s z u k u j a c go w t r a k c i e i n a d a j a c // numery p o s t o r d e r l u b p r e o r d e r

s t d : : c o u t << ” g ra ph G {\ n”; i f( orderName == ”PREORDER”) {

G. d f s ( Graph : : PREORDER, rootName ) ;

} e l s e i f( orderName == ”POSTORDER”) {

G. d f s ( Graph : : POSTORDER, rootName ) ; }

s t d : : c o u t << ” } ; \ n”; r e t u r n 0 ;

}

Cytaty

Powiązane dokumenty

Na podstawie obserwacji obliczono prawdopodobieństwo p=0,1 że któryś komputerów w czasie zajęć jest wolny (równe dla wszystkich pięciu

Powstaje podgraf H, który ma mniej krawędzi niż graf G (może nie być spójny), ale nadal każdy wierzchołek ma w nim stopień parzysty (po usunięciu cyklu C stopień zmniejsza

Kolorowanie harmoniczne wierzchołków grafu jest taką odmianą kolorowania klasycznego, która ma oryginalne zastosowania praktyczne. W niniejszej pracy pokazujemy, że

Stąd też w artykule przedstaw iono trzy m etody agregacji grafu połączeń.. In the paper, the connection graph is

Co komendant policji może wywnioskować z powyższego raportu (poza oczywistym fak- tem, że należy zwolnić

Ten pierwszy jest z tego powodu, Że nie wolno wchodzić do ogrodu, Drugi - że woda nie chce być sucha, Trzeci - że mucha wleciała do ucha, A jeszcze, że kot musi drapać,.. Że

Dostosowując powyższą metodę uzyskujemy pełny algorytm przy pomocy którego, możemy sprawdzić czy zadana liczba naturalna n o dowolnej podstawie m

osoby z niepełnosprawnością– osoby z niepełnosprawnością w rozumieniu Wytycznych w zakresie realizacji zasady równości szans i niedyskryminacji, w tym dostępności dla osób