33
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

  • 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

Page 1: Złożone typy danych

Złożone typy danych

Listy •Tworzenie elastycznych baz danych

Drzewa binarne

•Analiza symboliczna wyrażeń arytmetycznych

Grafy •Zagadnienia z dziedziny sztucznej inteligencji

Page 2: Złożone typy danych

Złożone typy danych – listy

Page 3: Złożone typy danych

Złożone typy danych – listy jednokierunkowe

Page 4: Złożone typy danych

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.

Page 5: Złożone typy danych

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.

Page 6: Złożone typy danych

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

Page 7: Złożone typy danych

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.

Page 8: Złożone typy danych

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

Page 9: Złożone typy danych

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.

Page 10: Złożone typy danych

Złożone typy danych – listy jednokierunkowe

Schemat wstawiania:

Ćwiczenie: Implementacja

Page 11: Złożone typy danych

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.

Page 12: Złożone typy danych

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.

Page 13: Złożone typy danych

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;}

Page 14: Złożone typy danych

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.

Page 15: Złożone typy danych

Złożone typy danych – listy jednokierunkowe

Page 16: Złożone typy danych

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.

Page 17: Złożone typy danych

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).

Page 18: Złożone typy 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.

Page 19: Złożone typy danych

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

Page 20: Złożone typy danych

Złożone typy danych – listy dwukierunkowe

Page 21: Złożone typy danych

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.

Page 22: Złożone typy danych

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

.

Page 23: Złożone typy danych

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.

Page 24: Złożone typy danych

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++:

Page 25: Złożone typy danych

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[]);

Page 26: Złożone typy danych

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.

Page 27: Złożone typy danych

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ę.

Page 28: Złożone typy danych

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.

Page 29: Złożone typy danych

Złożone typy danych – kolejka FIFO

Implementacja może być za pomocą list jednokierunkowych lub za pomocą tablic.

Page 30: Złożone typy danych

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

Page 31: Złożone typy danych

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

Page 32: Złożone typy danych

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

Page 33: Złożone typy danych

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