Listy jednokierunkowe
-- Sebastian Pawlak, 2003.
Węzeł listy jest strukturą zawierającą informację oraz wskaźnik na następny węzeł listy.
typedef struct wezel {
int wartosc;
wezel *nastepny;
} wezel;

Lista jednokierunkowa
Przechowywanie danych w listach ma swoje zalety i wady.
Zaletą list jest dynamiczne przydzielanie i zwalnianie pamięci na
poszczególne węzły. Zatem w trakcie działania programu można zarezerwować
tylko tyle pamięci ile potrzeba. Gdyby nieprzewidywalną ilość danych
przechowywać w tablicy, której wielkość ustawia się "na sztywno"
przed kompilacją, należałoby zadeklarować tablicę o zapewne dużym rozmiarze.
Także operowanie na danych przechowywanych w liście jest na ogół mniej
czasochłonne niż w przypadku tablic. Usuwanie i wstawianie z/do listy nie
wymaga przenoszenia pozostałych elementów, jak ma to miejsce w przypadku
tablic.
Wadą list jest to, że każdy węzeł zawiera wskaźnik do następnego węzła, co
pochłania pamięć operacyjną.
Za pomocą listy nie można zaimplementować algorytmu wyszukiwania binarnego
-- co nie jest problemem w przypadku tablic. Dostęp do poszczególnych
elementów listy wymaga przejścia poprzednich elementów.

Wstawianie elementu na początek listy

Usuwanie elementu z początku listy

Usuwanie elementu ze środka bądź końca listy
Kod źródłowy pliku "lista.h":
/* lista.h: plik naglowkowy biblioteki z implementacja operacji na
* listach jednokierunkowych
* Sebastian Pawlak, 2003-12-3
*/
#ifndef _LISTA_H_
#define _LISTA_H_
typedef struct wezel {
int wartosc;
struct wezel *nastepny;
} wezel;
enum {
POPRAWNIE = 0,
BRAK_PAMIECI = -1,
BLAD_IO = -2,
BLAD_POZYCJI = -3
};
int wstawPocz(wezel **L, int wartosc);
int wstaw(wezel **L, int p, int wartosc);
int usun(wezel **L, int p);
int zwroc(wezel *L, int p, int *wartosc);
int znajdz(wezel *L, int *p, int wartosc);
void wyczysc(wezel **L);
void wypisz(wezel *L);
int zapisz(wezel *L, char *nazwaPliku);
int wczytaj(wezel **L, char *nazwaPliku);
#endif
Kod źródłowy pliku "lista.c":
/* lista.c: biblioteka z implementacja operacji na
* listach jednokierunkowych
* Sebastian Pawlak, 2003-12-3
*/
#include <stdio.h>
#include <stdlib.h>
#include "lista.h"
/* wstawPocz: tworzy i wstawia nowy element na poczatek listy */
int wstawPocz(wezel **L, int wartosc)
{
wezel *Q;
if ((Q = (wezel *)malloc(sizeof (wezel))) == NULL)
return BRAK_PAMIECI;
Q -> wartosc = wartosc;
Q -> nastepny = *L;
*L = Q;
return POPRAWNIE;
}
/* wstaw: tworzy i wstawia nowy element na p-ta pozycje na liscie;
* pozycja liczona jest od 0
*/
int wstaw(wezel **L, int p, int wartosc)
{
wezel *Q, *S = NULL, *T = *L;
while (T && (p > 0)) {
S = T;
T = T -> nastepny;
p--;
}
if (p != 0)
return BLAD_POZYCJI;
if ((Q = (wezel *)malloc(sizeof (wezel))) == NULL)
return BRAK_PAMIECI;
Q -> wartosc = wartosc;
Q -> nastepny = T;
if (S == NULL)
*L = Q;
else
S -> nastepny = Q;
return POPRAWNIE;
}
/* usun: usuwa element z p-tej pozycji na liscie;
* pozycja liczona jest od 0
*/
int usun(wezel **L, int p)
{
wezel *S = NULL, *T = *L;
while (T && (p > 0)) {
S = T;
T = T -> nastepny;
p--;
}
if ((p != 0) || (T == NULL))
return BLAD_POZYCJI;
if (S == NULL)
*L = T -> nastepny;
else
S -> nastepny = T -> nastepny;
free(T);
return POPRAWNIE;
}
/* zwroc: przypisuje zmiennej "wartosc" wartosc p-tego elementu z listy */
int zwroc(wezel *L, int p, int *wartosc)
{
while (L && (p > 0)) {
L = L -> nastepny;
p--;
}
if ((p != 0) || (L == NULL))
return BLAD_POZYCJI;
*wartosc = L -> wartosc;
return 0;
}
/* znajdz: przypisuje zmiennej "p" numer elementu listy, pod ktorym wystepuje
* "wartosc"
*/
int znajdz(wezel *L, int *p, int wartosc)
{
*p = 0;
while (L && (L -> wartosc != wartosc)) {
(*p)++;
L = L -> nastepny;
}
if (L == NULL)
return BLAD_POZYCJI;
return POPRAWNIE;
}
/* wyczysc: usuwa wszystkie elementy z listy */
void wyczysc(wezel **L)
{
wezel *Q;
while (*L) {
Q = *L;
*L = (*L) -> nastepny;
free(Q);
}
}
/* wypisz: wypisuje wszystkie elementy z listy */
void wypisz(wezel *L)
{
while (L) {
printf("%d\n", L -> wartosc);
L = L -> nastepny;
}
}
/* zapisz: zapisuje wszystkie elementy z listy do pliku tekstowego */
int zapisz(wezel *L, char *nazwaPliku)
{
FILE *f;
if ((f = fopen(nazwaPliku, "w")) == NULL)
return BLAD_IO;
while (L) {
if (fprintf(f, "%d%c",
L -> wartosc, L -> nastepny ? ' ' : '\n') < 0)
return BLAD_IO;
L = L -> nastepny;
}
fclose(f);
return POPRAWNIE;
}
/* wczytaj: wczytuje z pliku tekstowego elementy i wstawia je na liste
* w odwrotnej kolejnosci
*/
int wczytaj(wezel **L, char *nazwaPliku)
{
wezel *Q, *T = *L;
FILE *f;
int wartosc;
if ((f = fopen(nazwaPliku, "r")) == NULL)
return BLAD_IO;
/* odnalezienie konca listy */
while (T && (T -> nastepny))
T = T -> nastepny;
while (fscanf(f, "%d", &wartosc) != EOF) {
if ((Q = (wezel *)malloc(sizeof (wezel))) == NULL)
return BRAK_PAMIECI;
Q -> wartosc = wartosc;
Q -> nastepny = NULL;
if (T == NULL)
*L = T = Q;
else {
T -> nastepny = Q; /* dopisywanie elementow do konca listy */
T = T -> nastepny;
}
}
fclose(f);
return POPRAWNIE;
}
Kod źródłowy pliku "test.c":
/* test.c: ilustracja dzialania biblioteki lista.c
* Sebastian Pawlak, 2003-12-3
*/
#include <stdio.h>
#include "lista.h"
int main(void)
{
wezel *L = NULL;
int p;
wstawPocz(&L, 11);
wstawPocz(&L, 33);
wstaw(&L, 1, 22);
wstaw(&L, 0, 78);
usun(&L, 0);
wypisz(L);
return 0;
}





