• Nie Znaleziono Wyników

Wykład 8 - Dynamiczne struktury danych -uporządkowane(część II) 8.1. Lista jednokierunkowa uporządkowana 8.2. Lista dwukierunkowa 8.3. Drzewo binarne poszukiwań

N/A
N/A
Protected

Academic year: 2021

Share "Wykład 8 - Dynamiczne struktury danych -uporządkowane(część II) 8.1. Lista jednokierunkowa uporządkowana 8.2. Lista dwukierunkowa 8.3. Drzewo binarne poszukiwań"

Copied!
14
0
0

Pełen tekst

(1)

Wykład 8 - Dynamiczne struktury danych -uporządkowane(część II) 8.1. Lista jednokierunkowa uporządkowana

8.2. Lista dwukierunkowa

8.3. Drzewo binarne poszukiwań

Algorytmy stosowane w strukturach uporządkowanych sterowane są wartościami przechowywanymi w poszczególnych elementach tej struktury, w odróżnieniu od algorytmów dla struktur nieuporządkowanych, które sterowane są kolejnością powstawania elementów struktur ( stosy, kolejki...).

(2)

8.1. Lista jednokierunkowa uporządkowana

8.1.1. Wyszukanie w liście uporządkowanej za pomocą funkcji Szukaj

(3)

1) Lista pusta: Poczatek = nil; stąd Gdzie= nil oraz Szukaj := False

Dane_2

„A”

Nastepny Poczatek

Jeśli Poczatek<> nil, wtedy

Nast Dane_2

„A”

Nastepny

Poczatek Dane_3

„C”

Nastepny nil

jeśli Poczatek^.Dane.Nazwisko = Klucz wtedy Gdzie:= nil, Szukaj:= True, w przeciwnym wypadku,

gdy Poczatek^.Dane.Nazwisko > Klucz wtedy Gdzie:= nil, Szukaj:= False 2) Wyszukanie elementu na początku listy:

Dane_1

„D”

Nastepny nil

3) Wyszukanie w środku lub na końcu listy:

 Gdzie:=nil;

 Nast:=Poczatek;

 jeśli to nie jest ostatni element listy (Nast^.Nastepny <> nil) i jeśli jeszcze można odszukać element równy kluczowi ( Nast^.Dane.Nazwisko < Klucz) wtedy:

 Gdzie:= Nast;

 Nast:= Nast^.Nastepny;

w przeciwnym przypadku :

 Gdzie^.Nastepny wskazuje na poszukiwany element równy Kluczowi i Szukaj := True;

 lub Szukaj := False i Gdzie^. Nastepny wskazuje na element większy od Klucza Dane_1

„D”

Nastepny Gdzie

Gdzie:= nil Klucz:= „A”

kolejność wstawiania elementów do listy

Klucz := „C”

(4)

Implementacja operacji wyszukania miejsca do wstawienia (Szukaj := False) oraz elementu do usunięcia (Szukaj:= True)

unit MLISTALU;

interface

uses Modul, Rozne, Crt, MlistaLN;

{reszta procedur jak dla listy nieuporządkowanej}

function Szukaj(Poczatek:PElement;Klucz:lan;var Gdzie:PElement):Boolean;

implementation

function Szukaj(Poczatek:PElement;Klucz:lan;var Gdzie:PElement): Boolean;

var Nast: PElement;

begin

Gdzie := nil;

Szukaj:= False;

if Poczatek= nil then exit;

Nast:=Poczatek;

while ( Nast^.Dane.Nazwisko < Klucz) and (Nast^.Nastepny <> nil) do

begin

Gdzie:= Nast;

Nast := Nast^.Nastepny;

end;

if Nast^.Dane.Nazwisko = Klucz then Szukaj := True

else

{nie znaleziono w liście elementu większego od klucza}

if Nast^.Dane.Nazwisko < Klucz then Gdzie:= Nast;

end;

end.

(5)

