CodeGym /Kurslar /JAVA 25 SELF /Queue, Deque, Stack: növbələr və yığınlarla iş

Queue, Deque, Stack: növbələr və yığınlarla iş

JAVA 25 SELF
Səviyyə, Dərs
Mövcuddur

1. Queue interfeysi: klassik növbə (FIFO)

Proqramlaşdırmada, həyatda olduğu kimi, bəzən təkcə elementləri saxlamaq deyil, onların emal qaydasını idarə etmək vacibdir. Supermarketdə növbəni təsəvvür edin: kim başlanğıca daha yaxındırsa — daha tez xidmət alır. Bu, FIFO prinsipidir — “birinci gələn — birinci gedən”. Şkafdakı boşqab yığını isə LIFO prinsipi ilə işləyir — “son gələn — ilk gedən”. Java-da bu prinsiplərə koleksiyalar cavab verir: növbələr Queue, iki uclu növbələr Deque və yığınlar Stack.

Harada tətbiq olunur:

  • Tapşırıqların daxilolma qaydasında emalı (tapşırıq növbəsi, sənədlərin çapı, hadisələrin emalı).
  • Əməllərin ləğvi (undo/redo) — yığın.
  • Ifadələrin parsinqi, ağac və qrafların keçilməsi (eninə/dərinliyinə axtarış) və daha çox.

Növbə nədir?

Növbə (Queue) — FIFO prinsipi ilə qurulmuş kolleksiyadır. Elementlər sonuna əlavə olunur və başlanğicdan çıxarılır. Mağazada olduğu kimi: kim daha tez gəlibsə, ilk olaraq o xidmət alır.

Queue interfeysinin əsas metodları

Metod Nə edir Qaytarır
offer(e)
Elementi sonuna əlavə edir (istisnasız) true/false
add(e)
Elementi sonuna əlavə edir (istisna atır) true/istisna
poll()
Birinci elementi silir və qaytarır element/null
remove()
Birinci elementi silir və qaytarır element/istisna
peek()
Birinci elementi silmədən qaytarır element/null
element()
Birinci elementi silmədən qaytarır element/istisna

Oxşar davranışlı cüt metodları gördünüz. Fərq “yumşaqlıq”dadır: offer, poll, peek uğursuzluqda xüsusi dəyər qaytarır (adətən null və ya false) və istisna atmır, add, remove, element isə sərhəd vəziyyətlərində (boş növbə, bəzən də dolma) istisna atır.

Nümunə: tapşırıqlar növbəsi

import java.util.*;

public class QueueDemo {
    public static void main(String[] args) {
        Queue<String> tasks = new LinkedList<>();
        tasks.offer("Dişləri fırçalamaq");
        tasks.offer("İdman etmək");
        tasks.offer("Qəhvə içmək");

        while (!tasks.isEmpty()) {
            String task = tasks.poll(); // Tapşırığı növbənin əvvəlindən götürürük
            System.out.println("İcra edirəm: " + task);
        }
    }
}

Çıxış:

İcra edirəm: Dişləri fırçalamaq
İcra edirəm: İdman etmək
İcra edirəm: Qəhvə içmək

Niyə çox vaxt LinkedList istifadə olunur?

İnterfeys — müqavilədir və bir neçə reallaşdırması var. Tez-tez LinkedList istifadə olunur, çünki hər iki sondan sürətli əlavə/silmə edir. Lakin əla alternativ — ArrayDeque-dur. Xüsusiləşdirilmiş variantlar da var: PriorityQueue (prioritetlərə görə növbə), bu barədə aşağıda.

2. Deque interfeysi: iki uclu növbə

Deque (Double Ended Queue, “dek”) — elementləri hər iki tərəfdən: həm əvvəlindən, həm də sonundan əlavə edib silmək mümkün olan növbədir. Sanki iki qapılı avtobus: daxil olub-çıxmaq hər iki tərəfdən mümkündür.

Deque = universal əsgər: adi növbə (FIFO), yığın (LIFO) və hibrid kimi işləyə bilər.

Deque interfeysinin əsas metodları

Metod Nə edir İstifadə nümunəsi
addFirst(e)
Əvvəlinə əlavə et
ochered.addFirst("A")
addLast(e)
Sonuna əlavə et
ochered.addLast("B")
removeFirst()
Əvvəldən sil və qaytar
ochered.removeFirst()
removeLast()
Sondan sil və qaytar
ochered.removeLast()
peekFirst()
Əvvələ bax (silmədən)
ochered.peekFirst()
peekLast()
Sona bax (silmədən)
ochered.peekLast()
offerFirst(e)
Əvvəlinə əlavə et (istisnasız)
ochered.offerFirst("C")
offerLast(e)
Sonuna əlavə et (istisnasız)
ochered.offerLast("D")

Nümunə: Deque həm növbə, həm yığın kimi

import java.util.*;

public class DequeDemo {
    public static void main(String[] args) {
        Deque<String> deque = new ArrayDeque<>();

        // Növbə kimi istifadə edirik (FIFO)
        deque.offerLast("A");
        deque.offerLast("B");
        deque.offerLast("C");
        System.out.println("Növbə (FIFO):");
        while (!deque.isEmpty()) {
            System.out.println(deque.pollFirst());
        }

        // Yığın kimi istifadə edirik (LIFO)
        deque.offerLast("1");
        deque.offerLast("2");
        deque.offerLast("3");
        System.out.println("Yığın (LIFO):");
        while (!deque.isEmpty()) {
            System.out.println(deque.pollLast());
        }
    }
}

Çıxış:

Növbə (FIFO):
A
B
C
Yığın (LIFO):
3
2
1

Niyə ArrayDeque?

ArrayDeque — Deque-in massiv üzərində sürətli və sıx reallaşdırmasıdır. Yığın və növbə üçün o, adətən köhnə Stack-dən daha sürətli və etibarlıdır, və sabit ölçüsü yoxdur (yalnız yaddaşla məhdudlaşır).

3. Stack: yığın — son daxil olan, ilk çıxır (LIFO)

Yığın — LIFO prinsipi ilə işləyən kolleksiyadır: üst element son əlavə edilən olur. Proqramlaşdırmada yığın əməl tarixçəsi (undo), rekursiv strukturların (ağaclar/qraflar) keçilməsi, ifadələrin hesablanması və s. üçün faydalıdır.

Stack sinfi (və niyə ondan istifadə etməmək lazımdır)

Java-da Stack sinfi var və o, köhnəlmiş Vector-dan miras alır. Bu gün yeni layihələrdə ondan istifadə tövsiyə edilmir. Daha üstün seçim — Deque/ArrayDeque.

Yığın metodları (Deque)

Metod Nə edir
push(e)
Elementi yığının üstünə qoy
pop()
Üst elementı götür və qaytar
peek()
Üst elementə bax

Diqqət: Deque-də bu əməliyyatlar addFirst/removeFirst/peekFirst metodlarına uyğundur, lakin uyğunluq üçün push/pop/peek “yığın” adları da mövcuddur.

Nümunə: ArrayDeque üzərində yığın

import java.util.*;

public class StackDemo {
    public static void main(String[] args) {
        Deque<String> stack = new ArrayDeque<>();
        stack.push("Birinci");
        stack.push("İkinci");
        stack.push("Üçüncü");

        while (!stack.isEmpty()) {
            System.out.println(stack.pop());
        }
    }
}

Çıxış:

Üçüncü
İkinci
Birinci

Niyə Stack deyil?

  • Stack sinxronizasiya olunub (daha yavaşdır) və köhnəlmiş Vector-dan miras alır.
  • ArrayDeque çox vaxt daha sürətli və daha sıxdır, axınları bloklamır.
  • Yeni kodda Stack görsəniz — adətən o, ArrayDeque ilə əvəzlənməli namizəddir.

4. Nə zaman və nə istifadə etməli

Struktur Prinsip Harada istifadə etmək Reallaşdırma nümunəsi
Queue FIFO Tapşırıqlar növbəsi, hadisələrin emalı, çap, müştəri növbələri
LinkedList, ArrayDeque, PriorityQueue
Stack LIFO Undo/redo, rekursiya, parserlər, ağacların keçilməsi
ArrayDeque
Deque FIFO/LIFO Bufferlər, palindromlar, iki uclu növbələr, universal tapşırıqlar
ArrayDeque, LinkedList

Həyatdan nümunələr:

  • Bankda növbə — Queue.
  • Redaktorda əməl tarixçəsi — Stack.
  • Avtobus növbəsi, hər iki tərəfdən giriş/çıxış — Deque.

5. Kod nümunələri: mini-tətbiqdə növbə və yığını reallaşdıraq

Nümunə 1: Sənədlərin çap növbəsi

import java.util.*;

public class PrintQueueApp {
    public static void main(String[] args) {
        Queue<String> printQueue = new ArrayDeque<>();
        printQueue.offer("Sənəd1.pdf");
        printQueue.offer("Sənəd2.docx");
        printQueue.offer("Sənəd3.xls");

        while (!printQueue.isEmpty()) {
            String doc = printQueue.poll();
            System.out.println("Çap olunur: " + doc);
        }
    }
}

Nümunə 2: Əməllərin ləğv yığını (undo)

import java.util.*;

public class UndoStackApp {
    public static void main(String[] args) {
        Deque<String> undoStack = new ArrayDeque<>();
        undoStack.push("Mətni daxil etmə");
        undoStack.push("Rəngin dəyişdirilməsi");
        undoStack.push("Şəklin silinməsi");

        System.out.println("Son əməl: " + undoStack.peek()); // Şəklin silinməsi

        while (!undoStack.isEmpty()) {
            System.out.println("Geri al: " + undoStack.pop());
        }
    }
}

Nümunə 3: İki uclu növbə

import java.util.*;

public class DequeApp {
    public static void main(String[] args) {
        Deque<String> deque = new ArrayDeque<>();
        deque.addFirst("A");
        deque.addLast("B");
        deque.addFirst("C");
        deque.addLast("D");

        System.out.println("Əvvəldən çıxarırıq: " + deque.removeFirst()); // C
        System.out.println("Sondan çıxarırıq: " + deque.removeLast());   // D
        System.out.println("Qaldı: " + deque); // [A, B]
    }
}

6. Reallaşdırma xüsusiyyətləri və nüanslar

  • ArrayDeque — əksər tapşırıqlar üçün növbə/yığın reallaşdırması olaraq ən sürətli və ən universal seçimdir.
  • LinkedList — həmçinin Deque-i reallaşdırır; faydalı ola bilər, lakin qısa növbələr üçün adətən ArrayDeque-dən daha yavaşdır.
  • PriorityQueue — prioritetə görə növbədir: qayda prioritetlə (təbii və ya Comparator vasitəsilə) müəyyən olunur, bu, adi FIFO-növbə deyil.
  • Stack — köhnəlmiş və sinxronlaşdırılmışdır; yeni layihələrdə ArrayDeque üstünlük təşkil edir.
  • Deque həm əvvəl, həm də sonla işləməyə imkan verdiyi üçün növbə və yığın ssenarilərini tək abstraksiya ilə əhatə edir.

7. Növbələr və yığınlarla işləyərkən tipik səhvlər

Səhv №1: Deque əvəzinə Stack-dən istifadə.
Bir çox yeni başlayanlar Stack sinfini adı görə seçirlər. Müasir layihələrdə onun yerinə ArrayDeque (və ya LinkedList) üzərində push/pop metodları istifadə olunur.

Səhv №2: Strukturun prinsipini pozmaq.
Növbə/yığın elementlərinə indekslə müraciət etməyə çalışırlar, məsələn queue.get(0) və ya stack.get(0). Belə olmaz — növbə və yığın üçün uyğun metodlardan istifadə edin (peek, poll, pop və s.).

Səhv №3: remove()/element()/add() yoxlamasız istifadə.
remove, element, add metodları boş/dolmuş strukturda istisna ata bilər. Uğursuzluqda xüsusi dəyər qaytaran “yumşaq” offer, poll, peek metodları ilə işləmək daha təhlükəsizdir.

Səhv №4: ArrayDeque-də null elementlərdən istifadə.
ArrayDeque null qəbul etmir. null əlavə etmək cəhdi NullPointerException-a səbəb olacaq.

Səhv №5: PriorityQueue-nu adi növbə kimi istifadə etmək.
PriorityQueue-da qayda prioritetlərlə müəyyən edilir (təbii və ya Comparator vasitəsilə). Sərt FIFO üçün ArrayDeque və ya LinkedList istifadə edin.

Səhv №6: for-each ilə keçərkən növbə/yığını dəyişmək.
for-each zamanı kolleksiyadan element silmək ConcurrentModificationException-a gətirib çıxara bilər. Silmə üçün iterator istifadə edin və ya nümunələrdə göstərildiyi kimi dövrdə poll/pop metodlarından istifadə edin.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Sistemdə növbəti tapşırığa baxış 💼
Sistemdə növbəti tapşırığa baxış 💼
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Printerin işləməsinin və əməliyyat tarixçəsinin təqlidi 🖨️🔄
Printerin işləməsinin və əməliyyat tarixçəsinin təqlidi 🖨️🔄
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION