|
Serwis Edukacyjny w I-LO w Tarnowie
Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej
Autor artykułu: mgr Jerzy Wałaszek |
©2026 mgr Jerzy Wałaszek
|
Podane tutaj procedury obsługi list nie uwzględniają sytuacji błędnych – np. braku pamięci dla tworzonych elementów czy nieprawidłowych danych wejściowych. Można je zatem stosować tylko wtedy, gdy jesteśmy w 100% pewni, że nie dojdzie do żadnych nieprawidłowości. W przeciwnym razie należałoby zaimplementować obsługę wyjątków, a to jest temat na osobny artykuł.
Cykliczna lista jednokierunkowa jest zwykłą listą jednokierunkową. Różnica polega jedynie na tym, iż pole next ostatniego elementu wskazuje na pierwszy element listy. Zmienna head wskazuje nie początek, lecz punkt wejścia do pierścienia, który tworzą elementy listy jednokierunkowej.

| Pascal |
type
PCSLel = ^CSLel;
CSLel = record
next : PCSLel;
Data: typ_danych;
end;
|
|
|
struct CSLel
{
CSLel * next;
typ_danych data;
};
|
| Basic |
Type CSLel next As CSLel Ptr data As typ_danych End Type |
| Python (dodatek) |
# klasa elementu listy cyklicznej
# jednokierunkowej
class CSLel:
def __init__(self, data):
self.next = None
self.data = data
# klasa listy cyklicznej
# jednokierunkowej
class CSLvar:
def __init__(self):
self.head = None
|
Lista cykliczna nigdy się nie kończy, gdyż ostatni element łączy się z pierwszym. Nie możemy więc przechodzić jej w taki sam sposób jak listę niecykliczną. Umówimy się, że zmienna head wskazuje początek takiej listy, który będziemy nazywali punktem wejścia (ang. entry point). Natomiast ostatnim elementem będzie ten, którego pole next wskazuje pierwszy element, czyli zawiera taki sam adres jak head. Pozwoli nam to przejść przez wszystkie elementy listy cyklicznej.
K01: p ← head ; w p ustawiamy adres punktu wejścia K02: Jeśli p = nil, ; kończymy, jeśli lista jest pusta to zakończ K03: Przetwarzaj element wskazywany przez p K04: p ← p→next ; w p umieść zawartość pola next ; elementu wskazywanego przez p K05: Jeśli p ≠ head, ; w pętli przechodzimy przez kolejne to idź do kroku K03 ; elementy listy, aż wrócimy ; do punktu wejścia K06: Zakończ
| Pascal |
…
p := head;
if p <> nil then
repeat
…
p := p^.next;
until p = head;
…
|
|
|
…
p = head;
if(p)
do
{
…
p = p->next;
} while(p != head);
…
|
| Basic |
…
p = head
if p Then
Do
…
p = p->next
Loop Until p = head
End If
…
|
| Python (dodatek) |
# klasa elementu listy cyklicznej
# jednokierunkowej
class CSLel:
def __init__(self, data):
self.next = None
self.data = data
# klasa listy cyklicznej
# jednokierunkowej
class CSLvar:
def __init__(self):
self.head = None
…
cl = CSLvar()
…
p = cl.head
if p:
while True:
… # przetwarzanie elementu
p = p.next
if p is cl.head: break
…
|
Do obliczenia liczby elementów wykorzystujemy algorytm przejścia z licznikiem. Przed wejściem do pierścienia licznik zerujemy. Przechodzimy przez kolejne elementy, przy każdym zwiększamy licznik o 1. Po przejściu dookoła pierścienia w liczniku otrzymamy liczbę elementów listy.
K01: c ← 0 ; zerujemy licznik K02: p ← head ; w p ustawiamy adres pierwszego elementu K03: Jeśli p = nil, ; pomijamy obliczanie, jeśli lista jest pusta to idź do kroku K07 K04: c ← c+1 ; dla każdego elementu zwiększamy licznik o 1 K05: p ← p→next ; p ustawiamy na następny element w pierścieniu K06: Jeśli p ≠ head, ; w pętli przechodzimy przez wszystkie to idź do kroku K04 ; elementy pierścienia K07: Zakończ z wynikiem c
Pascalfunction l_len(head : PCSLel) : cardinal;
var
c : cardinal;
p : PCSLel;
begin
c := 0;
p := head;
if p <> nil then
repeat
inc(c);
p := p^.next;
until p = head;
l_len := c;
end; |
unsigned l_len(CSLel * head)
{
unsigned c = 0;
CSLel * p = head;
if(p)
do
{
c |
BasicFunction l_len(head As CSLel Ptr) _
As UInteger
Dim c As UInteger
Dim p As CSLel Ptr
c = 0
p = head
If p Then
Do
c += 1
p = p->next
Loop Until p = head
End If
l_len = c
End Function |
| Python (dodatek) |
# klasa elementu listy cyklicznej
# jednokierunkowej
class CSLel:
def __init__(self, data):
self.next = None
self.data = data
# klasa listy cyklicznej
# jednokierunkowej
class CSLvar:
def __init__(self):
self.head = None
# Zliczanie elementów
def l_len(self):
c = 0
p = self.head
if p:
while True:
c += 1
p = p.next
if self.head is p:
break
return c
|



W tym algorytmie wstawiania zmienna head zawsze wskazuje ostatnio dodany do listy element. Następnik jest natomiast zawsze pierwszym z dodanych elementów. Taka prosta struktura pozwala tworzyć tzw. kolejki (ang. queue), czyli bufory przechowujące dane. W kolejce dane odczytujemy w tej samej kolejności, w której zostały wstawione. Tutaj wystarczy odczytywać następnik i usuwać go z listy.
K01: p ← adres nowego elementu K02: p→data ← v ; w nowym elemencie umieszczamy dane K03: Jeśli head ≠ nil, ; sprawdzamy, czy lista jest pusta to idź do kroku K06 K04: p→next ← p ; jeśli tak, to nowy element jest ; swoim własnym następnikiem K05: Idź do kroku K08 K06: p→next ← head→next ; następnikiem będzie następnik ; punktu wejścia K07: head→next ← p ; następnikiem pierwszego elementu ; będzie nowy element K08: head ← p ; przesuwamy punkt wejścia na wstawiony element K09: Zakończ
Pascalprocedure l_push(var head : PCSLel;
v : char);
var
p : PCSLel;
begin
new(p);
p^.Data:= v;
if head = nil then
p^.next := p
else
begin
p^.next := head^.next;
head^.next := p;
end;
head := p;
end; |
void l_push(CSLel * & head, char v)
{
CSLel * p = new CSLel;
p->data = v;
if(head)
{
p->next = head->next;
head->next = p;
}
else
p->next = p;
head = p;
} |
BasicSub l_push(ByRef head As CSLel Ptr, _
v As String)
Dim p As CSLel Ptr
p = new CSLel
p->data = v
If head = 0 Then
p->next = p
Else
p->next = head->next
head->next = p
End If
head = p
End Sub |
| Python (dodatek) |
# klasa elementu listy cyklicznej
# jednokierunkowej
class CSLel:
def __init__(self, data):
self.next = None
self.data = data
# klasa listy cyklicznej
# jednokierunkowej
class CSLvar:
def __init__(self):
self.head = None
# wstawianie następnika
def l_push(self, v):
p = CSLel(v)
if self.head:
p.next = self.head.next
self.head.next = p
else:
p.next = p
self.head = p
|




K01: Jeśli head = 0, ; lista jest pusta i nie ma to zakończ ; co z niej usuwać K02: p ← head→next ; p będzie wskazywało następnik ; punktu wejścia K03: head→next ← p→next ; następnikiem punktu wejścia ; będzie następnik następnika K04: Jeśli p→next = p, ; zerujemy head, jeśli lista to head ← nil ; jest jednoelementowa K05: Usuń element wskazywany przez p ; usuwamy następnik K06: Zakończ
Pascalprocedure l_pop(var head : PCSLel);
var
p : PCSLel;
begin
if head <> nil then
begin
p := head^.next;
head^.next := p^.next;
if p^.next = p then
head := nil;
dispose(p);
end;
end; |
void l_pop(CSLel * & head)
{
if(head)
{
CSLel * p = head->next;
head->next = p->next;
if(p->next == p)
head = NULL;
delete p;
}
} |
BasicSub l_pop(ByRef head As CSLel Ptr)
Dim p As CSLel Ptr
If head Then
p = head->next
head->next = p->next
If p->next = p Then _
head = 0
Delete p
End If
End Sub |
| Python (dodatek) |
# klasa elementu listy cyklicznej
# jednokierunkowej
class CSLel:
def __init__(self, data):
self.next = None
self.data = data
# klasa listy cyklicznej
# jednokierunkowej
class CSLvar:
def __init__(self):
self.head = None
#usuwanie
def l_pop(self):
if self.head:
p = self.head.next
self.head.next = p.next
if p.next is p:
self.head = None
p = None
|
|
Uwaga: Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich. |
To jest program testowy, który
działa następująco:
|
Pascal// Program testowy dla list
// cyklicznych jednokierunkowych
// Data: 16.02.2012
// (C)2020 mgr Jerzy Wałaszek
//------------------------------
program ccslist_test;
// Typ elementów listy
//--------------------
type
PCSLel = ^CSLel;
CSLel = record
next : PCSLel;
Data: char;
end;
// Oblicza liczbę elementów listy
//-------------------------------
function l_len(head : PCSLel) : cardinal;
var
c : cardinal;
p : PCSLel;
begin
c := 0;
p := head;
if p <> nil then
repeat
inc(c);
p := p^.next;
until p = head;
l_len := c;
end;
// Wyświetla kolejne elementy listy
//---------------------------------
procedure l_print(head : PCSLel);
var
p : PCSLel;
begin
write(l_len(head):3, ' [');
p := head;
if p <> nil then
repeat
write(' ', p^.data);
p := p^.next;
until p = head;
writeln(' ]');
end;
// Wstawia nowy element
//---------------------
procedure l_push(var head : PCSLel;
v : char);
var
p : PCSLel;
begin
new(p);
p^.Data:= v;
if head = nil then
p^.next := p
else
begin
p^.next := head^.next;
head^.next := p;
end;
head := p;
end;
// Usuwa element z listy
//----------------------
procedure l_pop(var head : PCSLel);
var
p : PCSLel;
begin
if head <> nil then
begin
p := head^.next;
head^.next := p^.next;
if p^.next = p then
head := nil;
dispose(p);
end;
end;
//---------------
// Program główny
//---------------
var
head : PCSLel;
i : char;
begin
head := nil;
l_print(head);
for i := 'A' to 'G' do
begin
l_push(head, i);
l_print(head);
end;
while head <> nil do
begin
l_pop(head);
l_print(head);
end;
end. |
// Program testowy dla list
// cyklicznych jednokierunkowych
// Data: 16.02.2012
// (C)2020 mgr Jerzy Wałaszek
//------------------------------
#include <iostream>
#include <iomanip>
using namespace std;
struct CSLel
{
CSLel * next;
char data;
};
// Funkcja oblicza liczbę
// elementów listy
//-----------------------
unsigned l_len(CSLel * head)
{
unsigned c = 0;
CSLel * p = head;
if(p)
do
{
c |
Basic' Program testowy dla list
' cyklicznych jednokierunkowych
' Data: 16.02.2012
' (C)2020 mgr Jerzy Wałaszek
'------------------------------
' Typ elementów listy
'--------------------
Type CSLel
next As CSLel Ptr
data As String * 1
End Type
' Funkcja oblicza liczbę elementów listy
'---------------------------------------
Function l_len(head As CSLel Ptr) _
As UInteger
Dim c As UInteger
Dim p As CSLel Ptr
c = 0
p = head
If p Then
Do
c += 1
p = p->next
Loop Until p = head
End If
l_len = c
End Function
' Wyświetla kolejne elementy listy
'---------------------------------
Sub l_print(head As CSLel Ptr)
Dim p As CSLel Ptr
Print Using "### [";l_len(head);
p = head
If p Then
do
Print " ";p->data;
p = p->next
Loop Until p = head
End If
Print " ]"
End Sub
' Wstawia nowy element
'---------------------
Sub l_push(ByRef head As CSLel Ptr, _
v As String)
Dim p As CSLel Ptr
p = new CSLel
p->data = v
If head = 0 Then
p->next = p
Else
p->next = head->next
head->next = p
End If
head = p
End Sub
' Usuwa element
'--------------
Sub l_pop(ByRef head As CSLel Ptr)
Dim p As CSLel Ptr
If head Then
p = head->next
head->next = p->next
If p->next = p Then _
head = 0
Delete p
End If
End Sub
'---------------
' Program główny
'---------------
Dim head As CSLel Ptr
Dim i As Integer
head = 0
l_print(head)
For i = Asc ("A") To Asc ("G")
l_push(head, Chr(i))
l_print(head)
Next
While head
l_pop(head)
l_print(head)
Wend
End |
| Python (dodatek) |
# Program testowy dla list
# cyklicznych jednokierunkowych
# Data: 11.05.2024
# (C)2024 mgr Jerzy Wałaszek
#------------------------------
# klasa elementu listy cyklicznej
# jednokierunkowej
class CSLel:
def __init__(self, data):
self.next = None
self.data = data
# klasa listy cyklicznej
# jednokierunkowej
class CSLvar:
# Konstruktor
def __init__(self):
self.head = None
# destruktor
def __del__(self):
while self.head:
self.l_pop()
# zliczanie elementów
def l_len(self):
c = 0
p = self.head
if p:
while True:
c += 1
p = p.next
if self.head is p:
break
return c
# wyświetla elementy
def l_print(self):
print("%3d [ " % self.l_len(), end="")
p = self.head
if p:
while True:
print(p.data, end=" ")
p = p.next
if p is self.head:
break
print("]")
# wstawia element
def l_push(self, v):
p = CSLel(v)
if self.head:
p.next = self.head.next
self.head.next = p
else:
p.next = p
self.head = p
# usuwa element
def l_pop(self):
if self.head:
p = self.head.next
self.head.next = p.next
if p.next is p:
self.head = None
#---------------
# Program główny
#---------------
cl = CSLvar()
cl.l_print()
for i in range(ord('A'), ord('G')+1):
cl.l_push(chr(i))
cl.l_print()
while cl.head:
cl.l_pop()
cl.l_print()
|
| Wynik: |
0 [ ] 1 [ A ] 2 [ B A ] 3 [ C A B ] 4 [ D A B C ] 5 [ E A B C D ] 6 [ F A B C D E ] 7 [ G A B C D E F ] 6 [ G B C D E F ] 5 [ G C D E F ] 4 [ G D E F ] 3 [ G E F ] 2 [ G F ] 1 [ G ] 0 [ ] |
Poniższy program jest obiektową wersją ostatniego programu.
Pascal// Obiekt listy cyklicznej jednokierunkowej
// Data: 16.02.2012
// (C)2020 mgr Jerzy Wałaszek
//----------------------------------------
program ccslist_object;
// Typ elementów listy
//--------------------
type
PCSLel = ^CSLel;
CSLel = record
next : PCSLel;
Data: char;
end;
// Obiekt listy cyklicznej jednokierunkowej
//-----------------------------------------
CSLvar = object
public
head : PCSLel; // punkt wejścia
constructor init;
destructor destroy;
function l_len : cardinal;
procedure l_print;
procedure l_push(v : char);
procedure l_pop;
end;
// Metody obiektu CSLvar
//-------------------------
// Inicjuje obiekt
//----------------
constructor CSLvar.init;
begin
head := nil;
end;
// Usuwa listę
//------------
destructor CSLvar.destroy;
begin
while head <> nil do l_pop;
end;
// Oblicza liczbę elementów listy
//-------------------------------
function CSLvar.l_len : cardinal;
var
c : cardinal;
p : PCSLel;
begin
c := 0;
p := head;
if p <> nil then
repeat
inc(c);
p := p^.next;
until p = head;
l_len := c;
end;
// Wyświetla kolejne elementy listy
//---------------------------------
procedure CSLvar.l_print;
var
p : PCSLel;
begin
write(l_len:3, ' [');
p := head;
if p <> nil then
repeat
write (' ', p^.data);
p := p^.next;
until p = head;
writeln(' ]');
end;
// Wstawia nowy element
//---------------------
procedure CSLvar.l_push(v : char);
var
p : PCSLel;
begin
new(p);
p^.Data:= v;
if head = nil then p^.next := p
else
begin
p^.next := head^.next;
head^.next := p;
end;
head := p;
end;
// Usuwa element z listy
//----------------------
procedure CSLvar.l_pop;
var
p : PCSLel;
begin
if head <> nil then
begin
p := head^.next;
head^.next := p^.next;
if p^.next = p then head := nil;
dispose(p);
end;
end;
//---------------
// Program główny
//---------------
var
L : CSLvar;
i : char;
begin
L.init;
L.l_print;
for i := 'A' to 'G' do
begin
L.l_push(i);
L.l_print;
end;
while L.head <> nil do
begin
L.l_pop;
L.l_print;
end;
end.
|
// Obiekt listy cyklicznej jednokierunkowej
// Data: 16.02.2012
// (C)2020 mgr Jerzy Wałaszek
//-----------------------------------------
#include <iostream>
#include <iomanip>
using namespace std;
struct CSLel
{
CSLel * next;
char data;
};
// Definicja obiektu listy dwukierunkowej
//---------------------------------------
class CSLvar
{
public:
CSLel * head; // punkt wejścia
CSLvar(); // konstruktor
~CSLvar(); // destruktor
unsigned l_len();
void l_print();
void l_push(char v);
void l_pop();
};
//-------------------------------------------------
// Metody obiektu listy cyklicznej jednokierunkowej
//-------------------------------------------------
// Inicjuje obiekt
//----------------
CSLvar::CSLvar()
{
head = NULL;
}
// Usuwa listę z pamięci
//----------------------
CSLvar::~CSLvar()
{
while(head) l_pop();
}
// Funkcja oblicza liczbę elementów listy
//---------------------------------------
unsigned CSLvar::l_len()
{
unsigned c = 0;
CSLel * p = head;
if(p)
do
{
c++;
p = p->next;
} while(p != head);
return c;
}
// Wyświetla kolejne elementy listy
//---------------------------------
void CSLvar::l_print()
{
CSLel * p;
cout << setw(3) << l_len() << " [";
p = head;
if(p)
do
{
cout << " " << p->data;
p = p->next;
} while(p != head);
cout << " ]\n";
}
// Wstawia nowy element
//---------------------
void CSLvar::l_push(char v)
{
CSLel * p = new CSLel;
p->data = v;
if(head)
{
p->next = head->next;
head->next = p;
}
else
p->next = p;
head = p;
}
// Usuwa element
//--------------
void CSLvar::l_pop()
{
if(head)
{
CSLel * p = head->next;
head->next = p->next;
if(p->next == p)
head = NULL;
delete p;
}
}
//---------------
// Program główny
//---------------
int main()
{
CSLvar L;
char i;
L.l_print();
for(i = 'A'; i <= 'G'; i++)
{
L.l_push(i);
L.l_print();
}
while(L.head)
{
L.l_pop();
L.l_print();
}
return 0;
}
|
Basic' Obiekt listy cyklicznej jednokierunkowej
' Data: 16.02.2012
' (C)2020 mgr Jerzy Wałaszek
'----------------------------------------
' Typ elementów listy
'--------------------
Type CSLel
next As CSLel Ptr
data As String * 1
End Type
' Typ obiektowy listy cyklicznej jednokierunkowej
'------------------------------------------------
Type CSLvar
head As CSLel Ptr
Declare Constructor()
Declare Destructor()
Declare Function l_len() As UInteger
Declare Sub l_print()
Declare Sub l_push(v As String)
Declare Sub l_pop()
End Type
'---------------
' Program główny
'---------------
Dim L As CSLvar
Dim i As Integer
L.l_print()
For i = Asc ("A") To Asc ("G")
L.l_push(Chr(i))
L.l_print()
Next
While L.head
L.l_pop()
L.l_print()
Wend
End
' Konstruktor listy
'------------------
Constructor CSLvar()
head = 0
End Constructor
' Usuwa listę z pamięci
Destructor CSLvar()
While head
l_pop()
Wend
End Destructor
' Funkcja oblicza liczbę elementów listy
'---------------------------------------
Function CSLvar.l_len() As UInteger
Dim c As UInteger
Dim p As CSLel Ptr
c = 0
p = head
If p Then
Do
c += 1
p = p->next
Loop Until p = head
End If
l_len = c
End Function
' Wyświetla kolejne elementy listy
'---------------------------------
Sub CSLvar.l_print()
Dim p As CSLel Ptr
Print Using "### [";l_len();
p = head
If p Then
do
Print " ";p->data;
p = p->next
Loop Until p = head
End If
Print " ]"
End Sub
' Wstawia nowy element
'---------------------
Sub CSLvar.l_push(v As String)
Dim p As CSLel Ptr
p = new CSLel
p->data = v
If head = 0 Then
p->next = p
Else
p->next = head->next
head->next = p
End If
head = p
End Sub
' Usuwa element
'--------------
Sub CSLvar.l_pop()
Dim p As CSLel Ptr
If head Then
p = head->next
head->next = p->next
If p->next = p Then _
head = 0
Delete p
End If
End Sub
|
![]() |
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2026 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.