8.1.2. Wstawianie w miejsce wyszukane przez funkcję Szukaj:= False, gdy znalazła element większy od Klucza lub koniec listy (operacje implementowane jak dla listy nieuporządkowanej - wykład 7)

(6)

 Nowy^.Nastepny:= Poczatek

 Poczatek:= Nowy

New(Nowy), gdzie N=1,2,...N Nowy Dane_N

Nastepny nil

if Poczatek = nil then Poczatek:= Nowy;

Nowy

Dane_2

„A”

Nastepny Poczatek

Nowy Dane_2

„A”

Nastepny

Poczatek Dane_3

„C”

Nastepny nil

2.2) wstawianie na początku listy, Szukaj:= False Poczatek

if Gdzie = nil then:

1) Tworzenie kolejnego elementu Nowy na stercie:

2) Wstawianie do listy kolejnego elementu Nowy

Nowy Dane_1

„D”

Nastepny nil

2.1) wstawianie do listy pustej , Szukaj:= False

Dane_1

„D”

Nastepny

nil

2.3) wstawianie wewnątrz lub na końcu listy (Szukaj:=False:)

jeśli Gdzie nie wskazuje na ostatni element listy, to Gdzie wskazuje na element większy od Klucza i wstawiaj wewnątrz listy,

 Nowy^.Nastepny:= Gdzie^.Nastepny;

 Gdzie^.Nastepny:= Nowy

Dane_1

„D”

Nastepny Gdzie

„A” < „D”

„C” < „D”

Gdzie Dane_2

„A”

Nastepny

Poczatek Dane_1

„D”

Nastepny nil

Dane_3

„E”

Nastepny

„E” > „D” Nowy

nil

w przeciwnym przypadku Gdzie wskazuje na element mniejszy od Klucza i wstawiaj na końcu listy (te same przypisania):

8.1.3. Usuwanie w miejscu wyszukanym przez funkcję Szukaj:= True, gdy znalazła element równy Kluczowi (operacje implementowane jak dla listy nieuporządkowanej - wykład 7)

(7)

Pom

Pom Dane_1

Nastepny Poczatek

Dane_2 Nastepny

Dane_3 Nastepny

nil Gdzie

nil 1) Usuwanie na początku listy: Szukaj:=True Gdzie:= nil

2) Usuwanie elementu w środku listy lub na końcu:

Dane_2

„A”

Nastepny

Poczatek Dane_3

„C”

Nastepny

Dane_2

„D”

Nastepny nil

Dane_1 Nastepny

Poczatek Dane_2

Nastepny

Dane_3 Nastepny

nil Gdzie

Gdzie:=nil

Klucz:=”A jeśli Gdzie= nil wtedy:

 Pom:= Poczatek;

 Poczatek:= Poczatek^.Nastepny

 Dispose (Pom);

Pom

jeśli Gdzie<> nil wtedy usuwany jest element wskazywany przez Gdzie^.Nastepny

 Pom:= Gdzie^.Następny;

 Gdzie^.Następny := Pom^.Nastepny

 Dispose (Pom);

Gdzie<> nil nigdy nie wskazuje na ostatni element listy, stąd ostatni element listy jest wskazywany przez Gdzie^.Nastepny i jest usuwany tak samo jak wewnątrz listy

(8)

8.2. Lista dwukierunkowa

Lista dwukierunkowa uporządkowana ma identycznie zaimplementowane procedury wstawiania, usuwania i przejścia przez strukturę (wykład 7), natomiast funkcja Szukaj, umożliwiająca wyszukanie elementów może być zaimplementowana podobnie jak dla listy jednokierunkowej lub z uwzględnieniem przejścia w obie strony

8.2.1. Wyszukanie zawsze od początku listy, podobnie jak dla listy jednokierunkowej

unit MLISTDLU;

interface

uses Modul, Rozne, Crt, MListDLN;

{reszta procedur jak dla listy nieuporządkowanej}

function Szukaj(Poczatek:PElementD;Klucz:lan;var Gdzie:PElementD):Boolean;

implementation

