Операции со связанным списком

OTUS, Алгоритм

Content

Данная статья приурочена к старту курса "Алгоритмы для разработчиков" от компании OTUS. Выражаю признательность за поддержку ресурса данной компанией.

Давайте изучим, какие операции можно выполнять со связанным списком.

Два важных момента, которые нужно помнить:

  • 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 --->

Заключение

Также вы можете изучить более углублённо алгоритмы на курсе "Алгоритмы для разработчиков" от компании OTUS вы сможете более углублённо изучить как базовые алгоритмы, так и более сложные.

Курс предлагает следующее:

  • Понимание принципов работы разнообразных алгоритмов, структур данных
  • Умение использовать готовые алгоритмы и структуры данных и создавать свои под поставленную задачу
  • Владение техникой вычисления сложности алгоритмов
  • Освоение продвинутых структур данных: хэш-таблиц, графов, деревьев поиска и многих других
  • Умение решать алгебраические задачи и задачи динамического программирования

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

Вы можете проверить свои силы в тестировании , чтобы понять готовы ли к прохождению данного курса, и что данный курс даст вам дополнительно.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate

Comments

Only authorized users can post comments.
Please, Log in or Sign up
How to become an author?

Contribute to the evolution of the EVILEG community.

Learn how to become a site author.

Learn it
Donate

Good day, Dear Users!!!

I am Evgenii Legotckoi, developer of EVILEG. And it is my hobby project, which helps to learn programming another programmers and developers

If the site helped you, and you want also support the development of the site, than you can donate by following ways

PayPalYandex.Money
Timeweb

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting Timeweb
June 6, 2020, 12:20 a.m.
Aleksej

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:60points,
  • Rating points-1
June 6, 2020, 12:15 a.m.
Aleksej

C++ - Test 001. The first program and data types

  • Result:53points,
  • Rating points-4
V
June 5, 2020, 5:47 p.m.
Vladzo

C++ - Test 005. Structures and Classes

  • Result:83points,
  • Rating points4
Last comments
June 5, 2020, 11:52 a.m.
progammist

Распознавание изображений на Python с помощью TensorFlow и Keras

Огромное спасибо за метериал, по-больше бы подобных статей (с подробным описанием работы и примерами применения) на тему современных технологий. Вопрос поразмышлять. На текущий момент реал…
June 5, 2020, 2:39 a.m.
Evgenij Legotskoj

Qt/C++ - Tutorial 091. How to write a custom delegate controlling the highlighting of a row in a table

По-моему, смысла в этом нет особого. Если делегат будет игнорировать настройки таблицы, то это приведёт ещё к большему непониманию, что вообще происходит, для программиста, который после вас буд…
June 5, 2020, 2:34 a.m.
IscanderChe

Qt/C++ - Tutorial 091. How to write a custom delegate controlling the highlighting of a row in a table

Сижу, размышляю: можно ли переписать делегата так, чтобы независимо от настроек строк выделялись строки?
June 5, 2020, 2:31 a.m.
Evgenij Legotskoj

Qt/C++ - Tutorial 091. How to write a custom delegate controlling the highlighting of a row in a table

Понятно. Я не обратил внимания на то, что там было в старом коде по настройкам строк :)
Now discuss on the forum
s
June 6, 2020, 2:54 a.m.
shuric

Qt/C++ Определение положения курсора над действие(кнопкой) в QToolBar

Доброго дня. Возник вопрос - как можно определить что курсор находится над определенным действием(кнопкой) в qtoolbar ? mainwindow.cpp MainWindow::MainWi…
s
June 6, 2020, 1:45 a.m.
shuric

Qt/C++ особенности QProxyStyle

Да, Вы правы. Код был скопирован с сайта (уже не помню с какого), но решил пойти по пути более легком. Пришлось переписать - кому интересно: использовал stackedWidget для пе…
June 6, 2020, 12:08 a.m.
Aleksej

Посоветуйте новичку (базы данных и Qt, что учить)

Блин, а я недавно купил Шлее Qt 5.10 :( С детства хотел стать программистом, баловался Паскалем, писал простенькие программки на Delphi, создавал движок на php, изучал C (забросил и перешел на п…
June 5, 2020, 2:09 p.m.
IscanderChe

QPlainTextEdit настройка цвета фона

Вечер добрый. Пытаюсь настроить цвет фона QPlainTextEdit следующим образом: CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent){ ... QPalette::ColorRole role = bac…
June 5, 2020, 7:13 a.m.
IscanderChe

Фильтр для QtableView sql

Добрый день. Для такой фильтрации необходимо использовать QSortFilterProxyModel. В оффдоках есть хороший пример.
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB