Загрузка данных


// === 1. ЭЛЕМЕНТ СПИСКА (ДВУСВЯЗНЫЙ УЗЕЛ) ===
class Node {
    public int data;  // Данные кирпичика
    public Node next; // Стрелочка на следующий элемент (вперед)
    public Node prev; // Стрелочка на предыдущий элемент (назад)

    public Node(int value) {
        data = value;
        next = null;
        prev = null;
    }
}

// === 2. ДВУХСВЯЗНЫЙ ДВУСТОРОННИЙ СПИСОК ===
class DoublyLinkedList {
    Node first = null; // Ссылка на начало списка
    Node last = null;  // Ссылка на конец списка
    int currentSize = 0; // Счетчик элементов

    public boolean isEmpty() {
        return first == null;
    }

    public int getSize() {
        return currentSize;
    }

    // Вставка в самое НАЧАЛО списка (для Стека)
    public void insertFirst(int value) {
        Node newBrick = new Node(value);
        if (isEmpty()) {
            last = newBrick; // Если список пуст, новый узел становится и последним
        } else {
            first.prev = newBrick; // Старый первый смотрит назад на новый
            newBrick.next = first; // Новый смотрит вперед на старый первый
        }
        first = newBrick; // Новый официально стал первым
        currentSize++;
    }

    // Вставка в самый КОНЕЦ списка (для Очереди)
    public void insertLast(int value) {
        Node newBrick = new Node(value);
        if (isEmpty()) {
            first = newBrick; // Если список пуст, новый узел становится и первым
        } else {
            last.next = newBrick; // Старый последний смотрит вперед на новый
            newBrick.prev = last; // Новый смотрит назад на старый последний
        }
        last = newBrick; // Новый официально стал последним
        currentSize++;
    }

    // Вставка ПО ПОРЯДКУ возрастания (для Приоритетной очереди)
    public void insertInOrder(int value) {
        Node newBrick = new Node(value);
        
        if (isEmpty()) {
            first = newBrick;
            last = newBrick;
            currentSize++;
            return;
        }

        Node current = first;
        // Шагаем вперед, пока не найдем число, которое больше нашего value
        while (current != null && value > current.data) {
            current = current.next;
        }

        if (current == first) { 
            insertFirst(value); // Если нужно встать в самое начало
        } else if (current == null) { 
            insertLast(value);  // Если нужно встать в самый конец
        } else { 
            // Вставка в середину между current.prev и current (раздвигаем вагоны)
            newBrick.next = current;
            newBrick.prev = current.prev;
            current.prev.next = newBrick;
            current.prev = newBrick;
            currentSize++;
        }
    }

    // Удаление ВСЕГДА С НАЧАЛА списка (для всех трех структур)
    public void removeFirst() {
        if (isEmpty()) return;

        if (first.next == null) { // Если в списке был всего один кирпичик
            first = null;
            last = null;
        } else {
            first = first.next; // Новым первым становится следующий узел
            first.prev = null;  // Отрезаем стрелочку назад у нового первого узла
        }
        currentSize--;
    }

    // Получить значение первого элемента
    public int getFirstValue() {
        if (isEmpty()) {
            return -1; 
        }
        return first.data;
    }

    // Вывод всех элементов на экран
    public void printList() {
        Node current = first;
        while (current != null) {
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }
}

// === 3. КЛАСС СТЕК (LIFO) ===
class Stack {
    DoublyLinkedList list = new DoublyLinkedList();

    public void push(int num) {
        list.insertFirst(num); // Кладём всегда в начало (наверх стопки)
    }

    public void pop() {
        if (!list.isEmpty()) {
            list.removeFirst(); // Удаляем верхний элемент
        } else {
            System.out.println("Стек пуст");
        }
    }

    public int peek() {
        return list.getFirstValue(); // Просто смотрим на верхний элемент
    }

    public boolean isEmpty() {
        return list.isEmpty();
    }

    public int size() {
        return list.getSize();
    }

    public void printStack() {
        System.out.print("Стек: ");
        list.printList();
    }
}

// === 4. КЛАСС ОЧЕРЕДЬ (FIFO) ===
class Queue {
    DoublyLinkedList list = new DoublyLinkedList();

    public void push(int num) {
        list.insertLast(num); // Новые элементы встают в конец очереди
    }

    public void pop() {
        if (!list.isEmpty()) {
            list.removeFirst(); // Первые пришедшие уходят первыми из начала
        } else {
            System.out.println("Очередь пуста");
        }
    }

    public int peek() {
        return list.getFirstValue(); // Смотрим, кто первый на выход
    }

    public boolean isEmpty() {
        return list.isEmpty();
    }

    public int size() {
        return list.getSize();
    }

    public void printQueue() {
        System.out.print("Очередь: ");
        list.printList();
    }
}

// === 5. КЛАСС ПРИОРИТЕТНАЯ ОЧЕРЕДЬ ===
class Priority {
    DoublyLinkedList list = new DoublyLinkedList();

    public void push(int num) {
        list.insertInOrder(num); // Автоматическая сортировка при добавлении
    }

    public void pop() {
        if (!list.isEmpty()) {
            list.removeFirst(); // Удаляем самый приоритетный (минимальный) элемент
        } else {
            System.out.println("Приоритетная очередь пуста");
        }
    }

    public int peek() {
        return list.getFirstValue(); // Посмотреть на самый приоритетный элемент
    }

    public boolean isEmpty() {
        return list.isEmpty();
    }

    public int size() {
        return list.getSize();
    }

    public void printPriority() {
        System.out.print("Приоритетная очередь: ");
        list.printList();
    }
}

// === 6. ОСНОВНОЙ КЛАСС ДЛЯ ПРОВЕРКИ ===
public class Main {
    public static void main(String[] args) {
        System.out.println("=== СТЕК НА ДВУСВЯЗНОМ СПИСКЕ ===");
        Stack stack = new Stack();
        stack.push(10);
        stack.push(20);
        stack.push(30);
        stack.printStack(); // Выведет: 30 20 10 (30 наверху)
        System.out.println("Вершина через peek: " + stack.peek());
        System.out.println("Текущий размер: " + stack.size());
        stack.pop();
        stack.printStack(); // Выведет: 20 10

        System.out.println("\n=== ОЧЕРЕДЬ НА ДВУСВЯЗНОМ СПИСКЕ ===");
        Queue queue = new Queue();
        queue.push(100);
        queue.push(200);
        queue.push(300);
        queue.printQueue(); // Выведет: 100 200 300 (100 в начале)
        System.out.println("Первый элемент через peek: " + queue.peek());
        System.out.println("Текущий размер: " + queue.size());
        queue.pop();
        queue.printQueue(); // Выведет: 200 300

        System.out.println("\n=== ПРИОРИТЕТНАЯ ОЧЕРЕДЬ НА ДВУСВЯЗНОМ СПИСКЕ ===");
        Priority pr = new Priority();
        pr.push(55);
        pr.push(11);
        pr.push(33);
        pr.printPriority(); // Автоматически выстроит по росту: 11 33 55
        System.out.println("Приоритетный (минимальный) через peek: " + pr.peek());
        pr.pop(); // Уберет 11
        pr.printPriority(); // Выведет: 33 55
    }
}