function Szukaj(Poczatek:PElementD;Klucz:lan;var Gdzie:PElementD): Boolean;

begin

Gdzie := Poczatek;

Szukaj:=False;

if Poczatek= nil then exit;

while ( Gdzie^.Dane.Nazwisko < Klucz) and (Gdzie^.Nastepny <> nil) do Gdzie := Gdzie^.Nastepny;

if Gdzie^.Dane.Nazwisko = Klucz then Szukaj := True;

{ znaleziono w liście element większy lub równy kluczowi}

if not (Gdzie^.Dane.Nazwisko < Klucz) then Gdzie:= Gdzie^.Poprzedni;

end;

end.

(9)

8.2.2. Wyszukanie zawsze od miejsca ostatniego wyszukania, charakterystyczne dla listy dwukierunkowej

unit MLISDLU1;

interface

uses Modul,Rozne,Crt,MListDLN;

{reszta procedur jak dla listy nieuporządkowanej}

function Szukaj(Poczatek:PElementD;Klucz:lan;var Gdzie:PElementD):Boolean;

implementation

function Szukaj(Poczatek:PElementD;Klucz:lan;var Gdzie:PElementD):Boolean;

begin

Szukaj:= False;

if Poczatek= nil then begin

Gdzie:=nil;

exit;

end;

if Gdzie=nil then Gdzie:= Poczatek;

if Gdzie^.Dane.Nazwisko < Klucz then

while (Gdzie^.Dane.Nazwisko < Klucz) and (Gdzie^.Nastepny <> nil) do Gdzie := Gdzie^.Nastepny

else

if Gdzie^.Dane.Nazwisko > Klucz then

while (Gdzie^.Dane.Nazwisko > Klucz) and (Gdzie^.Poprzedni<> nil) do

Gdzie := Gdzie^.Poprzedni;

if Gdzie^.Dane.Nazwisko = Klucz then Szukaj := True;

{ znaleziono w liście element większy lub równy kluczowi}

if not (Gdzie ^.Dane.Nazwisko < Klucz) then Gdzie:= Gdzie^.Poprzedni;

end;

end.

(10)

program Lista_uporzadkowana_dwukierunkowa; {przykład zastosowania}

uses Crt, Rozne, Modul, MListDLN, MLisDLU1;

const Tab_menu : Lancuchy =

('1 : Zakladanie listy','2 : Usuwanie z listy', '3 : Wydruk listy', '4 : Usun liste', 'K/k - Koniec programu','','','','','','');

procedure Podaj_klucz(var Klucz: lan);

begin

repeat Write('Podaj nazwisko: '); Readln(Klucz); until (Klucz <> '');

end;

procedure Wstaw_do_listy(var Poczatek, Gdzie: PElementD);

var Dana : Osoba; Z: char;

begin

Podaj_dane(Dana);

if not Szukaj(Poczatek, Dana.Nazwisko, Gdzie) or Pusty(Poczatek) then begin

Wstaw(Poczatek,Dana,Gdzie);

Dla_jednego(Poczatek,Gdzie,Wydruk_danych); Pauza(Z, False);

end;

end;

procedure Usun_z_listy(var Poczatek, Gdzie: PElementD);

var Klucz:lan; Z: char;

begin

Podaj_klucz(Klucz);

if Szukaj(Poczatek,Klucz,Gdzie) then Writeln(Usun(Poczatek,Gdzie)) else Writeln(False); Pauza(Z,False);

end;

var Wybor,Z : char; Poczatek_DLN, Gdzie : PElementD;

begin ClrScr;

Randomize; Inicjalizacja(Poczatek_DLN);

repeat

Menu(Tab_menu, 5, Wybor);

case Wybor of

'1' : Wstaw_do_listy(Poczatek_DLN, Gdzie);

'2' : Usun_z_listy(Poczatek_DLN, Gdzie);

'3' : begin

Writeln(Dla_kazdego(Poczatek_DLN,Wydruk_danych)); Pauza(Z,False);

end;

'4' : Usun_Pamiec(Poczatek_DLN);

end;

until Wybor = 'K';

end.

8.3. Drzewo binarne poszukiwań

 typ proceduralny dla procedur przejścia przez drzewo

(11)

zrob= procedure(A: Osoba);

 definicja elementu drzewa POsobaD = ^ROsobaD;

ROsobaD = record

Dane: Osoba;

Lewy, Prawy: POsobaD;

end;

Budowa interfejsu

procedure Inicjalizacja( var Wezel : POsobaD);

{ działanie: inicjuje drzewo

warunki wstępne: Wezel wskazuje na pierwszy element, zwany korzeniem warunki końcowe: drzewo zostaje zainicjowane jako puste}

procedure Szukaj(Wezel : POsobaD; var Gdzie : POsobaD; Klucz : lan);

{ działanie: szuka elementu w drzewie

warunki początkowe: Wezel wskazuje na zainicjowane drzewo, Klucz jest poszukiwanym elementem,

warunki końcowe: jeśli to możliwe, procedura szuka elementu w drzewie o wartości równej Kluczowi idąc na lewo każdego z węzłów, jeśli element w węźle jest większy i na prawo, jeśli element w węźle jest mniejszy, natomiast jeśli znajdzie węzeł równy Kluczowi, Gdzie wskazuje na ten element drzewa, w przeciwnym wypadku zwraca adres pusty w Gdzie}

procedure Wstaw(var var Wezel, :Pozycja : POsobaD);

{działanie: dodaje element do drzewa

warunki początkowe: Pozycja jest daną do wstawienia do zainicjowanego drzewa

warunki końcowe: jeśli to możliwe, procedura dodaje daną Pozycja do drzewa idąc na lewo każdego z węzłów, jeśli element w węźle jest większy od Pozycja i na prawo, jeśli element w węźle jest mniejszy aż do osiągnięcia węzła z wolnym łączem, który po wstawieniu wskazuje na element Pozycja, natomiast jeśli znajdzie węzeł z elementem równym Pozycja, to kończy poszukiwania, usuwa element Pozycja i zwraca adres pusty w Pozycja }

(12)

procedure Usun(var Wezel : POsobaD; Klucz : lan);

{działanie: usuwa element z drzewa

warunki początkowe: Wezel jest zainicjowanym drzewem

warunki końcowe: jeśli jest to możliwe, procedura szuka elementu w drzewie równego Kluczowi idąc na lewo każdego z węzłów, jeśli element w węźle jest większy i na prawo, jeśli element w węźle jest mniejszy, natomiast jeśli znajdzie węzeł równy Kluczowi, to jeśli ma on tylko jednego następcę (prawego lub lewego), zostaje nim zastąpiony i następnie usunięty. W przeciwnym przypadku (węzeł równy Kluczowi nie jest liściem) procedura szuka elementu największego idąc w lewo wyszukanego węzła i potem w prawo lewego następcy, wstawia kopię wartości znalezionego elementu do usuwanego węzła, w miejsce skopiowanego elementu w drzewie podłącza jego lewego następcę oraz usuwa węzeł ze skopiowanym elementem, }

procedure Usun_pamiec(Wezel : POsobaD );

{ działanie: usuwa elementy z drzewa i inicjuje drzewo jako puste warunki początkowe: Wezel jest zainicjowanym drzewem

warunki końcowe: liczba elementów w drzewie jest równa 0, funkcja przechodzi przez wszystkie gałęzie aż do osiągnięcia liści i usuwa je z pamięci zaczynając zawsze od lewego liścia. Każdy węzeł z usuniętymi liśćmi staje się liściem }

procedure Dla_kazdego(Wezel : POsobaD; funkcja: zrob );

{działanie: wykonuje funkcje na każdym wstawionym elemencie do drzewa warunki początkowe: Węzeł jest zainicjowanym drzewem, zrob jest typem

funkcji, która pobiera element drzewa i nie zwraca wartości

warunki końcowe: jeśli jest to możliwe, procedura typu zrób jest wykonywana tylko raz dla każdego elementu wstawionego do drzewa zaczynając od najmniejszego elementu }

procedure Dla_jednego(Wezel : POsobaD; klucz: lan; funkcja: zrob);

{ działanie: wykonuje funkcja na elemencie wyszukanym w drzewie

warunki początkowe: Wezel jest zainicjowanym drzewem, zrob jest typem procedury, która pobiera element z drzewa i nie zwraca wartości

warunki końcowe: procedura typu zrób jest wykonywana tylko raz dla elementu z drzewa Wezel o wartości Klucza, jeśli zostanie wyszukany przez funkcję Szukaj}

(13)

8.3.1. Wstawianie do drzewa

Należy wstawić do drzewa ciąg: 8, 5, 9, 2, 11, 1, 4, 3, 10, 15, 13, 7 , 6

8

5 9

2

1

2 3

4 1 8

8

5

8

5 9

1 2

1

2 3

8

5 9

2

4

11 1 1

1

2 3

4

7

5

6 8

5 9

2 11

1

2 3

4 5

8

5 9

2 11

1

1

2 3

4 5

8

5 9

2

1

2 3

4

11 5

8

5 9

2

4 10

11

1

1

2 3

4

7 9

5

6 8

5 9

2

4 10

11

1

1

2 3

4

7 9

5

6 6

8

5 9

2

4

3 11

1

1

2 3

4

7

8 5

6

3 8

3 8

15 10 1

6

4 7

3 8

10 9

15 10

13 11 7

12

6 13 ...

procedure Wstaw(var Wezel,Nowy : POsobaD);

begin

if Wezel = nil then Wezel := Nowy;

else

if Wezel^.Dane.Nazwisko > Nowy^.Dane.Nazwisko then Wstaw(Wezel^.Lewy, Nowy)

else

if Wezel^.Dane.Nazwisko < Nowy^.Dane.Nazwisko then

(14)

8.3.2. Usuwanie z drzewa

8

5 9

2

4 10

11 1

1

2 3

4

7 9

5

6

3 8

15 10

13 11

8

5 9

2

4 10

11 1

1

2 3

4

7 9

5

6

15 10

13 11

8

5 9

2

4 10

11 1

1

2 3

4

7 9

5

6

13 11

8

5 9

2 4

10 1

1

2 3

4

7

9

6

13 11

7 9

2 4

10 1

3

4

7

9

6

13 11 7

12

7 12

7 12

7 12

5 12 2 613

6 13

6 13

6 13

6 13

procedure Usun(var Wezel : POsobaD; Klucz : lan);

var Usuwany : POsobaD;

procedure Usun_(var Lisc_Prawy : POsobaD);

begin

if Lisc_Prawy^.Prawy <> nil then Usun_(Lisc_Prawy^.Prawy)

else begin {wymiana danych usuwanych z liściem}

Usuwany^.Dane := Lisc_Prawy^.Dane;

Usuwany := Lisc_Prawy;

Lisc_Prawy := Lisc_Prawy^.Lewy; end;

end;

begin

if Wezel <> nil then

if Klucz<Wezel^.Dane.Nazwisko then Usun(Wezel^.Lewy, Klucz)

else if Klucz > Wezel^.Dane.Nazwisko then Usun(Wezel^.Prawy, Klucz) else {znaleziono element do usunięcia}

begin

Usuwany := Wezel;

if Usuwany^.Prawy = nil then Wezel := Usuwany^.Lewy else

if Usuwany^.Lewy = nil then Wezel := Usuwany^.Prawy else Usun_(Usuwany^.Lewy);

Dispose(Usuwany); end;

end;

(15)

8.3.3. Przeszukiwanie w drzewie

procedure Szukaj(Wezel : POsobaD; var Gdzie : POsobaD; Klucz : lan);

begin

if Wezel = nil then begin

Gdzie := nil; Exit;

end;

if Wezel^.Dane.Nazwisko = Klucz then Gdzie := Wezel else

if Wezel^.Dane.Nazwisko > Klucz then Szukaj(Wezel^.Lewy,Gdzie,Klucz) else

Szukaj(Wezel^.Prawy,Gdzie,Klucz) end;

8.3.4. Przejście przez drzewo

procedure Dla_kazdego(Wezel : POsobaD; funkcja: zrob);

begin

if Wezel <> nil then begin

Dla_kazdego(Wezel^.Lewy,funkcja);

funkcja(Wezel^.Dane);

Dla_kazdego(Wezel^.Prawy, funkcja) end;

end;

procedure Dla_jednego(Wezel : POsobaD; klucz:lan; funkcja: zrob);

var Gdzie: POsobaD;

begin

Szukaj(Wezel, Gdzie, klucz);

if Gdzie <> nil then funkcja(Gdzie^.Dane);

end;

8.3.5. Usunięcie drzewa

procedure Usun_drzewo(Wezel : POsobaD);

begin

if Wezel <> nil then begin

Usun_drzewo(Wezel^.Lewy);

Usun_drzewo(Wezel^.Prawy);

(16)

program Drzewo_binarne;

uses Crt, Rozne, Modul, MDrzewoB;

const Tab_menu : Lancuchy =

('1 :Wstawianie', '2 :Usuwanie', '3 :Wyswietlenie jednego',

'4 :Wydruk drzewa', '5 : Usun drzewo', 'K/k - Koniec programu','','','','','');

procedure Wstaw_do_drzewa(var Poczatek:POsobaD);

var Dana : Osoba; Nowy : POsobaD;

begin

Podaj_dane(Dana);

if Nowy_Element_D(Nowy, Dana) then begin

Wstaw(Poczatek, Nowy);

if Nowy <> nil then

Dla_jednego(Poczatek, Dana.Nazwisko, Wydruk_danych);

end;

end;

function Klucz: lan;

var Pom: lan;

begin

repeat Write('Podaj nazwisko: '); Readln(Pom); until Pom <> '';

Klucz:= Pom;

end;

var Wybor, Z : char; Poczatek_D: POsobaD;

begin

ClrScr; Randomize;

Inicjalizacja(Poczatek_D);

repeat

Menu(Tab_menu, 6, Wybor);

case Wybor of

'1' : Wstaw_do_drzewa(Poczatek_D);

'2' : Usun_element_drzewa(Poczatek_D, Klucz);

'3' : Dla_jednego(Gdzie^.Dane, Klucz, Wydruk_danych);

'4' : Dla_kazdego(Poczatek_D, Wydruk_danych);

'5' : begin

Usun_drzewo(Poczatek_D); Poczatek_D :=nil;

end;

end;

Pauza(Z, False);

until Wybor = 'K';

end.

Cytaty

Powiązane dokumenty

Używając pakietu R, przeprowadzić analizy opisane w Rozdziale 8 książki Agresti (2002) dla danych ankietowych dotyczących używek (A-Alcohol, C-Cigarette, M-Marijuana) z Tabeli

Ziemia gromadzi wypadkowy ładunek, który wytwarza pole o natężeniu 150 N/C, skierowane do środka planety.. Jaki jest znak i wielkość ładunku zgromadzonego

Określ długość pręta drgającego z taką samą

W ściance bocznej dużego zbiornika, 5 m pod powierzchnią lustra wody znajduje się malutki otwór. Do jakiego ciśnienia należy napompować dętkę, aby zapewnić

Określ długość pręta drgającego z taką samą częstotliwością.. Oblicz maksymalną wartość energii potencjalnej i

• Jeśli lista jest pusta (rozpoznajemy po tym, że pierwszy wskaźnik nadal wskazuje na początek listy, a drugi pozostał na NULL):. • dodajemy element

Na kolejnych slajdach przedstawiono podstawowe operacje na liście dwukierunkowej:. • dodanie elementu na początku

Zad 3) Zestaw lampek choinkowych składa się z żarówek o napięciu znamionowym 14V i mocy 5W. Z ilu żarówek musi składad się zestaw, aby mógł byd zasilany