Upload
matteo
View
77
Download
1
Embed Size (px)
DESCRIPTION
Złożone typy danych. Złożone typy danych – listy. Złożone typy danych – listy jednokierunkowe. Złożone typy danych – listy jednokierunkowe. Pola: głowa, ogon i następny są wskaźnikami, natomiast wartość może być czymkolwiek: liczbą, znakiem, rekordem, itp. - PowerPoint PPT Presentation
Citation preview
Złożone typy danych
Listy •Tworzenie elastycznych baz danych
Drzewa binarne
•Analiza symboliczna wyrażeń arytmetycznych
Grafy •Zagadnienia z dziedziny sztucznej inteligencji
Złożone typy danych – listy
Złożone typy danych – listy jednokierunkowe
Złożone typy danych – listy jednokierunkowe
Pola: głowa, ogon i następny są wskaźnikami, natomiast wartość może być czymkolwiek: liczbą, znakiem, rekordem, itp.
Złożone typy danych – listy jednokierunkowe
Przykład.Lista złożona z trzech elementów: 2, -12, 3.
Jeśli lista jest pusta, to struktura informacyjna zawiera dwa wskaźniki i NULL.
Pierwszy element listy jest złożony z jego własnej wartości (informacji do przechowania) oraz ze wskaźnika na drugi element listy, itd.
Złożone typy danych – listy jednokierunkowe
adres_tmp=info.głowadopóki (adres_tmp !=NULL)wykonuj{ jeśli(adres_tmp.wartość==x)to { wypisz "Znalzałem poszukiwany element" opuść procedurę } w przeciwym wypadku adres_tmp=adres_tmp.nastepny}wypisz "Nie znalazłem poszukiwanego elementu"
Tak może wyglądać procedura przeglądająca elementy listy w poszukiwaniu wartości x
Złożone typy danych – listy jednokierunkowe
Dla reprezentacji list jednokierunkowych typ w C++ może być zdefiniowany następująco:
struct element { int liczba; element *następny; };typedef element *adres;
Pozwala on konstruować listy jednokierunkowe (acykliczne) o długości ograniczonej wielkością tzw. sterty.
Typ może być dowolny, dla prostoty używamy
typu int.
Złożone typy danych – listy jednokierunkowe
Opisana poniżej funkcja realizuje operację wpisania na początek listy o adresie pierwszy liczbę całkowitą i. Funkcja zwraca adres pierwszego elementu listy rozbudowanej.
adres wstaw_na_stos(adres pierwszy, int x){ element *a; a = new element; //a) (*a).liczba = x; //b) (*a).następny = pierwszy; //c) return a;}
a
a
ptr
Ilustracja kodu
Złożone typy danych – listy jednokierunkowe
Dużo bardziej złożona jest funkcja dołączająca nowy element w takie miejsce, aby całość listy była widziana jako posortowana. Ideę przedstawia rysunek:
Nowy element może zostać wstawiony na początek (a), koniec (b) lub w środek (c). W istniejącej liście trzeba zrobić
miejsce wstawienia, tzn. zapamiętać dwa wskaźniki: element, przed którym mamy wstawić nową
komórkę i element, za którym trzeba to zrobić. Mogą być to zmienne
przed i po.
Złożone typy danych – listy jednokierunkowe
Schemat wstawiania:
Ćwiczenie: Implementacja
Złożone typy danych – listy jednokierunkowe
adres lista(int n){ adres pierwszy = NULL; pierwszy = wstaw_na_stos(pierwszy,random(5*n)); int i; for(i =1;i<=n-1;i++) pierwszy = wstaw_na_stos(pierwszy,random(5*n)); return pierwszy;}
Następująca funkcja konstruuje dla liczby naturalnej n, listę jednokierunkową losowo wybranych liczb naturalnych z przedziału od 0 do 5n.
Złożone typy danych – listy jednokierunkowe
adres zdejm_se_stosu(adres pierwszy, int x){ adres zdjety; if (pierwszy != NULL) { zdjety = pierwszy; pierwszy = (*pierwszy).nastepny; } return zdjety; }
Funkcja opisana poniżej usuwa z listy element o adresie pierwszy, określający początek listy. Funkcja zwraca adres usuwanego elementu. Zmienna pierwszy nadal przechowuje adres początku nowej listy.
Złożone typy danych – listy jednokierunkowe
Wady Zalety
Nienaturalny dostęp do elementów
Małe zużycie pamięci
Niełatwe sortowanie Elastyczność
Problem:
Lista, do której nowe elementy wstawiamy zgodnie z pewnym porządkiem jest idealna, gdy mamy tylko jedno kryterium sortowania.
Co zrobić, gdy elementami listy są rekordy o bardziej skomplikowanej strukturze? struct
{char imie[20];char nazwisko[30];int wiek;int kod_pracownika;}
Złożone typy danych – listy jednokierunkowe
Możliwości sortowania
Alfabetycznie, wg nazwisk
Wiek pracownika
Kod pracownika
Jak rozwiązać?
3 wersje list?
Sortowanie list w pamięci?
Obok listy danych dysponujemy kilkoma listami wskaźników do nich – tyle list, ile kryteriów sortowania!
Podczas sortowania list wskaźników dane w ogóle nie są ruszane – przemieszczaniu ulegają same wskaźniki.
Złożone typy danych – listy jednokierunkowe
Złożone typy danych – listy jednokierunkowe
Tablicowa reprezentacja listy:
I sposób (klasyczna reprezentacja):• i-temu elementowi indeksu tablicy odpowiada i-ty element listy;•musimy zarezerwować dużo miejsca, a lista ostatecznie może być krótka;•trzeba wybrać zmienną, która zapamięta aktualną ilość elementów wstawionych wcześniej do listy.
Złożone typy danych – listy jednokierunkowe
Tablicowa reprezentacja listy:
II sposób (metoda tablic równoległych):• deklarujemy tablicę rekordów składających się z pola informacyjnego „info” („liczba”, „wartość”) i pola typu całkowitego „nastepny”, które służy do odszukania następnego elementu na liście;•można tu oddzielać tablice i mieć jedną tablicę na dane, a drugą na wskaźniki, lub nawet kilka tablic na wskaźniki ( w zależności od sposobu posortowania danych).
Złożone typy danych – listy jednokierunkowe
Przykład:
P R Z Y K Ł A D
5 2 -1 4 1 6 8 3 7 ?
A D K Ł P R Y Z ?
T[0]
T[1]
T[2]
T[3]
T[4]
T[5]
T[6]
T[7]
T[8]
następny
info
•T[0].następny – indeks pierwszego rzeczywistego elementu listy: 5,
czyli w t[5].info znajduje się „P”
•Odczytujemy T[5].następny, tj. 6, więc w T[6].info jest „R”
•Odczytujemy T[6].następny, itd.
Złożone typy danych – listy jednokierunkowe
Przykład: Minibaza danych zgrupowana w wyodrębnionej tablicy danych i trzy odrębne tablice wskaźników
Złożone typy danych – listy dwukierunkowe
Złożone typy danych – listy dwukierunkowe
Lista dwukierunkowa: Pierwsza komórka na liście nie ma swojego poprzednika, zaznaczamy
to wpisując NULL do pola poprzedni; Ostatnia komórka nie posiada swojego następnika; zaznaczamy to,
wpisując wartość NULL do pola następny.
Zaletą listy dwukierunkowej jest szybkość działania, wadą –
większa ilość pamięci niż w przypadku listy jednokierunkowej.
Złożone typy danych – listy dwukierunkowe
Dla reprezentacji list dwukierunkowych typ w C++ może być zdefiniowany następująco:
struct element { int liczba; element *następny; element *poprzedni; };typedef element *adres;
Schemat usuwanie elementu p z listy dwukierunkowej
Ćw
iczenie
: Sch
em
at
wsta
wia
nia
.
Złożone typy danych – listy cykliczne
Lista cykliczna jest zamknięta w pierścień: wskaźnik ostatniego elementu wskazuje „pierwszy” element. Element „pierwszy” jest wskazany umownie.
Przykład: Problem Josephusa.
n osób postanowiło wybrać przywódcę, robiąc wyliczankę m-sylabową, stojąc w kole. Na kogo padnie ostatnia, m-ta sylaba wyliczanki, ta odpada.
Złożone typy danych – listy cykliczne
Przykład: Rozwiązanie problemu Josephusa.
n osób postanowiło wybrać przywódcę, robiąc wyliczankę m-sylabową, stojąc w kole. Na kogo padnie ostatnia, m-ta sylaba wyliczanki, ta odpada.
•Tworzymy listę n-elementową cykliczną, zaczynając od jednego elementu, który wskazuje na siebie i wstawiamy za nim pozostałe elementy;•Przetwarzamy listę odliczając m-1 elementów i usuwamy element o numerze m.
Implementacja w C++:
Złożone typy danych – listy cykliczne
#include <iostream>struct element //element listy { int info; element *next; element(int x, element *t) {info = x; next =t;} }; typedef element *link;int main(int argc, char *argv[]){ //n-liczba elementów listy, m-oznacza, który element usuwamy int i,n =atoi(argv[1]),m=atoi(argv[2]); link t= new element(1,0); //pierwszy element listy t->next=t; link x=t; for(i=2;i<=n;i++) //utworzenie n-elementowej listy x=(x->next = new element(i,t)); while(x!=x->next) { for(i=1;i<m;i++) x=x->next; //przesuwanie listy o m elementów x->next=x->next->next; //usuwanie elementu z listy } std:: cout<<x->info<<std::endl; //wyświetlanie danych std:: cout<<"Nacisnij <Enter>, aby kontynuowac.\n"; std:: cin.get(); return 0;}
/*deklaracja funkcji odpowiedzialnej za zamianę z char na liczbę integer*/int atoi(char[]);
Złożone typy danych – stos
Stos jest strukturą danych, do której dostęp jest możliwy tylko od strony tzw. wierzchołka.
Last In
First Out LIFO
ang.
push(x) – dokładanie danych na wierzchołek stosupop(x) – zdjęcie, pobranie elementu x z wierzchołka stosu
Nazwy funkcji wstaw_na_stos i zdejm_ze_stosu użyte wcześniej, nie zostały wybrane przypadkowo.
Acykliczna lista jednokierunkowa wyposażona w funkcje dopisywania do listy pierwszego elementu i usuwania pierwszego elementu nosi właśnie nazwę stosu.
Złożone typy danych – stos
Stos i podstawowe operacje na nim:
1. Stos tutaj ma pojemność dwóch elementów, na użytek przykładu, aby zilustrować efekt przepełnienia.
2. Symboliczny stos znajdujący się pod każdą z 6 grup instrukcji ukazuje zawsze stan po wykonaniu „swojej” grupy instrukcji.
Stos można implementować jako listę lub tablicę.
Złożone typy danych – kolejka FIFO
First In
First Out FIFO
ang.
First in First out
1. Kolejka (jak stos) zakłada dostęp ograniczony.
2. Dwie podstawowe operacje: wstaw (wprowadź dane na ogon kolejki) i obsłuż (usuń – pobierz dane z czoła kolejki.
Kolejka FIFO to inaczej acykliczna lista jednokierunkowa wyposażona w funkcje wstawiania na początek listy i usuwania elementu ostatniego na liście.
Złożone typy danych – kolejka FIFO
Implementacja może być za pomocą list jednokierunkowych lub za pomocą tablic.
Złożone typy danych – kolejka FIFO
#include<stdio.h>#include<stdlib.h>
struct elkol // przykładowa struktura kolejki{ int wart; struct elkol *nast;};
struct kolejka{ struct elkol *pocz; struct elkol *kon;};
void init(struct kolejka **k); //inicjowanie funkcji init
int main(void) //główny program{ struct kolejka *ko; init(&ko); return 0;};
void init(struct kolejka **k) //definiowanie funkcji init{ (*k)->pocz = NULL; (*k)->kon = NULL;}
Przy
kładow
a im
ple
menta
cja
Złożone typy danych – kolejka FIFO
void initT(struct kolejkaT **kol){ (*kol)->p = 0; (*kol)->k = 0;}
int EmptyT(struct kolejkaT **kol){ return (kol->k ==kol->p);}
Funkcja ustawia kolejkę pustą
Czy kolejka jest pusta
void PushT(struct kolejkaT **kol, int x){ (*kol)->tabS[(*kol)->k] = x; (*kol)->k++; (*kol)->k = (*kol)->k%N;}
Funkcja dodaje element na koniec
Złożone typy danych – kolejka FIFO
int FirstT(struct kolejkaT *kol){ return kol->tabS[kol->p];}
Funkcja podaje adres pierwszego elementu
int LastT(struct kolejkaT *kol){ return kol->tabS[kol->k-1];}
Funkcja podaje adres ostatniego elementu
int PoptT(struct kolejkaT *kol){ int elem = kol->tabS[kol->p]; kol->p = ((kol->p) + 1)%N; return elem;}
Funkcja ściąga pierwszy element
Złożone typy danych – kolejka FIFO
#include<stdio.h>#include<stdlib.h>#define N 100struct kolejkaT{ int tabS[N]; int p, k;};void initT(struct kolejkaT **kol);void PushT(struct kolejkaT **kol, int x);int main(void){ struct kolejkaT *ko; initT(&ko); PushT(&ko,2); PushT(&ko,7); return 0;}void initT(struct kolejkaT **kol){ (*kol)->p = 0; (*kol)->k = 0;}void PushT(struct kolejkaT **kol, int x){ (*kol)->tabS[(*kol)->k] = x; (*kol)->k++; (*kol)->k = (*kol)->k%N;}
Przykład dodania elementów do kolejki