Programowanie i struktury danych Programowanie i struktury danych
Wykład 4 Wykład 4
Dr Piotr Cybula <piotr.cybula@wmii.uni.lodz.pl>
Dr Piotr Cybula <piotr.cybula@wmii.uni.lodz.pl>
Typ wska nikowy ź Typ wska nikowy ź
int* pointer; //wskaźnik do zmiennych typu int
● pozwala na dostęp do dowolnego miejsca pamięci (zmienne wskaźnikowe są stałej wielkości zależnej jedynie od architektury procesora, np. 32-bit, 64-bit)
● zmienna typu wskaźnikowego zawiera adres zmiennej, na którą wskazuje (domyślnie adres przypadkowy):
● inicjalizacja adresem pustym NULL (stała zdefiniowana w bibliotece cstdlib) lub nullptr (słowo kluczowe dla c++11)
pointer = nullptr;
● inicjalizacja adresem istniejącej zmiennej automatycznej (niebezpieczne)
int variable;
pointer = &variable; //operator adresu (referencji)
● inicjalizacja adresem zmiennej tworzonej dynamicznie
pointer = new int; //operator alokacji pamięci delete pointer; //operator dealokacji pamięci
● dostęp do wskazywanej zmiennej tylko dla niepustych wskaźników
p v
Typ wska nikowy ź Typ wska nikowy ź
● operator przypisania zmiennych wskaźnikowych kopiuje tylko adresy (nie wartości zmiennych wskazywanych)
int* p1 = new int;
int* p2;
p2 = p1; //p2 wskazuje na to samo co p1
● współdzielenie adresu jednej zmiennej doprowadzi do powstania tzw.
wskaźnika wiszącego (ang. dangling pointer) po zwolnieniu pamięci zajmowanej przez tę zmienną
delete p1;
cout << *p2; //zachowanie nieokreślone
● przed zwolnieniem pamięci dla zmiennej wskazywanej przez wskaźnik należy zmienić wartości dla wszystkich wskaźników wskazujących na tę zmienną poza jednym (tzw. zliczanie referencji)
p2 = nullptr; //p2 nie wskazuje już na wspólną zmienną
//p1 jest jedynym wskaźnikiem do tej zmiennej delete p1; //zwolnienie pamięci jest bezpieczne
p1 p2
p1 p2
?
Wska niki do struktur ź Wska niki do struktur ź
● dostęp do wskazywanej zmiennej strukturalnej (tylko dla niepustych wskaźników) za pomocą:
● operatorów dereferencji i selekcji (* i .): (*pointer).member
● operatora dereferencji wskaźnikowej (->): pointer->member
class Student { string name;
int index;
public:
Student(string _name);
int getName() const;
… //inne metody };
Student* p = new Student(”Scott Tiger”); //alokacja struktury cout << (*p).getName(); //operatory dereferencji i selekcji cout << p->getName(); //operator dereferencji wskaźnikowej
Wska nik this ź Wska nik this ź
● wskaźnik do obiektu, dla którego została wywołana metoda (dostępny w każdej metodzie struktury/klasy)
class Vector { double* v;
int dim;
public:
Vector(int dim) { v = new double[this->dim = dim]; } Vector& operator=(const Vector&);
};
Vector& Vector::operator=(const Vector &r)
{ if(this != &r) { //sprawdzenie adresów obiektów delete[] v;
v = new double[dim = r.dim];
for(int i = 0; i < dim; i++) v[i] = r.v[i];
} return *this; //dereferencja wskaźnika zwraca obiekt
Bezpiecze stwo wska ników ń ź Bezpiecze stwo wska ników ń ź
● dereferencja wskaźnika możliwa tylko gdy wskaźnik nie jest pusty (warunkowe użycie dereferencji, pustość wskaźnika oznacza najczęściej przypadek
szczególny w algorytmie)
● nazwa wskaźnika powinna jednoznacznie określać jego zastosowanie (proste wnioskowanie w przypadku pustości wskaźnika)
● powoływanie dedykowanych wskaźników dla alokacji i dealokacji pamięci
● 4 kroki poprawnej dealokacji pamięci (zapobieganie powstawania wskaźników wiszących):
(1) powołanie wskaźnika i przypisanie mu adresu obiektu do zwolnienia (2) opcjonalne zabezepieczenie ważnych danych z obiektu
(3) odpięcie (modyfikacja) wszystkich wskaźników przechowujących adres obiektu (poza wskaźnikiem z kroku pierwszego)
Lista czona łą Lista czona łą
● pozwala na nieciągły przydział pamięci przy implementacji ADT
● złożona z węzłów połączonych wskaźnikami - każdy węzeł zawiera dane i adres następnego (lista jednokierunkowa) oraz poprzedniego (lista dwukierunkowa)
● zalety: wysoka skalowalność i rozszerzalność, optymalne zużycie pamięci, łatwe dodawanie i usuwanie danych bez konieczności zmiany położenia w pamięci pozostałych danych
● wady: implementacja (operacje na wskaźnikach), niska wydajność odczytu (brak dostępu bezpośredniego do dowolnego elementu), dodatkowa pamięć wymagana dla zapamiętania adresów węzłów
A next
B next
C head
Implementacja listowa ADT Implementacja listowa ADT
● pozwala na nieograniczony rozmiar struktury
● wskaźnik na pierwszy (opcjonanie również ostatni) węzeł listy łączonej
● główne metody:
● konstruktor bezparametrowy (puste wskaźniki, brak węzłów)
● destruktor (zwolnienie pamięci wszystkich węzłów)
● konstruktor kopiujący (przydział pamięci dla węzłów)
● operator przypisania (zwolnienie starej i przydział nowej pamięci dla węzłów)
● dodawanie elementu (przydział pamięci dla nowego węzła)
● usuwanie elementu (zwolnienie pamięci węzła)
Wstawianie na pocz tek ą Wstawianie na pocz tek ą
(1) tworzymy nowy węzeł (creator) z podaną wartością i adresem pierwszego węzła (head) jako adresem następnego (next)
A next
B next
C head
Wstawianie na pocz tek ą Wstawianie na pocz tek ą
(1) tworzymy nowy węzeł (creator) z podaną wartością i adresem pierwszego węzła (head) jako adresem następnego (next)
A next
B next
C head
creator V next
Wstawianie na pocz tek ą Wstawianie na pocz tek ą
(1) tworzymy nowy węzeł (creator) z podaną wartością i adresem pierwszego węzła (head) jako adresem następnego (next)
(2) przestawiamy wskaźnik pierwszego węzła (head) na nowy węzeł
(3) jeżeli jest wskaźnik na ostatni węzeł (tail) i wskazuje on na pusty adres, ustawiamy go na nowy węzeł
A next
B next
C head
creator V next
Wstawianie na pocz tek ą Wstawianie na pocz tek ą
(1) tworzymy nowy węzeł (creator) z podaną wartością i adresem pierwszego węzła (head) jako adresem następnego (next)
(2) przestawiamy wskaźnik pierwszego węzła (head) na nowy węzeł
(3) jeżeli jest wskaźnik na ostatni węzeł (tail) i wskazuje on na pusty adres, ustawiamy go na nowy węzeł
A next
B next
C head
creator V next
Wstawianie na pocz tek ą Wstawianie na pocz tek ą
(1) tworzymy nowy węzeł (creator) z podaną wartością i adresem pierwszego węzła (head) jako adresem następnego (next)
(2) przestawiamy wskaźnik pierwszego węzła (head) na nowy węzeł
(3) jeżeli jest wskaźnik na ostatni węzeł (tail) i wskazuje on na pusty adres, ustawiamy go na nowy węzeł
A next
B next
C head
V next
Usuwanie na pocz tku ą Usuwanie na pocz tku ą
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację (2) ustawiamy dedykowany wskaźnik (killer) na pierwszy węzeł
A next
B next
C head
Usuwanie na pocz tku ą Usuwanie na pocz tku ą
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację (2) ustawiamy dedykowany wskaźnik (killer) na pierwszy węzeł
A next
B next
C head
killer
Usuwanie na pocz tku ą Usuwanie na pocz tku ą
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację (2) ustawiamy dedykowany wskaźnik (killer) na pierwszy węzeł
(3) przestawiamy wskaźnik pierwszego węzła (head) na węzeł drugi (używając adresu zapisanego we wskaźniku next z pierwszego węzła)
(4) jeżeli jest wskaźnik na ostatni węzeł (tail) i wskazuje on na usuwany, ustawiamy go na pusty adres
A next
B next
C head
killer
Usuwanie na pocz tku ą Usuwanie na pocz tku ą
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację (2) ustawiamy dedykowany wskaźnik (killer) na pierwszy węzeł
(3) przestawiamy wskaźnik pierwszego węzła (head) na węzeł drugi (używając adresu zapisanego we wskaźniku next z pierwszego węzła)
(4) jeżeli jest wskaźnik na ostatni węzeł (tail) i wskazuje on na usuwany, ustawiamy go na pusty adres
A next
B next
C head
killer
Usuwanie na pocz tku ą Usuwanie na pocz tku ą
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację (2) ustawiamy dedykowany wskaźnik (killer) na pierwszy węzeł
(3) przestawiamy wskaźnik pierwszego węzła (head) na węzeł drugi (używając adresu zapisanego we wskaźniku next z pierwszego węzła)
(4) jeżeli jest wskaźnik na ostatni węzeł (tail) i wskazuje on na usuwany, ustawiamy go na pusty adres
(5) zwalniamy węzeł wskazywany przez wskaźnik dedykowany (killer)
A next
B next
C head
killer
Usuwanie na pocz tku ą Usuwanie na pocz tku ą
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację (2) ustawiamy dedykowany wskaźnik (killer) na pierwszy węzeł
(3) przestawiamy wskaźnik pierwszego węzła (head) na węzeł drugi (używając adresu zapisanego we wskaźniku next z pierwszego węzła)
(4) jeżeli jest wskaźnik na ostatni węzeł (tail) i wskazuje on na usuwany, ustawiamy go na pusty adres
(5) zwalniamy węzeł wskazywany przez wskaźnik dedykowany (killer)
B next
C head
killer
Usuwanie na pocz tku ą Usuwanie na pocz tku ą
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację (2) ustawiamy dedykowany wskaźnik (killer) na pierwszy węzeł
(3) przestawiamy wskaźnik pierwszego węzła (head) na węzeł drugi (używając adresu zapisanego we wskaźniku next z pierwszego węzła)
(4) jeżeli jest wskaźnik na ostatni węzeł (tail) i wskazuje on na usuwany, ustawiamy go na pusty adres
(5) zwalniamy węzeł wskazywany przez wskaźnik dedykowany (killer)
B next
C head
Wstawianie na koniec (wer. 1) Wstawianie na koniec (wer. 1)
● wersja ze wskaźnikiem na pierwszy węzeł (head):
(1) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do ostatniego węzła
A next
B next
C head
Wstawianie na koniec (wer. 1) Wstawianie na koniec (wer. 1)
● wersja ze wskaźnikiem na pierwszy węzeł (head):
(1) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do ostatniego węzła
A next
B next
C head
Wstawianie na koniec (wer. 1) Wstawianie na koniec (wer. 1)
● wersja ze wskaźnikiem na pierwszy węzeł (head):
(1) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do ostatniego węzła
A next
B next
C head
Wstawianie na koniec (wer. 1) Wstawianie na koniec (wer. 1)
● wersja ze wskaźnikiem na pierwszy węzeł (head):
(1) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do ostatniego węzła
(2) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
A next
B next
C head
Wstawianie na koniec (wer. 1) Wstawianie na koniec (wer. 1)
● wersja ze wskaźnikiem na pierwszy węzeł (head):
(1) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do ostatniego węzła
(2) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
A next
B next
C head
V
Wstawianie na koniec (wer. 1) Wstawianie na koniec (wer. 1)
● wersja ze wskaźnikiem na pierwszy węzeł (head):
(1) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do ostatniego węzła
(2) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
(3) przestawiamy wskaźnik next w węźle wskazywanym przez tmp (lub wskaźnik head gdy tmp jest pusty) na nowy węzeł
A next
B next
C head
V
Wstawianie na koniec (wer. 1) Wstawianie na koniec (wer. 1)
● wersja ze wskaźnikiem na pierwszy węzeł (head):
(1) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do ostatniego węzła
(2) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
(3) przestawiamy wskaźnik next w węźle wskazywanym przez tmp (lub wskaźnik head gdy tmp jest pusty) na nowy węzeł
A next
B next
C head
next V
Wstawianie na koniec (wer. 1) Wstawianie na koniec (wer. 1)
● wersja ze wskaźnikiem na pierwszy węzeł (head):
(1) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do ostatniego węzła
(2) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
(3) przestawiamy wskaźnik next w węźle wskazywanym przez tmp (lub wskaźnik head gdy tmp jest pusty) na nowy węzeł
A next
B next
C head
next V
Wstawianie na koniec (wer. 2) Wstawianie na koniec (wer. 2)
● wersja ze wskaźnikami na pierwszy i ostatni węzeł (head i tail):
(1) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
A next
B next
C
head tail
Wstawianie na koniec (wer. 2) Wstawianie na koniec (wer. 2)
● wersja ze wskaźnikami na pierwszy i ostatni węzeł (head i tail):
(1) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
A next
B next
C head
V
tail
Wstawianie na koniec (wer. 2) Wstawianie na koniec (wer. 2)
● wersja ze wskaźnikami na pierwszy i ostatni węzeł (head i tail):
(1) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
(2) przestawiamy wskaźnik next w ostatnim węźle wskazywanym przez tail (lub wskaźnik head gdy tail jest pusty) na nowy węzeł
A next
B next
C head
V
tail
Wstawianie na koniec (wer. 2) Wstawianie na koniec (wer. 2)
● wersja ze wskaźnikami na pierwszy i ostatni węzeł (head i tail):
(1) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
(2) przestawiamy wskaźnik next w ostatnim węźle wskazywanym przez tail (lub wskaźnik head gdy tail jest pusty) na nowy węzeł
A next
B next
C head
next V
tail
Wstawianie na koniec (wer. 2) Wstawianie na koniec (wer. 2)
● wersja ze wskaźnikami na pierwszy i ostatni węzeł (head i tail):
(1) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
(2) przestawiamy wskaźnik next w ostatnim węźle wskazywanym przez tail (lub wskaźnik head gdy tail jest pusty) na nowy węzeł
(3) przestawiamy wskaźnik tail na nowy węzeł
A next
B next
C head
next V
tail
Wstawianie na koniec (wer. 2) Wstawianie na koniec (wer. 2)
● wersja ze wskaźnikami na pierwszy i ostatni węzeł (head i tail):
(1) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
(2) przestawiamy wskaźnik next w ostatnim węźle wskazywanym przez tail (lub wskaźnik head gdy tail jest pusty) na nowy węzeł
(3) przestawiamy wskaźnik tail na nowy węzeł
A next
B next
C head
next V
tail
Wstawianie na koniec (wer. 2) Wstawianie na koniec (wer. 2)
● wersja ze wskaźnikami na pierwszy i ostatni węzeł (head i tail):
(1) tworzymy nowy węzeł (creator) z podaną wartością i wartością pustą jako adresem następnego (next)
(2) przestawiamy wskaźnik next w ostatnim węźle wskazywanym przez tail (lub wskaźnik head gdy tail jest pusty) na nowy węzeł
(3) przestawiamy wskaźnik tail na nowy węzeł
A next
B next
C head
next V
tail
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
A B
tail C
head
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty)
A B
tail C
head tmp
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty)
A B
tail C
head tmp
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
A B
tail C
head tmp
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
A B
tail C
head tmp
killer
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
(4) ustawiamy wskaźnik next węzła wskazywanego przez tmp (lub wskaźnik head gdy tmp jest pusty) na pusty adres
A B
tail C
head tmp
killer
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
(4) ustawiamy wskaźnik next węzła wskazywanego przez tmp (lub wskaźnik head gdy tmp jest pusty) na pusty adres
A B
tail C
head tmp
killer
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
(4) ustawiamy wskaźnik next węzła wskazywanego przez tmp (lub wskaźnik head gdy tmp jest pusty) na pusty adres
(5) jeżeli jest wskaźnik na ostatni węzeł (tail), ustawiamy go na tmp
A B
tail C
head tmp
killer
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
(4) ustawiamy wskaźnik next węzła wskazywanego przez tmp (lub wskaźnik head gdy tmp jest pusty) na pusty adres
(5) jeżeli jest wskaźnik na ostatni węzeł (tail), ustawiamy go na tmp
A B
tail C
head tmp
killer
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
(4) ustawiamy wskaźnik next węzła wskazywanego przez tmp (lub wskaźnik head gdy tmp jest pusty) na pusty adres
(5) jeżeli jest wskaźnik na ostatni węzeł (tail), ustawiamy go na tmp (6) zwalniamy węzeł wskazywany przez wskaźnik dedykowany (killer)
A B
tail C
head tmp
killer
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
(4) ustawiamy wskaźnik next węzła wskazywanego przez tmp (lub wskaźnik head gdy tmp jest pusty) na pusty adres
(5) jeżeli jest wskaźnik na ostatni węzeł (tail), ustawiamy go na tmp (6) zwalniamy węzeł wskazywany przez wskaźnik dedykowany (killer)
A B
head tmp tail
killer
Usuwanie na ko cu ń Usuwanie na ko cu ń
(1) jeżeli lista jest pusta zgłaszamy wyjątek i przerywamy operację
(2) przechodzimy wskaźnikiem pomocniczym (tmp) od początku listy do
przedostatniego węzła (ostatniego węzła, którego wskaźnik next jest niepusty) (3) ustawiamy dedykowany wskaźnik (killer) na ostatni węzeł używając adresu
zapisanego we wskaźniku next węzła wskazywanego przez tmp (lub wskaźnika head jeżeli tmp jest pusty, lub wskaźnika tail jeżeli istnieje)
(4) ustawiamy wskaźnik next węzła wskazywanego przez tmp (lub wskaźnik head gdy tmp jest pusty) na pusty adres
(5) jeżeli jest wskaźnik na ostatni węzeł (tail), ustawiamy go na tmp (6) zwalniamy węzeł wskazywany przez wskaźnik dedykowany (killer)
A B
head tail