Evgenii Legotckoi
Evgenii Legotckoi22 квітня 2019 р. 02:13

Операції зі зв'язаним списком

Ця стаття присвячена старту курсу ["Алгоритми для розробників"] (https://otus.ru/lessons/algorithm/?utm_source=partners&utm_medium=cpm&utm_campaign=algo&utm_term=evileg&utm_content=dod#event Висловлюю подяку за підтримку ресурсу даною компанією.

Давайте вивчимо, які операції можна виконувати зі зв'язаним списком.

Два важливі моменти, які потрібно пам'ятати:

  • head вказує на перший вузол пов'язаного списку
  • next покажчик останнього вузла дорівнює nullptr , тому, якщо наступний з поточного вузла дорівнює nullptr , ми досягли кінця зв'язаного списку.

У всіх прикладах ми припускатимемо, що пов'язаний список має три вузли 1 ---> 2 ---> 3 зі структурою вузла, як показано нижче:

struct node
{
    int data;
    struct node* next {nullptr};
};

Як пройти по зв'язаному списку

Відображення вмісту пов'язаного списку дуже просто. Ми продовжуємо переміщати тимчасовий вузол до наступного та відображаємо його вміст.

Коли temp дорівнює NULL , ми знаємо, що досягли кінця зв'язаного списку, тому ми виходимо із циклу while .

struct node* temp = head;
std::cout << std::endl << std::endl << "List elements are - " << std::endl;
while(temp != nullptr)
{
    std::cout << temp->data << " ---> ";
    temp = temp->next;
}

Виведення цієї програми буде:

List elements are - 
1 ---> 2 ---> 3 --->

Як додати елементи до пов'язаного списку

Ви можете додавати елементи на початок, середину або кінець пов'язаного списку.

Додати до початку

  • Виділіть пам'ять для нового вузла
  • Збережіть дані
  • Змініть новий next вузол, щоб він вказував на head
  • Змініть head , щоб вказати на нещодавно створений вузол
struct node* newNode = new node();
newNode->data = value;
newNode->next = head;
head = newNode;

Додати в кінець

  • Виділіть пам'ять для нового вузла
  • Збережіть дані
  • Зробіть перехід до останнього вузла
  • Змініть next з останнього вузла на нещодавно створений вузол
struct node* newNode = new node();
newNode->data = value;
newNode->next = nullptr;

struct node *temp = head;
while (temp->next != nullptr)
{
    temp = temp->next;
}
temp->next = newNode;

Додати в середину

  • Виділіть пам'ять та збережіть дані для нового вузла
  • Перехід до вузла безпосередньо перед необхідною позицією нового вузла
  • Змініть next покажчики, щоб додати новий вузол між ними
struct node *newNode = new node();
newNode->data = value;

struct node *temp = head;

for (int i=2; i < position; i++)
{
    if (temp->next != nullptr)
    {
        temp = temp->next;
    }
}
newNode->next = temp->next;
temp->next = newNode;

Як видалити вузол зі зв'язаного списку

Ви можете видалити або з початку, з кінця або з певної позиції.

Видалити з початку

  • Налаштуйте вказівник head на другий вузол
head = head->next;

Видалити з кінця

  • Перейти до другого останнього елементу
  • Змінити next покажчик на nullptr
struct node* temp = head;
while (temp->next->next != nullptr)
{
    temp = temp->next;
}
temp->next = nullptr;

Видалити з середини

  • Перехід до елемента до елемента, що видаляється
  • Змінити next покажчики, щоб виключити вузол з ланцюжка
struct node* temp = head;
for (int i = 2; i < position; ++i)
{
    if (temp->next != nullptr)
    {
        temp = temp->next;
    }
}

temp->next = temp->next->next;

Повна програма для операцій зі зв'язаним списком

Ось повна програма для всіх операцій із пов'язаним списком, який ми вивчили. Багато крайніх випадків були опущені, щоб зробити програму короткою.

Ми пропонуємо вам просто поглянути на програму та спробувати її реалізувати самостійно.

Також зверніть увагу на те, як ми передаємо адресу head як struct node headRef у функції insertAtFront та deleteFromFront. Ці дві функції змінюють положення вказівника head , тому нам потрібно передати адресу вказівника head** та змінити його значення всередині функції.

#include <iostream>

struct node
{
  int data;
  struct node* next {nullptr};
};

void display(struct node* head)
{
    struct node* temp = head;
    std::cout << std::endl << std::endl << "List elements are - " << std::endl;
    while(temp != nullptr)
    {
        std::cout << temp->data << " ---> ";
        temp = temp->next;
    }
}

void insertAtMiddle(struct node *head, int position, int value)
{
    struct node *newNode = new node();
    newNode->data = value;

    struct node *temp = head;

    for (int i=2; i < position; i++)
    {
        if (temp->next != nullptr)
        {
            temp = temp->next;
        }
    }
    newNode->next = temp->next;
    temp->next = newNode;
}

void insertAtFront(struct node** headRef, int value)
{
    struct node* head = *headRef;

    struct node* newNode = new node();
    newNode->data = value;
    newNode->next = head;
    head = newNode;

    *headRef = head;
}

void insertAtEnd(struct node* head, int value)
{
    struct node* newNode = new node();
    newNode->data = value;
    newNode->next = nullptr;

    struct node *temp = head;
    while (temp->next != nullptr)
    {
        temp = temp->next;
    }
    temp->next = newNode;
}

void deleteFromFront(struct node** headRef)
{
    struct node* head =  *headRef;
    head = head->next;
    *headRef = head;
}

void deleteFromEnd(struct node* head)
{
    struct node* temp = head;
    while (temp->next->next != nullptr)
    {
      temp = temp->next;
    }
    temp->next = nullptr;
}

void deleteFromMiddle(struct node* head, int position)
{
    struct node* temp = head;
    for (int i = 2; i < position; ++i)
    {
        if (temp->next != nullptr)
        {
            temp = temp->next;
        }
    }

    temp->next = temp->next->next;
}

int main()
{
  /* Initialize nodes */
  struct node *head;
  struct node *one = new node();
  struct node *two = new node();
  struct node *three = new node();

  /* Assign data values */
  one->data = 1;
  two->data = 2;
  three->data = 3;

  /* Connect nodes */
  one->next = two;
  two->next = three;
  three->next = nullptr;

  /* Save address of first node in head */
  head = one;

  display(head); // 1 ---> 2 ---> 3 --->

  insertAtFront(&head, 4);
  display(head); // 4 ---> 1 ---> 2 ---> 3 --->

  deleteFromFront(&head);
  display(head); // 1 ---> 2 ---> 3 --->

  insertAtEnd(head, 5);
  display(head); // 1 ---> 2 ---> 3 ---> 5 --->

  deleteFromEnd(head);
  display(head); // 1 ---> 2 ---> 3 --->

  int position = 3;
  insertAtMiddle(head, position, 10);
  display(head); // 1 ---> 2 ---> 10 ---> 3 --->

  deleteFromMiddle(head, position);
  display(head); // 1 ---> 2 ---> 3 --->
}

Виведення програми буде наступним

List elements are - 
1 ---> 2 ---> 3 ---> 

List elements are - 
4 ---> 1 ---> 2 ---> 3 ---> 

List elements are - 
1 ---> 2 ---> 3 ---> 

List elements are - 
1 ---> 2 ---> 3 ---> 5 ---> 

List elements are - 
1 ---> 2 ---> 3 ---> 

List elements are - 
1 ---> 2 ---> 10 ---> 3 ---> 

List elements are - 
1 ---> 2 ---> 3 --->

Висновок

Також ви можете вивчити більш поглиблено алгоритми на курсі ["Алгоритми для розробників"]. зможете більш поглиблено вивчити як базові алгоритми, і складніші.

Курс пропонує наступне:

  • Розуміння принципів роботи різноманітних алгоритмів, структур даних
  • Вміння використовувати готові алгоритми та структури даних та створювати свої під поставлене завдання
  • Володіння технікою обчислення складності алгоритмів
  • Освоєння просунутих структур даних: хеш-таблиць, графів, дерев пошуку та багатьох інших
  • Вміння вирішувати алгебраїчні задачі та завдання динамічного програмування

При цьому на даному курсі пропонується вивчення алгоритмів та структур даних з використанням мов програмування як Java, C++, Python.

Ви можете перевірити свої сили в тестуванні , щоб зрозуміти, чи готові до проходження даного курсу Вам додатково.

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 01:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 01:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 11:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi31 жовтня 2024 р. 14:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 08:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 07:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 11:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi24 червня 2024 р. 15:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 06:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 03:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 09:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Слідкуйте за нами в соціальних мережах