You are on page 1of 46

Složene strukture izvedene

uporabom povezane liste


Upoznat ćemo tri korisne varijacije
povezane liste:
Kružna jednostruko povezana lista
Dvostruko povezana lista
Višestruko povezana lista

1
Kružna jednostruko povezana lista

Kružna povezana lista je poseban tip povezane


liste.
Podržava obilazak liste od kraja liste prema
početku jer zadnji čvor liste pokazuje na prvi
čvor liste (na glavu liste).
Pokazivač na zadnji element se često koristi
umjesto pokazivača na glavu liste.

10 30 50 55 80

zadnji
2
Motivacija

Kružne povezane liste su obično


uređene.
Kružne liste su korisne npr. za
izvođenje video i zvučnih zapisa
(datoteka) u petlji.
Korisne su i u izvedbi grafa kao
važne strukture podataka.

3
Definicija kružne jednostruko
povezane liste

struct Cvor{
int podatak;
Cvor* slijedeci;
};
Cvor *zadnji=0;

4
Operacije na kružnoj jednostruko
povezanoj listi

umetniCvor(Cvor *& zadnji, int podatak)


//dodaje novi čvor kružnoj povezanoj listi

brisiCvor(Cvor *& zadnji, int podatak)


//briše čvor u kružnoj povezanoj listi

ispis(Cvor * zadnji)
//ispisuje elemente kružne povezane liste

5
Obilazak liste
void ispis(Cvor * zadnji){
Cvor * tekuci;
if(zadnji != 0){ // za nepraznu listu
tekuci = zadnji->slijedeci; // počinjemo sa 1. elementom
do{
cout << tekuci->podatak << " ";
tekuci = tekuci->slijedeci;
}while(tekuci != zadnji->slijedeci);
cout << endl;
}
10 30 35 55 60

6
zadnji
Umetanje čvora
Umetanje u praznu listu
20

Cvor * novi = new Cvor; zadnji

novi->podatak = 20; novi

zadnji = novi;
zadnji->slijedeci = zadnji; // to je i prvi čvor

7
Umetanje prvog čvora (glave) u kružnu
povezanu listu (između preth i tekuci)
Cvor * novi = new Cvor;
novi->podatak = 20;
novi->slijedeci = tekuci;
// isto kao: novi->slijedeci = zadnji->slijedeci;
preth->slijedeci = novi; // isto kao: zadnji->slijedeci = novi;

20 35 40 65 70

novi tekuci preth


zadnji 8
Umetanje čvora u sredinu kružne
povezane liste između čvorova preth i
tekuci
novi->slijedeci = tekuci;
preth->slijedeci = novi; // kao kod umetanja glave!

5 30 55 70

40
preth tekuci zadnji

novi
9
Umetanje na kraj kružne povezane liste
novi->slijedeci = tekuci;
// isto kao: novi->slijedeci = zadnji->slijedeci;
preth->slijedeci = novi;
// isto kao: zadnji->slijedeci = novi;
zadnji = novi; // novi čvor postaje zadnji u listi

10 30 40 55 70

tekuci preth novi


zadnji 10
void umetniCvor(Cvor *& zadnji, int broj){
Cvor *novi, *tekuci, *preth; 30
novi = new Cvor;
novi->podatak = broj;
if(zadnji == NULL){ // umetanje u praznu listu zadnji
zadnji = novi;
novi
zadnji->slijedeci = zadnji;
return; // završetak izvođenja funkcije
}
preth = zadnji; // preth se postavlja na zadnji element liste
tekuci = zadnji->slijedeci; // usmjeravanje na prvi element u listi
do{ // nadji preth i tekuci - lista je uređena
if(broj <= tekuci->podatak) // uzlazno!
break;
preth = tekuci;
tekuci = tekuci->slijedeci;
}while(tekuci != zadnji->slijedeci);

// slijedeći slajd ->


11
novi->slijedeci = tekuci; // usmjeri pokazivače
preth->slijedeci = novi;
if(broj > zadnji->podatak) // usmjeri pokazivač zadnji kod
zadnji = novi; // dodavanja na kraj
}

5 30 55 70

40
preth tekuci zadnji

novi

12
Brisanje čvora
Brisanje čvora u jednočlanoj kružnoj
povezanoj listi
zadnji = NULL;
40
delete tekuci;

zadnji = tekuci = preth

13
Brisanje čvora na mjestu glave liste u
kružnoj povezanoj listi
preth->slijedeci = tekuci->slijedeci;
// isto kao: zadnji->slijedeci = tekuci->slijedeci
delete tekuci;

5 30 50 55 90

zadnji preth
tekuci
14
Brisanje čvora tekuci u sredini kružne
povezane liste

preth->slijedeci = tekuci->slijedeci;
delete tekuci;

5 10 20 75 90

preth tekuci zadnji

15
Brisanje zadnjeg čvora u kružnoj povezanoj
listi
preth->slijedeci = tekuci->slijedeci;
// isto kao: zadnji->slijedeci;
delete tekuci;
zadnji = preth;

5 10 15 25 30

preth tekuci
zadnji 16
void brisiCvor(Cvor *& zadnji, int broj){
Cvor *tekuci, *preth;
if(zadnji == NULL){
cout << "Lista je prazna!" << endl;
return;
}
preth = zadnji;
tekuci = zadnji->slijedeci;
do{ // nađi preth i tekuci
if(broj <= tekuci->podatak) break; // uređena lista
preth = tekuci;
tekuci = tekuci->slijedeci;
}while(tekuci != zadnji->slijedeci);

17
if(tekuci->podatak != broj){ //podatak nije u listi
cout << "Podatak nije nadjen!" << endl;
return;
}
if(tekuci == preth){ // briši jedini čvor liste
zadnji = NULL;
delete tekuci;
return;
}
if(tekuci == zadnji) // usmjeri pokazivač zadnji
zadnji = preth; // ako se briše kraj liste
preth->slijedeci = tekuci->slijedeci; // preusmjeri
delete tekuci; // pokazivače

}
18
void main(){
Cvor *zadnji = NULL;
Izvorni kod: kpl1.cpp

umetniCvor(zadnji, 2);
umetniCvor(zadnji, 3);
umetniCvor(zadnji, 6);
umetniCvor(zadnji, 4);
umetniCvor(zadnji, 9);
ispis(zadnji);
brisiCvor (zadnji, 2);
brisiCvor(zadnji, 9);
brisiCvor(zadnji, 3); Ispis:
ispis(zadnji); 23469
umetniCvor(zadnji, 7); 46
umetniCvor(zadnji, 9); 4679
ispis(zadnji);
}
19
Dvostruko povezana lista
U dvostruko povezanoj listi svaki čvor je
povezan i sa prethodnim i sa slijedećim
čvorom.
preth pokazuje na prethodnika
slijedeci pokazuje na sljedbenika

10 30 50 55 70

glava
tekuci->preth tekuci tekuci->slijedeci

20
Motivacija
Dvostruko povezana lista je korisna za
prikaz video i zvučnih zapisa (u
datotekama), uz premotavanje (rewind) i
ponovni prikaz (instant replay).
Korisne su i za druge povezane podatke
koji zahtijevaju "premotavanje unatrag" i
"brzi prijelaz podataka" (fast forward).
Prikaz snopa karata u igri, “undo” u
Wordu, cache memorija pretraživača,
binarno stablo
21
Definicija dvostruko povezane liste

struct Cvor{
int podatak;
Cvor* slijedeci;
Cvor* preth;
};
Cvor *glava;

22
Operacije na dvostruko povezanoj
listi
umetniCvor(Cvor *&glava, int podatak)
dodaje novi čvor u uređenu dvostruko povezanu listu

brisiCvor(Cvor *&glava, int podatak)


briše čvor u dvostruko povezanoj listi

traziCvor(Cvor *glava, int podatak)


traži čvor u dvostruko povezanoj listi

ispis(Cvor *glava)
23
ispisuje elemente liste
Brisanje čvora
Brisanje čvora tekuci (nije prvi ni zadnji)
(tekuci->preth)->slijedeci = tekuci->slijedeci;
(tekuci->slijedeci)->preth = tekuci->preth;
delete tekuci;

10 30 40 65 80

glava
tekuci
24
Umetanje čvora
Umetanje čvora novi prije čvora tekuci
(nije prvi ni zadnji)
novi->slijedeci = tekuci;
novi->preth = tekuci->preth;
tekuci->preth = novi;
(novi->preth)->slijedeci = novi;

10 30 65 80

glava 40
tekuci

novi 25
Dvostruko povezane liste sa lažnim
prvim čvorom
Da bi pojednostavili umetanje i brisanje
i izbjegli slučajeve brisanja i umetanja
na mjestu prvog i zadnjeg elementa, na
početak liste dodajemo lažni čvor.
Zadnji čvor pokazuje na lažni prvi čvor
kao svog sljedbenika.

26
Dvostruko povezane liste sa lažnim prvim
čvorom

Neprazna lista
Lažni čvor

10 30 40 55 80

glava

Prazna lista Lažni čvor

glava
27
void kreirajGlavu(Cvor*& glava){
glava = new Cvor;
glava->slijedeci = glava;
glava->preth = glava;
}

28
Brisanje čvora
Brisanje čvora tekuci na početku
(tekuci->preth)->slijedeci = tekuci->slijedeci;
(tekuci->slijedeci)->preth = tekuci->preth;
delete tekuci;

Lažni čvor
10 30 40 65 80

glava tekuci

29
Brisanje čvora tekuci u sredini

(tekuci->preth)->slijedeci = tekuci->slijedeci;
(tekuci->slijedeci)->preth = tekuci->preth;
delete tekuci; // isto kao brisanje prvoga!

Lažni čvor
10 30 40 65 70

tekuci
glava

30
Brisanje čvora tekuci kao zadnjeg
čvora liste
(tekuci->preth)->slijedeci = tekuci->slijedeci;
(tekuci->slijedeci)->preth = tekuci->preth;
delete tekuci; // isto kao brisanje prvog i srednjeg
čvora!

Lažni čvor
10 30 40 65 70

glava tekuci

31
void brisicvor(Cvor * glava, int broj){
Cvor * tekuci;
tekuci = traziCvor(glava, broj);
if(tekuci != NULL){
tekuci->preth->slijedeci = tekuci->slijedeci;
tekuci->slijedeci->preth = tekuci->preth;
delete tekuci;
}
}

32
Umetanje čvora
Umetanje čvora novi nakon lažnog
čvora a prije čvora tekuci
novi->slijedeci = tekuci;
novi->preth = tekuci->preth;
tekuci->preth = novi;
(novi->preth)->slijedeci = novi;

Lažni čvor
30
10
glava novi tekuci
33
Umetanje čvora novi u sredinu prije čvora
tekuci
novi->slijedeci = tekuci;
novi->preth = tekuci->preth;
tekuci->preth = novi;
(novi->preth)->slijedeci = novi; // isto kao umetanje na
// početak!

Lažni čvor

10 30 65
40

novi tekuci
glava
34
Umetanje čvora novi na poziciju zadnji
(tekuci pokazuje na lažan čvor)
novi->slijedeci = tekuci;
novi->preth = tekuci->preth;
tekuci->preth = novi;
(novi->preth)->slijedeci = novi; // isto kao umetanje na
// početak!

Lažni čvor

10 30 40 65 70

tekuci glava novi

35
Umetanje čvora novi u praznu listu
(tekuci pokazuje na lažan čvor)
novi->slijedeci = tekuci;
novi->preth = tekuci->preth;
tekuci->preth = novi;
(novi->preth)->slijedeci = novi;

Lažni čvor

30

glava tekuci novi

36
void umetniCvor(Cvor *glava, int broj){
Cvor *novi, *tekuci;
novi = new Cvor;
novi->podatak = broj;

tekuci = glava->slijedeci; // 1. čvor je lažni!


while(tekuci != glava){ //pozicija za umetanje
if(tekuci->podatak < broj) //uzlazna lista
tekuci = tekuci->slijedeci;
else
break;
}
// slijedeći slajd-> 37
novi->slijedeci = tekuci;
novi->preth = tekuci->preth;
tekuci->preth = novi;
(novi->preth)->slijedeci = novi;
}

38
Traženje čvora:
Cvor * traziCvor(Cvor *glava, int broj){
Cvor * tekuci = glava->slijedeci;
while(tekuci != glava){
if(tekuci->podatak == broj)
return tekuci;
if(tekuci->podatak < broj)
tekuci = tekuci->slijedeci;
else
break;
}
return NULL;
} 39
Ispis liste:

void ispis(Cvor *glava){


Cvor * tekuci=glava->slijedeci;
while(tekuci != glava){
cout << tekuci->podatak << " ";
tekuci = tekuci->slijedeci;
}
cout << endl;
}

40
void main(){
Cvor *glava, *temp;
kreirajGlavu(glava);
Izvorni kod: kdpl1.cpp
ispis(glava);
umetniCvor(glava, 2);
ispis(glava);
umetniCvor(glava, 6);
ispis(glava);
umetniCvor(glava, 7);
ispis(glava); Ispis:
umetniCvor(glava, 4);
umetniCvor(glava, 3); 2
umetniCvor(glava, 9); 26
ispis(glava); 267
brisiCvor(glava, 5); 234679
brisiCvor(glava, 6); 23479
ispis(glava); Podatak se nalazi u listi.
temp = traziCvor(glava, 7);
if(temp != NULL)
cout << "Podatak se nalazi u listi." << endl;
else
cout << "Podatak se ne nalazi u listi." << endl;
41
}
Višestruko povezane liste

Višestruko povezana lista je lista sa dva ili više


logičkih sljedova ključeva.
Npr., promotrimo listu koja sadrži prvih deset
predsjednika SAD-a.
Listu možemo sortirati prema:
Datumu ulaska u Bijelu kuću.
Abecedno temeljeno na prezimenu predsjednika.
Abecedno prema djevojačkom prezimenu predsjednikove
supruge.
itd.
42
Višestruko povezane liste
Pretpostavimo da želimo imati listu uređenu
prema svakom od ovih kriterija.
Podaci kod višestruko povezane liste postoje
samo u jednom primjerku u listi, ali postoje
različiti pokazivači za različite liste.

43
Primjeri sa kviza
1. Slijedeća funkcija treba vratiti duljinu povezane liste. Što
nije u redu?
int duljina(Cvor *glava) {
int velicina = 0;
Cvor * tekuci;
while(tekuci != NULL){
velicina++;
tekuci = tekuci->slijedeci;
}
}

44
2. Slijedeća funkcija treba ispisati kružnu jednostruko
povezanu listu. Što nije u redu?

void ispis(Cvor *zadnji){


Cvor *tekuci;
tekuci = zadnji;
while(tekuci!=NULL){
cout << tekuci->podatak << " ";
tekuci = tekuci->slijedeci;
}
cout << endl;
}

45
3. Slijedeća funkcija treba kreirati lažan prvi čvor dvostruko
povezane liste. Što nije u redu?
void kreirajGlavu(Cvor * glava){
glava = new Cvor;
glava->slijedeci = NULL;
glava->preth = NULL;
}

46

You might also like