Автор оригинала: Pankaj Kumar.
Связанный список-это линейная структура данных, содержащая последовательность элементов, так что каждый элемент имеет ссылку на следующий элемент в последовательности.
Каждый элемент в связанном списке называется “Узлом”. Каждый узел содержит элемент данных и следующий узел, который указывает на следующий узел в связанном списке.
В связанном списке мы можем создать столько узлов, сколько захотим, в соответствии с нашими требованиями.
Зачем нам нужен Связанный список?
Хотя вы, должно быть, видели структуру данных массивов ранее, они тоже являются линейной структурой данных, но они создают определенные ограничения, такие как:
- Они статичны по своей природе, и поэтому их размер не может быть изменен.
- Им нужна непрерывная память для хранения своих ценностей.
Для устранения этих ограничений Связанный список предлагает следующие функции:
- ДИНАМИЧЕСКОЕ ВЫДЕЛЕНИЕ ПАМЯТИ т. е. выделение памяти выполняется во время выполнения компилятором.
- Каждый отдельный узел может иметь любой блок памяти, и он связан с другими узлами по адресу блока, поэтому не требуется никаких смежных блоков памяти.
Общая реализация связанного списка
- Класс связанного списка содержит узел частного класса и объект класса Узла (называемый как Head) в качестве одного из его свойств.
- Заголовок узла указывает на начало Связанного списка.
- Каждый узел содержит элемент данных и следующий узел, который указывает на следующий узел в Связанном списке.
- Последние узлы указывают на нуль.
- В более новых вариантах у нас также есть элемент хвостового узла, который помогает нам сократить трудоемкость операций, которые необходимо легко выполнять.
Операции со связанными списками
Реализация связанного списка должна иметь следующие методы общего назначения.
- get First : Он возвращает данные (если таковые имеются, иначе он создает исключение), присутствующие на первом узле. Он просто возвращает ” this.head.данные “предоставлены” если(это.) “, т. е. если размер связанного списка не равен нулю.
- get Last : Он возвращает данные (если таковые имеются, иначе он создает исключение), присутствующие на последнем узле. Он просто возвращает ” this.tail.data “при условии” если(это.) “, т. Е. если размер связанного списка не равен нулю.
- get At : В качестве аргумента используется целочисленный индекс, и если индекс допустим(т. Е. Если и индекс <размер связанного списка), он getNodeAt : В качестве аргумента он принимает целочисленный индекс, и если индекс допустим(т. Е. Если и индекс <размер связанного списка), он возвращает
- Узел по этому индексу. addLast : Он принимает ввод типа связанного списка, а затем добавляет его в последнюю позицию связанного списка, тем самым увеличивая размер на “+1” и указывая “хвост” на недавно добавленный узел.
- addFirst : Он принимает ввод типа связанного списка, а затем добавляет его в первую позицию связанного списка, тем самым увеличивая размер на “+1” и указывая “головку” на недавно добавленный узел.
- addAt : Он принимает входные данные типа Связанного списка, а также принимает в качестве аргументов целочисленный индекс (пусть он равен “k”), а затем добавляет его (данные) в k-ю позицию связанного списка, тем самым увеличивая размер на “+1”. В случае, если добавляемый элемент “
- Первый ” или ” Последний “, он вызывает ” addFirst ” или ” addLast ” соответственно. removeFirst : Он удаляет первый элемент связанного списка (при условии, что список не является пустым списком, в котором он создает исключение) и перемещает “заголовок”, чтобы указать на 2
- nd элемент (если таковой имеется ) и уменьшает размер на “1”. Кроме того, он возвращает удаленные данные. removeLast : Он удаляет последний элемент связанного списка (при условии, что список не является пустым списком, в котором он создает исключение) и перемещает “хвост”, указывая на 2
- nd последний элемент (если таковой имеется), и уменьшает размер на “1”. Кроме того, он возвращает удаленные данные. RemoveAt : В качестве аргумента он принимает целочисленный индекс (скажем, k), и если индекс допустим(т. Е. Если и индекс <размер связанного списка), удаляет “k-й” элемент связанного списка (при условии, что список не является пустым списком, в котором он создает исключение) и уменьшает размер на “1”. Кроме того, он возвращает удаленные данные. В случае, если удаляемый элемент “
- Первый ” или ” Последний “, он вызывает ” удалить первым ” или ” Удалить последний ” соответственно. display : Этот метод выводит весь связанный список, проходя его один раз, начиная с указателя, указывающего на “head”, пока он не укажет на “null”.
Реализация связанного списка в Java
package com.journaldev.ds; public class LinkedList { private class Node { int data; Node next; } private Node head; private Node tail; private int size; public int size() { return this.size; } public int getFirst() throws Exception { if (this.size == 0) { throw new Exception("LL is Empty."); } return this.head.data; } public int getLast() throws Exception { if (this.size == 0) { throw new Exception("LL is Empty."); } return this.tail.data; } public int getAt(int idx) throws Exception { if (this.size == 0) { throw new Exception("LL is Empty."); } if (idx < 0 || idx >= this.size) { throw new Exception("Invalid Index."); } Node temp = this.head; for (int i = 1; i <= idx; i++) { temp = temp.next; } return temp.data; } private Node getNodeAt(int idx) throws Exception { if (this.size == 0) { throw new Exception("LL is Empty."); } if (idx < 0 || idx >= this.size) { throw new Exception("Invalid Index."); } Node temp = this.head; for (int i = 1; i <= idx; i++) { temp = temp.next; } return temp; } public void addLast(int item) { // create Node nn = new Node(); nn.data = item; nn.next = null; // attach if (this.size > 0) this.tail.next = nn; // dm update if (this.size == 0) { this.head = nn; this.tail = nn; this.size += 1; } else { this.tail = nn; this.size += 1; } } public void addFirst(int item) { // create Node nn = new Node(); nn.data = item; nn.next = null; // attach nn.next = this.head; // dm update if (this.size == 0) { this.head = nn; this.tail = nn; this.size++; } else { this.head = nn; this.size++; } } public void addAt(int item, int idx) throws Exception { if (idx < 0 || idx > this.size) { throw new Exception("Invalid Index."); } if (idx == 0) { addFirst(item); } else if (idx == this.size) { addLast(item); } else { // create Node nn = new Node(); nn.data = item; nn.next = null; // attach Node nm1 = getNodeAt(idx - 1); Node np1 = nm1.next; nm1.next = nn; nn.next = np1; // dm this.size++; } } public int removeFirst() throws Exception { if (this.size == 0) { throw new Exception("LL is empty."); } Node temp = this.head; if (this.size == 1) { this.head = null; this.tail = null; this.size = 0; } else { this.head = this.head.next; this.size--; } return temp.data; } public int removeLast() throws Exception { if (this.size == 0) { throw new Exception("LL is empty."); } Node temp = this.tail; if (this.size == 1) { this.head = null; this.tail = null; this.size = 0; } else { Node sm2 = getNodeAt(this.size - 2); sm2.next = null; this.tail = sm2; this.size--; } return temp.data; } public int removeAt(int idx) throws Exception { if (this.size == 0) { throw new Exception("LL is empty."); } if (idx < 0 || idx >= this.size) { throw new Exception("Invalid Index."); } if (idx == 0) { return removeFirst(); } else if (idx == this.size - 1) { return removeLast(); } else { Node nm1 = getNodeAt(idx - 1); Node n = nm1.next; Node np1 = n.next; nm1.next = np1; this.size--; return n.data; } } public void display() { System.out.println("----------------------"); Node temp = this.head; while (temp != null) { System.out.print(temp.data + " "); temp = temp.next; } System.out.println("."); System.out.println("----------------------"); } public static void main(String[] args) throws Exception { LinkedList list = new LinkedList(); list.addLast(10); list.addLast(20); list.addLast(30); list.addLast(40); // this will display the list list.display(); // first element i.e.10 should be printed System.out.println(list.getFirst()); // last element i.e.40 should be printed System.out.println(list.getLast()); // element at 3rd index i.e.40 should be printed System.out.println(list.getAt(3)); // a memory address of a node should be printed System.out.println(list.getNodeAt(3)); // 10 should be removed and printed System.out.println(list.removeFirst()); // 40 should be removed and printed System.out.println(list.removeLast()); // list without 10 and 40 should be printed list.display(); // 100 should be added at first list.addFirst(100); list.display(); // 30 should be removed list.removeAt(2); // 300 should be added at 2nd index list.addAt(300, 2); list.display(); } }
Выход
Реализация связанного списка
ПРИМЕЧАНИЕ: Java обеспечивает реализацию LinkedList. Для фактического программирования используйте официальную реализацию.
Java LinkedList – Список ссылок На Java
Сложность Операций со Связанными Списками
getFirst | O(1) |
получить Последнее | O(1) {Примечание: Это потому , что у нас тоже есть указатель “хвост”, иначе это было бы O(n) } |
добраться До | O(n) |
Приготовьтесь к обеду | O(n) |
addLast | O(1) {Примечание: Это потому , что у нас тоже есть указатель “хвост”, иначе это было бы O(n) } |
Добавить сначала | O(1) |
добавить | O(n) |
Удалить первым | O(1) |
Удалить последние | O(1) {Примечание: Это потому , что у нас тоже есть указатель “хвост”, иначе это было бы O(n) } |
удалить | O(n) |
Дисплей | O(n) |
Вывод
Связанный список-одна из самых популярных структур данных. Он часто используется для последовательного хранения данных. Мы предоставили базовую реализацию Связанного списка. Но он не оптимизирован для производственного использования. Пожалуйста, используйте языковую реализацию Связанного списка в реальном программировании.