3.1 Verilənlər üzərində əməliyyatlar: əlavə etmə, silmə, axtarış
Əlavə etmə (Insert):
Verilənlər quruluşuna yeni elementin əlavə edilməsi əməliyyatı. Əlavə etmə başlanğıcda, sonda və ya istənilən mövqedə edilə bilər.
Silmə (Delete):
Verilənlər quruluşundan elementin silinməsi əməliyyatı. Silmə elementin dəyərinə, indeksinə və ya mövqeyinə görə baş verə bilər.
Axtarış (Search):
Verilənlər quruluşunda elementin tapılması əməliyyatı. Axtarış dəyərə və ya digər ölçütlərə görə edilə bilər.
Əməliyyatların nümunələri:
- Massivlər: Əlavə etmə və silmə elementlərin sürüşdürülməsini tələb edir, bu isə vaxt baxımından baha başa gələ bilər —
O(n)
. - Bağlı siyahılar: Əlavə etmə və silmə, əgər düyünün mövqeyi məlumdursa,
O(1)
vaxtda baş verə bilər. - Hash-cədvəllər: Axtarış, əlavə etmə və silmə adətən orta halda
O(1)
vaxtda yerinə yetirilir. - Ağaclar: Axtarış, əlavə etmə və silmə əməliyyatları balanslı ağaclarda
O(log n)
vaxtda həyata keçirilə bilər.
3.2 Əsas anlayışlar: massiv, siyahı, stack, növbə
Massiv
Massiv — eyni tipdən olan elementlər ardıcıllığıdır, hansı ki, indeks vasitəsilə əldə edilə bilər.
Əməliyyatların mürəkkəbliyi: İndeks üzrə giriş — O(1)
, əlavə etmək və silmək — O(n)
.
Nümunə: Massivin yaradılması, elementin dəyişdirilməsi və nəticənin çıxarılması
# Rəqəmlərdən ibarət massiv yaradırıq
arr = [1, 2, 3, 4, 5]
# 2-ci indeksdəki elementi dəyişirik (üçüncü element, çünki indeksləşmə 0-dan başlayır)
arr[2] = 10
# Dəyişdirilmiş massivi çıxarırıq
print(arr) # Çıxış: [1, 2, 10, 4, 5]
# Massivin sonuna yeni element əlavə edirik
arr.append(6)
print(arr) # Çıxış: [1, 2, 10, 4, 5, 6]
# İndeks üzrə element silirik
del arr[1]
print(arr) # Çıxış: [1, 10, 4, 5, 6]
Siyahı
Siyahı — elementlər kolleksiyasıdır, burada hər bir element növbəti elementə (birbağlı siyahı) və ya növbəti və əvvəlki elementə (ikibağlı siyahı) istinad edir.
Əməliyyatların mürəkkəbliyi: Əlavə etmək və silmək — O(1)
əgər mövqe bilinir, axtarış — O(n)
.
Nümunə: Sadə birbağlı siyahının yaradılması və onun dolaşılması
# Siyahı düyününün strukturunu təyin edirik
class Node:
def __init__(self, data):
self.data = data
self.next = None
# Birbağlı siyahı yaradırıq
node1 = Node("101")
node2 = Node("102")
node3 = Node("103")
# Düyünləri əlaqələndiririk
node1.next = node2
node2.next = node3
# Siyahının başlanğıcını təyin edirik
list_head = node1
# Siyahıdan keçirik və verilənləri çıxarırıq
current = list_head
while current:
print(current.data)
current = current.next
# Çıxış:
# 101
# 102
# 103
Stack
Stack — elementlər kolleksiyasıdır, LIFO
(Last In, First Out): sonuncu əlavə olunan birinci çıxır.
Əməliyyatların mürəkkəbliyi: Əlavə etmək (push) və silmək (pop) — O(1)
.
Nümunə: Mötərizələrin balanslılığını yoxlamaq üçün stack-in reallaşdırılması və tətbiqi
def is_balanced(expression):
stack = []
opening = "({["
closing = ")}]"
pairs = {")": "(", "}": "{", "]": "["}
for char in expression:
if char in opening:
stack.append(char)
elif char in closing:
if not stack or stack.pop() != pairs[char]:
return False
return len(stack) == 0
# Müxtəlif ifadələri yoxlayırıq
print(is_balanced("({[]})")) # Çıxış: True
print(is_balanced("([)]")) # Çıxış: False
print(is_balanced("((")) # Çıxış: False
Növbə (Queue)
Növbə — elementlər kolleksiyasıdır, FIFO
(First In, First Out): birinci əlavə olunan birinci çıxır.
Əməliyyatların mürəkkəbliyi: Əlavə etmək (enqueue) və silmək (dequeue) — O(1)
.
Nümunə: Tapşırıqların emulyasiyası üçün növbənin reallaşdırılması və istifadəsi
from collections import deque
class TaskQueue:
def __init__(self):
self.queue = deque()
def add_task(self, task):
self.queue.append(task)
print(f"Tapşırıq '{task}' növbəyə əlavə edildi")
def process_task(self):
if self.queue:
task = self.queue.popleft()
print(f"Tapşırığı emal edirik: '{task}'")
else:
print("Növbə boşdur")
def display_queue(self):
print("Cari tapşırıqlar növbəsi:", list(self.queue))
# Tapşırıqlar növbəsi yaradırıq və istifadə edirik
task_queue = TaskQueue()
task_queue.add_task("Email göndərmək")
task_queue.add_task("Məlumat bazasını yeniləmək")
task_queue.add_task("Hesabat yaratmaq")
task_queue.display_queue()
task_queue.process_task()
task_queue.process_task()
task_queue.display_queue()
# Çıxış:
# Tapşırıq 'Email göndərmək' növbəyə əlavə edildi
# Tapşırıq 'Məlumat bazasını yeniləmək' növbəyə əlavə edildi
# Tapşırıq 'Hesabat yaratmaq' növbəyə əlavə edildi
# Cari tapşırıqlar növbəsi: ['Email göndərmək', 'Məlumat bazasını yeniləmək', 'Hesabat yaratmaq']
# Tapşırığı emal edirik: 'Email göndərmək'
# Tapşırığı emal edirik: 'Məlumat bazasını yeniləmək'
# Cari tapşırıqlar növbəsi: ['Hesabat yaratmaq']
3.3 Məlumat strukturlarının müxtəlif növləri arasındakı fərqlər
Bax bu, müxtəlif növ məlumat strukturlarının əsas fərqləridir:
Massivlər:
- Giriş: İndeks üzrə sürətli giriş —
O(1)
. - Ölçünün dəyişməsi: Sabit ölçü, artırmaq üçün bütün elementlərin kopyalanması tələb olunur —
O(n)
. - Uyğunluğu: Elementlərə təsadüfi giriş üçün, məlumatların ölçüsü əvvəlcədən məlumdursa.
Linqed listlər (Linked Lists):
- Giriş: İndeks üzrə yavaş giriş —
O(n)
. - Ölçünün dəyişməsi: Ölçüsü asanlıqla dəyişdirilir, əlavə etmə və silmə
O(1)
vaxt alır. - Uyğunluğu: Elementlərin tez-tez əlavə olunması və silinməsi üçün.
Stack (Yığın):
- İş prinsipi:
LIFO
. - Əməliyyatlar: Əlavə etmə və silmə yalnız bir tərəfdən —
O(1)
. - Uyğunluğu: Tapşırıqların geriyə doğru icrası, funksiya çağırışlarının idarə olunması üçün.
Queue (Növbə):
- İş prinsipi:
FIFO
. - Əməliyyatlar: Əlavə etmə və silmə fərqli tərəflərdə həyata keçirilir —
O(1)
. - Uyğunluğu: Tapşırıqları daxil olma ardıcıllığı ilə idarə etmək üçün.
3.4 Müxtəlif məlumat strukturlarının tətbiqi
Müxtəlif məlumat strukturlarının praktikada istifadəsinə nümunələr:
Massivlər
Həftənin günləri və ya ilin ayları kimi sabit uzunluqlu məlumatların saxlanılması.
Nümunə: Həftənin günləri ilə işləmək üçün massivdən istifadə
# Həftənin günləri olan massiv yaradırıq
days = ["Bazar ertəsi", "Çərşənbə axşamı", "Çərşənbə", "Cümə axşamı", "Cümə", "Şənbə", "Bazar"]
# Günün indeks üzrə əldə olunması (məsələn, üçüncü gün)
print(days[2]) # Çap: Çərşənbə
# Günün adını dəyişdiririk
days[0] = "Bazar ertəsi (həftənin başlanğıcı)"
print(days[0]) # Çap: Bazar ertəsi (həftənin başlanğıcı)
# Həftənin bütün günlərini keçiririk
for day in days:
print(day)
# Çap:
# Bazar ertəsi (həftənin başlanğıcı)
# Çərşənbə axşamı
# Çərşənbə
# Cümə axşamı
# Cümə
# Şənbə
# Bazar
Bağlı siyahılar
Kolleksiyaların dinamik istifadəsi, harada elementlər kolleksiyanın ortasından əlavə edilə və ya çıxarıla bilər.
Nümunə: İşlər siyahısını saxlamaq üçün bağlı siyahının yaradılması və istifadəsi
class TodoItem:
def __init__(self, task):
self.task = task
self.next = None
class TodoList:
def __init__(self):
self.head = None
def add_task(self, task):
new_item = TodoItem(task)
if not self.head:
self.head = new_item
else:
current = self.head
while current.next:
current = current.next
current.next = new_item
def display_tasks(self):
current = self.head
if not current:
print("İşlər siyahısı boşdur")
else:
while current:
print(f"- {current.task}")
current = current.next
# İşlər siyahısını yaradırıq və istifadə edirik
todo = TodoList()
todo.add_task("Marketdən ərzaq al")
todo.add_task("Anama zəng et")
todo.add_task("Təqdimata hazırlaş")
print("Mənim işlər siyahım:")
todo.display_tasks()
# Çap:
# Mənim işlər siyahım:
# - Marketdən ərzaq al
# - Anama zəng et
# - Təqdimata hazırlaş
Yığın
Tapşırıqların tərs qaydada icrası, məsələn, rekursiyada funksiya çağırışlarının işlənməsi, əməliyyatların ləğvi (undo).
Nümunə: Yığın istifadə edərək stringi tərsinə çevirmək
def reverse_string(s):
stack = []
# Stringin hər bir simvolunu yığına yerləşdiririk
for char in s:
stack.append(char)
reversed_s = ''
# Yığından simvolları çıxararaq tərs string yaradırıq
while stack:
reversed_s += stack.pop()
return reversed_s
# İstifadə nümunəsi
original = "Hello, World!"
reversed_str = reverse_string(original)
print(f"Əsas string: {original}")
print(f"Tərsinə çevrilmiş string: {reversed_str}")
# Çap:
# Əsas string: Hello, World!
# Tərsinə çevrilmiş string: !dlroW ,olleH
Növbə
Tapşırıqların daxil olma sırasına uyğun idarə edilməsi, məsələn, printerdəki tapşırıqlar, müştərilərin xidmət növbəsi.
Nümunə: Sənədlərin çap növbəsinin simulyasiyası
from collections import deque
class PrinterQueue:
def __init__(self):
self.queue = deque()
def add_document(self, document):
self.queue.append(document)
print(f"Sənəd '{document}' çap növbəsinə əlavə edildi")
def print_document(self):
if self.queue:
document = self.queue.popleft()
print(f"Sənəd çap olunur: '{document}'")
else:
print("Çap növbəsi boşdur")
def display_queue(self):
print("Hal-hazırkı çap növbəsi:", list(self.queue))
# Çap növbəsini yaradırıq və istifadə edirik
printer = PrinterQueue()
printer.add_document("Hesabat")
printer.add_document("Təqdimat")
printer.add_document("Müqavilə")
printer.display_queue()
printer.print_document()
printer.print_document()
printer.display_queue()
# Çap:
# Sənəd 'Hesabat' çap növbəsinə əlavə edildi
# Sənəd 'Təqdimat' çap növbəsinə əlavə edildi
# Sənəd 'Müqavilə' çap növbəsinə əlavə edildi
# Hal-hazırkı çap növbəsi: ['Hesabat', 'Təqdimat', 'Müqavilə']
# Sənəd çap olunur: 'Hesabat'
# Sənəd çap olunur: 'Təqdimat'
# Hal-hazırkı çap növbəsi: ['Müqavilə']
Bu nümunədə biz çap növbəsinin sadə simulyasiyasını yaratdıq. Sənədlər növbənin sonuna əlavə edilir və daxil olma sırasına uyğun çap edilir, bu isə FIFO (First In, First Out) prinsipini nümayiş etdirir.
GO TO FULL VERSION