-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLinkedList.pas
173 lines (138 loc) · 5.92 KB
/
LinkedList.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
unit LinkedList;
type
/// Элемент связанного списка
LListNode<T> = class
public
value: T;
next: LListNode<T>;
constructor(value: T; next: LListNode<T> := nil);
begin
self.value := value;
self.next := next;
end;
function ToString: string; override;
begin
ToString := self.value.ToString();
end;
end;
/// Связный список (Linked list)
LList<T> = class
public
/// головной элемент списка
head: LListNode<T>;
/// последний элемент списка
tail: LListNode<T>;
/// размер списка
length: integer;
constructor();
begin
self.length := 0;
self.head := nil;
end;
/// добавляет элемент в список
procedure add(value: T);
begin
var node: LListNode<T> := new LListNode<T>(value);
if self.head = nil then self.head := node
else self.tail.next := node;
self.tail := node;
Inc(self.length); /// увеличивает размер списка после добавления элемента
end;
/// проверяет наличие в списке элемента с таким индексом
/// если индекс за пределами списка, тогда вызывется исключение
procedure checkIndexExists(index: integer);
begin
if (index < self.length) and (index >= 0) then exit;
raise new System.IndexOutOfRangeException('Индекс находился вне границ списка');
end;
/// удаляет первый элемент
procedure removeFirst();
begin
self.head := self.head.next;
/// уменьшает размер списка после удаления первого элемента
Dec(self.length);
end;
/// Удаляет последний элемент
procedure removeLast();
begin
self.removeElementByIndex(self.length - 1);
end;
/// Удаляет элемент по индексу
procedure removeElementByIndex(index: integer);
begin
checkIndexExists(index);
if index = 0 then
self.removeFirst()
else begin
var previous: LListNode<T> := self.head;
for var i := 0 to index - 2 do
previous := previous.next;
var toDelete: LListNode<T> := previous.next;
previous.next := toDelete.next;
/// уменьшает размер списка после удаления элемента
Dec(self.length);
end;
end;
/// Возвращает true если в списке есть такой элемент
function contains(element: T): boolean;
begin
for var i := 0 to self.length - 1 do
if self[i] = element then contains := True;
end;
/// Генерирует строковое представление списка (для вывода с помощью WriteLn итд)
function ToString: string; override;
begin
var res := '';
var current: LListNode<T> := self.head;
while not (current = nil) do
begin
/// пустая строка если это конец
res += current.value.toString() + (current.next = nil ? '' : ', ');
current := current.next;
end;
ToString := $'[{res}]';
end;
/// ....................................
/// РЕАЛИЗАЦИЯ ДОСТУПА ПО ИНДЕКСУ
/// позволяет использовать класс как массив
/// ....................................
/// Фунция получения элемента по индексному свойству
/// Например: переменная := список[индекс элемента];
function GetNode(index: integer): T;
begin
checkIndexExists(index);
var current: LListNode<T> := self.head;
var counter := 0;
while not (current = nil) do
begin
if (counter = index) then
begin
GetNode := current.value;
exit;
end;
current := current.next;
counter += 1;
end;
end;
/// Функция присваивания элемента по индексному свойству
/// Например: список[индекс элемента] := значение;
procedure SetNode(index: integer; value: T);
begin
checkIndexExists(index);
var current: LListNode<T> := self.head;
var counter := 0;
while not (current = nil) do
begin
if (counter = index) then
begin
current.value := value;
exit;
end;
current := current.next;
counter += 1;
end;
end;
/// Назначение индексных свойств
property Nodes[index: integer]: T read GetNode write SetNode;default;
end;
end.