Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.97/148: Рейтинг темы: голосов - 148, средняя оценка - 4.97
0 / 0 / 0
Регистрация: 11.06.2011
Сообщений: 33

Связанные списки

15.06.2012, 13:53. Показов 31264. Ответов 44
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Составить программу, работающую со связанными списками. Мы будем рассматривать связанный список как объект, содержащий связанный список данных и операций (методов), которые вы можете с ними выполнять. Связанный список данных состоит из указателей на начало («голову») и конец («хвост») связанного списка (в нашем примере из-за его гибкости используется двунаправленный связанный список). Каждый элемент связанного списка представляет собой реализацию отдельного объекта. Возможности, необходимые для использования связанного списка, предоставляют следующие операции:
• создание связанного списка (выделение для него памяти);
• уничтожение связанного списка (освобождение используемой памяти);
• инициализация связанного списка;
• деинициализация связанного списка;
• вставка элемента в середину списка перед существующим элементом;
• присоединение элемента к концу связанного списка;
• удаление элемента из связанного списка;
• возвращение первого элемента связанного списка;
• возвращение последнего элемента связанного списка.
Необходимо иметь в виду, что создание и инициализация, а также уничтожение и деинициализация методов — это не синонимы. При создании и уничтожении методы create и destroy выделяют и освобождают память для объекта (связанного списка), а методы инициализации и деинициализации initialize и deinitialize только инициализируют и деинициализируют ранее выделенные экземпляры объекта. Вы можете видеть, как объект связанного списка наследуется объектами стека или очереди, поскольку очередь и стек можно реализовать как связанный список с ограниченным числом операций. Например, можно реализовать очередь в виде связанного списка, в котором элементы могут добавляться к концу и извлекаться из начала. Если вы таким образом реализуете очередь, то нужно запретить наследуемые методы связанного списка, которые для очереди недопустимы (например, вставку в середину списка).

Добавлено через 2 часа 22 минуты
По ходу никто не сможет помочь
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
15.06.2012, 13:53
Ответы с готовыми решениями:

связанные списки
плиз помогите написать задачку: Запросить у пользователя число n. Построить связный список из n элементов, заполненный случайными...

Связанные списки
Вопросы в комментариях #include <iostream> #include <conio.h> #include <string.h> using namespace std; class NameDataSet { ...

Связанные списки
Здравствуйте! Не очень сложное задание, но так как я начинающий, запуталась немного... особенно с указателями и ссылками. В общем...

44
 Аватар для David Sylva
1321 / 983 / 267
Регистрация: 17.05.2012
Сообщений: 2,687
15.06.2012, 15:18
Вот тебе возьми за основу связный список, ничего не хватает добавишь сам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <iostream> 
using namespace std;
 
typedef int newtp;
struct node 
{ 
    newtp data; //  данные 
    node* next; // указатель на следующий
    node* pred; // указатель на предыдущий
}; 
 
class linklist // класс связный список
{ 
private: 
    node* first; // указатель на начало
public: 
    linklist() { first = NULL; } // в конструкторе инициализируем его, он указывает в 
                                 // в место где нет полезной информации
 
    void push( newtp d, int pos); // метод добавления элемента
    int pop( int pos);  // метод удаления элемента
    void clean(); // удаление всех элементов
    void view(); // вывод на экран
}; 
 
void linklist::push( newtp d, int pos) // метод добавления элемента
{ 
 
    node* newnode = new node; // создаём новый элемент
    newnode->data = d; // вводим в него данные
    if(first == NULL)   // если это первый элемент в списке                                   
    { 
        newnode->next = newnode; 
        newnode->pred = newnode; 
        first = newnode; // first  указывает на него
    } 
    else 
    {
        node* temp = first; // создаём времменный указатель
        for ( int i = pos; i > 1; i--,temp=temp->next); // цикл
            temp->pred->next = newnode; 
            newnode->pred = temp->pred; 
            newnode->next = temp; // добавляем перед времменным
            temp->pred = newnode;  
    }
}  
 
