3. Jednosmerný lineárny zoznam
3.2 Vytvorenie zoznamu, pridanie nového prvku
Kvôli zjednodušeniu budeme pracovať s lineárnym
zoznamom znakov. Najskôr si definujme vhodné typy a deklarujme
potrebné premenné - ukazovatele, pomocou ktorých budeme so zoznamom
pracovať:
#include <stdlib.h>
typdef struct prvok {
int hodnota;
struct prvok *dalsi;
} TPrvok;
TPrvok *z, *k, *p;
Deklarovali sme 3 pointery: jeden bude ukazovať na
začiatok zoznamu, druhý na koniec, tretí poslúži v prípade potreby
ako pomocný pointer.
Nový zoznam, ktorý bude na začiatku prázdny, vytvoríme príkazom
z = NULL;
Ak teraz chceme pridať do zoznamu prvok, ktorého hodnotovú časť prečítame zo vstupu, musíme najprv vytvoriť novú dynamickú premennú a potom zabezpečiť pripojenie nového prvku do zoznamu.
Prvky budeme pridávať na koniec zoznamu. Kreslite si na papier ! :-)
Pridáme do zoznamu prvý prvok:
z = (TPrvok*)malloc(sizeof(TPrvok)); |
v pamäti sa alokuje miesto pre prvý prvok zoznamu |
z->hodnota = getchar(); |
načíta sa hodnota zo vstupu |
z->dalsi = NULL; |
hodnota pointeru dalsi je NULL, prvok nemá nasledovníka |
Pridanie druhého prvku
Príkazom z = (TPrvok*)malloc(sizeof(TPrvok)); by sme už navždy stratili prvý prvok, preto musíme použiť pomocný ukazovateľ:
p = (TPrvok*)malloc(sizeof(TPrvok)); |
v pamäti sa alokuje miesto pre druhý prvok zoznamu |
p->hodnota = getchar(); |
načíta sa hodnota zo vstupu |
p->dalsi = NULL; |
pridaný prvok je posledný v zozname, nemá nasledovníka |
z->dalsi = p; |
spojenie
prvého prvku s práve pridaným - ukazovateľ dalsi v prvom prvku
teraz ukazuje na pridaný prvok t.j. tam kde ukazuje p |
Pridanie tretieho prvku by potom vyzeralo takto:
p = (TPrvok*)malloc(sizeof(TPrvok)); p->hodnota = getchar(); p->dalsi = NULL; z->dalsi->dalsi = p; |
Tento spôsob pridávania prvkov do zoznamu je očividne
dosť nepraktický, pre dlhšie zoznamy v podstate nepoužiteľný. Ak
by sme totiž pridávali prvky do zoznamu týmto spôsobom, museli by sme
napr. pri piatom prvku napísať:
z->dalsi->dalsi->dalsi->dalsi->dalsi = p;
čo určite nemožno pokladať za najvhodnejšie riešenie.
Oveľa výhodnejšie je mať k dispozícii nielen
ukazovateľ, ktorý ukazuje na začiatok zoznamu, ale aj ukazovateľ, ktorý
ukazuje na koniec, čiže posledný prvok zoznamu. Pridať nový prvok na
koniec zoznamu je potom "maličkosť".
Ukazovateľ
na koniec zoznamu je možné získať aj bez toho, aby sme si ho uchovávali
v samostatnej premennej. Stačí prejsť zoznamom postupne od prvého
prvku (ukazovateľ na začiatok zoznamu poznáme) až po posledný !
Príslušná procedúra môže vyzerať napr. takto:
void pridaj(TPrvok **z, TPrvok **k)
{
TPrvok *p;
printf("\nzadaj hodnotu prvku: ");
if (*z == NULL) {
*z = (TPrvok*)malloc(sizeof(TPrvok));
(*z)->hodnota = getchar();
(*z)->dalsi = NULL;
*k = *z;
}
else {
p = (TPrvok*)malloc(sizeof(TPrvok));
p->hodnota = getchar();
p->dalsi = NULL;
(*k)->dalsi = p;
*k = p;
}
}
|
OBRÁZOK
OBRÁZOK |
V programe potom stačí túto funkciu zavolať príkazom:
pridaj(&z, &k);
Oba parametre sú volané odkazom,
t.j. po vykonaní funkcie budú obsahovať ukazovateľ na nový začiatok (v
prípade pridávania prvého prvku) a nový koniec zoznamu (pridanie
ďalších prvkov). Do funkcie sa ako parametre odovzdávajú adresy
ukazovateľov z, k . Preto je nevyhnutné vo funkcii použiť zápis *z, *k !
Pridávaním prvkov na koniec zoznamu zachovávame aj ich poradie t.j. prvky budú v zozname uložené v takom poradí, v akom sme ich zadali zo vstupu.
Jednosmerný lineárny zoznam, ktorý bude mať 10 prvkov, môžeme teda vytvoriť napr. takto: z = k = NULL;
for (int i = 1; i <= 10; i++) pridaj(&z, &k);
Precvičme si
Možno
ste si práve položili otázku: "A čo takto rozširovať zoznam na
začiatku?" Dobrý nápad! Niekedy sa nám môže hodiť aj tento prístup,
prvky v zozname budú totiž uložené v opačnom poradí než v akom sme
ich do zoznamu pridávali. Napíšte funkciu, ktorá umožní pridávať prvky
na začiatok zoznamu (prvky nech sú celé čísla).
|
[Riešenie]
|
Napíš funkciu, ktorá vytvorí N - prvkový lineárny zoznam celých čísel, ktoré bude čítať zo vstupu, pričom
- poradie čísel uložených v zozname bude rovnaké
- poradie čísel uložených v zozname bude opačné, než v akom boli čísla zadané.
|
[Riešenie]
|
|