int linklist::pop( int pos) // удаляем элемент из списка по индексу
{ 
  if(first == NULL)  return 0; // если список пуст
  int val;  
  if(first == first ->next) // если это последний элемент в списке
  { 
      val = first->data; 
      delete first; 
      first = NULL; 
  } 
  else  
 { 
      node* temp = first; 
      for ( int i = pos; i > 1; i--, temp = temp->next); 
          if( temp == first) first = temp->next; 
              temp->pred->next = temp->next; // удаляем temp элемент
              temp->next->pred = temp->pred; 
              val = temp->data; 
              delete temp;   
  } 
  return val; 
} 
 
void linklist::clean() // удалить все элементы из списка
{  
    if(first == NULL) return ; 
    for ( node* newnode = first->next; newnode!=first; newnode = newnode->next) delete newnode; 
    delete first; 
    first = NULL; 
}
 
void linklist::view() // просмотр элементов в списке
{  
    if(first == NULL) return ; 
    node* newnode = first; 
    do 
    { 
        cout << newnode->data << endl; 
        newnode = newnode->next; 
    } while(newnode!=first); 
}
 
int main() 
{ 
    linklist li; 
    
    li.push(12,1); 
    li.push(13,2); 
    li.push(14,2); 
 
    li.view();
 
    
}
2
5 / 5 / 5
Регистрация: 25.09.2012
Сообщений: 42
25.09.2012, 23:40
Всем привет. ребят подскажите плз., где косяк допустил в листинге, уже голову сломал.
Смысл такой, надо создать метод для добавления элемента в конец связанного списка.
при компиляции возникает сообщение о прекращении работы программы
вот мой листинг:

#include <iostream>
using namespace std;
////////////////////////////////////////////////////////////////////////////////
struct link
{
int data;
link* next;
};
////////////////////////////////////////////////////////////////////////////////
class linklist
{
private:
link* first;
public:
linklist()
{ first = NULL; }
void additem(int d)
{
link *newlink = new link;
if(first==NULL)
{
newlink -> data = d;
newlink -> next = first;
first = newlink;
}
else
{
link *temp = first;
while(temp)
temp = temp -> next;
temp -> next = newlink;
newlink -> data = d;
newlink -> next = NULL;
}
}
void display()
{
link *temp = first;
while(temp)
{
cout << temp -> data << endl;
temp = temp -> next;
}
}
};
////////////////////////////////////////////////////////////////////////////////
int main()
{
linklist m;
m.additem(10);
m.additem(20);
m.additem(30);
m.additem(40);
m.display();
cout << endl;
system("pause");
return 0;
}
0
 Аватар для I.M.
576 / 559 / 47
Регистрация: 16.12.2011
Сообщений: 1,389
25.09.2012, 23:44
Sher_vud, у вас получается петля при добавлении первого элемента в список.
newlink -> next = first; не надо. надо занулять
0
5 / 5 / 5
Регистрация: 25.09.2012
Сообщений: 42
25.09.2012, 23:56
I.M. попробовал проставить NULL, к сожалению работать метод по прежнему отказывается.
больше всего сомнений в этих строках:
else
{
link *temp = first;
while(temp)
temp = temp -> next = newlink;
//temp -> next = newlink;
newlink -> data = d;
newlink -> next = NULL;
}
вот не могу не много понять. по идее когда завершается цикл указатель темп глядит на последний элемент списка. ну и я логично пытаюсь в поле next этого элемента изменить указатель со значения NULL на новоявленый элемент. Вешаться начало все после написания строки:
temp -> next = newlink;
я ее закоментил и попробовал по другому, что так же привело к аварийному завершению
temp = temp -> next = newlink; ( добавил =newlink)
вот и не пойму где я не правильно понял работу метода
0
 Аватар для BumerangSP
4311 / 1423 / 463
Регистрация: 16.12.2010
Сообщений: 2,939
Записей в блоге: 3
26.09.2012, 00:19
Sher_vud, вот, чуть подкорректировал функцию добавления:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void additem(int d)
{
 link *temp;
 link *newlink=first;
 if(first==NULL)
  {
   temp = new link;
            temp -> data = d;
   temp -> next = first;
   first = temp;
  }
 else
 {
  temp = newlink;
  while(temp->next)
   temp = temp -> next;
  temp->next = new link;
  temp = temp -> next;
  temp -> data = d;
 }
 temp-> next = NULL;
 newlink=temp;
}
0
5 / 5 / 5
Регистрация: 25.09.2012
Сообщений: 42
26.09.2012, 00:44
BumerangSP спасибо большое, все работает. сей час попробую разобраться где допустил ошибку.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
26.09.2012, 00:45
Можно и так сделать:
C++
1
2
3
4
5
6
7
8
void additem(int d)
{
     link *newlink = new link;
 
     newlink -> data = d;
     newlink -> next = first;
     first = newlink;
}
Тут ещё всё зависит от того, по какому принципу список строится. Самый простой - по принципу стека, т.е. последний по времени создания элемент будет в голове списка. Мой метод именно для него. Можно и по другому, чтобы в голове списка был первый по времени создания элемент.
0
5 / 5 / 5
Регистрация: 25.09.2012
Сообщений: 42
26.09.2012, 01:01
alsav22 такой метод я как раз использовал, изучая главу "указатели". в задании к этой главе было необходимо как раз изменить данный метод, так что бы элементы вставали не в начала списка, а с конца.
если честно, пока тяжело понять каким образом описать метод с привязкой по времени создания элемента. наверное должна использоваться какая то библиотечная функция, если alsav22 Вы расскажете подробнее, буду рад узнать что то новое.
BumerangSP никак не могу понять вот эту строчку:

while(temp->next)

делаем, пока указатель содержит не NULL? я в правильную сторону мыслю?
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
26.09.2012, 01:26
Цитата Сообщение от alsav22 Посмотреть сообщение
Можно и по другому, чтобы в голове списка был первый по времени создания элемент.
Тогда вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
using namespace std;
 
struct link
{
    int data;
    link* next;
};
 
class linklist
{
 private:
    link* first; // начало списка
    link* rear; // конец списка
 
 public:
    linklist()
    { 
        first = NULL;
        rear = NULL;
    }
    
    void additem(int d)
    {
       link *newlink = new link; // новый элемент списка
       newlink -> data = d;
       newlink -> next = NULL;
        
       if (first == NULL) // если список пустой, то в начало
            first = newlink; // first начало списка
       else  rear -> next = newlink; // если список не пустой, то в конец
       
       rear = newlink; // rear конец списка
    }
    
    void display()
    {
        link *temp = first;
        while(temp)
        {
            cout << temp -> data << endl;
            temp = temp -> next;
        }
    }
};
 
 
int main()
{
 linklist m;
 m.additem(10);
 m.additem(20);
 m.additem(30);
 m.additem(40);
 m.display();
 cout << endl;
 
 system("pause");
 return 0;
 }
0
 Аватар для BumerangSP
4311 / 1423 / 463
Регистрация: 16.12.2010
Сообщений: 2,939
Записей в блоге: 3
26.09.2012, 01:34
Sher_vud, вот у Вас было так:
C++
1
2
3
while(temp)
 temp = temp -> next;
...
т.е. пока текущий указатель temp не будет равен NULL. В моем же случае (temp->next) пока указатель на следующий элемент не будет = NULL. Т.е. тем самым мы смещаем указатель temp на последний элемент в списке. Если мы будем смещать указатель только текущего элемента, мы в итоге встретим null, цикл завершится, указывая на null, а не на последний элемент.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
26.09.2012, 01:54
Удалил.
0
5 / 5 / 5
Регистрация: 25.09.2012
Сообщений: 42
26.09.2012, 01:56
BumerangSP спасибо огромное, теперь понял
alsav22 спасибо, я понял суть метода, но вот механизм пока не удается осмыслить.
запутался в этих строках:
C++
1
2
else  rear -> next = newlink; // если список не пустой, то в конец
rear = newlink; // rear конец списка
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
26.09.2012, 02:09
Мне кажется, что вариант BumerangSP не очень рационален. Из за того, что нет указателя на конец очереди, приходится каждый раз, при добавлении нового элемента, пробегать по очереди от первого элемента до последнего.
0
5 / 5 / 5
Регистрация: 25.09.2012
Сообщений: 42
26.09.2012, 02:19
alsav22, BumerangSP, еще раз Вам спасибо. может тороплюсь, но все же. переработал свой метод, на основании Ваших замечаний и поправок. все заработало
вот что у меня получилось:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
      void additem(int d)
             {
                  link *temp = first;
                  link *newlink = new link;
                  if(first==NULL)
                  {
                  newlink -> data = d;
                  newlink -> next = NULL;
                  first = newlink;
                  }
                  else
                  {
                  while(temp->next)
                  temp = temp -> next;
                  temp -> next = newlink;
                  newlink -> data = d;
                  newlink -> next = NULL;
                  }
             }
делаю вывод, что грубая ошибка крылась в цикле, а именно:
while(temp)
0
 Аватар для BumerangSP
4311 / 1423 / 463
Регистрация: 16.12.2010
Сообщений: 2,939
Записей в блоге: 3
26.09.2012, 02:23
alsav22, я просто чуть исправил готовую функцию. Это односвязный линейный список, не очередь.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
26.09.2012, 02:42
Цитата Сообщение от Sher_vud Посмотреть сообщение
alsav22 спасибо, я понял суть метода, но вот механизм пока не удается осмыслить.
запутался в этих строках:
else rear -> next = newlink; // если список не пустой, то в конец
rear = newlink; // rear конец списка
Два указателя first и rear. Один указывает на начало списка, другой на конец. Сначала оба на NULL. Создаётся новый элемент, на него указывает newlink. Если список пустой, то значение newlink присваивается указателю на начало списка - first. Это произойдёт одни раз. В следующие разы заход будет уже только в else. То есть first в дальнейшем меняться не будет, и он будет указывать на начало списка. В первый раз else пропускается, после него указателю rear присваивается значение newlink, то есть, пока элемент в списке один, начало и конец списка совпадают. При добавлении следующего элемента заход только в else. После этого элемент, который до этого был в конце списка, будет содержать указатель на добавляемый элемент (rear -> next = newlink), а rear присваивается адресс нового элемента (rear = newlink), т.е. новый элемент становится концом списка, адресс которого находится в rear.

Добавлено через 6 минут
Цитата Сообщение от BumerangSP Посмотреть сообщение
Это односвязный линейный список, не очередь.
Я и имел ввиду список. Просто в разных источниках это всё по разному называется, где очередь, где список. Односторонняя очередь, двусторонняя. Односвязанный список, двусвязанный список. Сути это не меняет. Я не спорю, просто поясняю. Тут можно увязнуть в определениях.
0
5 / 5 / 5
Регистрация: 25.09.2012
Сообщений: 42
26.09.2012, 02:47
Цитата Сообщение от alsav22 Посмотреть сообщение
В первый раз else пропускается, после него указателю rear присваивается значение newlink
alsav22 спасибы, наконец то дошло. я видимо пересидел уже.. смотрел и представлял:
C++
1
2
3
4
5
else  
{
rear -> next = newlink; 
rear = newlink;
}
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
26.09.2012, 03:08
Хитрость этой конструкции в том, чтобы при первом проходе выполнилось только rear = newlink; , а при втором и далее - и rear -> next = newlink;, и rear = newlink;
0
 Аватар для BumerangSP
4311 / 1423 / 463
Регистрация: 16.12.2010
Сообщений: 2,939
Записей в блоге: 3
26.09.2012, 12:24
Просто в разных источниках это всё по разному называется, где очередь, где список
alsav22, это да. Но у меня именно односвязный список Просто делая функцию, я ни о каком другом виде не думал. И, опять же: будь это очередь, ее элементы при выборке исчезали бы (как в стеке или деке). Исправьте, если неправ.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
26.09.2012, 12:24
Помогаю со студенческими работами здесь

Связанные списки С++
Здравствуйте, изучаю С++ и возникли проблемы с пониманием как работают списки. Вот код: #include &lt;cstdio&gt; #include...

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

Связанные списки (переделать программу)
Как переделать программу, чтобы можно было вводить самому ключи и не было Access Violation? #include &lt;iostream&gt; #include...

Односвязанные и двух-связанные списки
Должны быть следующие функции: 1) Ввод количества элементов и заполнение списка случайными значениями 2) Вывод списка на экран 3)...

Подскажите как отладить код (связанные списки)
условие закомментировано в коде, подскажите, в чём ошибка? функция Sum Должна возвращать требуемое число // ВЫЧИСЛЯЕТ СУММУ ТЕХ ЭЛЕМЕНТОВ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru