Как добавить элементы в двусвязный список?

415
21 марта 2022, 20:40

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

#include <iostream>
using namespace std;
struct List {
    float num;
    List *next;
    List *prev;
};
List *ls = NULL;
void fill_list(){
    List *tmp, *last = NULL;
    for (int i = 0; i < 11; i++){
        tmp = new List;
        tmp->num = i;
        tmp->next = NULL;
        if (ls == NULL)
            ls = tmp;
        else
            last->next = tmp;
        last = tmp;
    }
}
void show(){
    for (List *tmp = ls; tmp; tmp = tmp->next)
        cout << tmp->num << " ";
    cout << endl;
}
void func(float a, float b){
    List *prev = NULL, *tmp;
    for (tmp = ls; tmp; prev = tmp, tmp = tmp->next)
    {
    }
}
int main()
{
    float a,b;
    fill_list();
    int sw;
    while (1)
    {
        cout << "1 - show(), 2 - func(a,b), 3 - exit" << endl;
        cin >> sw;
        switch (sw) {
            case 1:
                show();
            case 2:
                cout << "Input a, b " << endl;
                cin >> a;
                cin >> b;
                func(a,b);
            case 3:
                return 0;
        }
    }
    return 0;
}

fill_list - заполняет список, show - выводит список, func - должна добавить a в начало списка, b в конец списка

Answer 1

Давайте сначала пройдемся по вашим ошибкам в текущей реализации:

  1. При заполнении двусвязного списка вы ни разу не используете *prev, то есть работаете с ним, как с односвязным.
  2. В case после выполнения одного из сценариев всегда выполнится следующий, потому что вы в сценариях не используете break
  3. В вашей реализации вы нигде не храните начало и конце списка, что повлечет за собой пробег по всем элементам списка, чтобы вставить в нужное место требуемое значение
  4. У вас нигде не обрабатывается сценарий того, что список может быть изначально пустой

Ниже прилагаю вам код, где реализовано то, что вы хотели получить.

Сразу, опережая вопрос, почему мы в конец добавляем не отдельной функцией, а общей функцией добавления элемента в список Add - потому что Add всегда будет добавлять элемент в конец. И если вы все-таки используете С++, то не понятно, зачем изобретать велосипед, когда есть готовый контейнер list

#include <stdlib.h>
#include <iostream>
using namespace std;
struct Node                             //Структура, являющаяся звеном списка
{
    int x;                             //Значение x будет передаваться в список
    Node* Next, * Prev;                 //Указатели на адреса следующего и предыдущего элементов списка
};
class List                              //Создаем тип данных Список
{
    Node* Head, * Tail;                 //Указатели на адреса начала списка и его конца
public:
    List() :Head(NULL), Tail(NULL) {};    //Инициализируем адреса как пустые
    ~List();                           //Прототип деструктора
    void Show();                       //Прототип функции отображения списка на экране
    void Add(int x);                   //Прототип функции добавления элементов в список
    void AddFirst(int x);              //Прототип функции добавления в элемента в начало
    void func(int a, int b);           //Прототип требуемой вами функции
};
void List::func(int a, int b) {
    AddFirst(a);
    Add(b);
}
void List::AddFirst(int x) {
    Node* temp = new Node;
    temp->Next = NULL;                   //Указываем, что изначально по следующему адресу пусто
    temp->Prev = NULL;
    temp->x = x;
    if (Head != NULL) {                  //Если список не пустой
        temp->Next = Head;               //Указываем на предыдущий первый элемент
        Head->Prev = temp;               //Предыдущий перый элемент теперь указывает на новый первый элемент
        Head = temp;                     //Переназначаем первый элемент
    }
    else {                          //Если список пустой
        Head = Tail = temp;
    }
}
List::~List()                           //Деструктор
{
    while (Head)                       //Пока по адресу на начало списка что-то есть
    {
        Tail = Head->Next;             //Резервная копия адреса следующего звена списка
        delete Head;                   //Очистка памяти от первого звена
        Head = Tail;                   //Смена адреса начала на адрес следующего элемента
    }
}
void List::Add(int x)
{
    Node* temp = new Node;               //Выделение памяти под новый элемент структуры
    temp->Next = NULL;                   //Указываем, что изначально по следующему адресу пусто
    temp->x = x;                         //Записываем значение в структуру
    if (Head != NULL)                    //Если список не пуст
    {
        temp->Prev = Tail;               //Указываем адрес на предыдущий элемент в соотв. поле
        Tail->Next = temp;               //Указываем адрес следующего за хвостом элемента
        Tail = temp;                     //Меняем адрес хвоста
    }
    else //Если список пустой
    {
        temp->Prev = NULL;               //Предыдущий элемент указывает в пустоту
        Head = Tail = temp;              //Голова=Хвост=тот элемент, что сейчас добавили
    }
}
void List::Show()
{
    Node* temp = new Node;
    //ВЫВОДИМ СПИСОК С КОНЦА
    /*temp = Tail;                   //Временный указатель на адрес последнего элемента
    while (temp != NULL)               //Пока не встретится пустое значение
    {
        cout << temp->x << " ";        //Выводить значение на экран
        temp = temp->Prev;             //Указываем, что нужен адрес предыдущего элемента
    }
    cout << "\n";*/
    //ВЫВОДИМ СПИСОК С НАЧАЛА
    temp = Head;                       //Временно указываем на адрес первого элемента
    while (temp != NULL)              //Пока не встретим пустое значение
    {
        cout << temp->x << " ";        //Выводим каждое считанное значение на экран
        temp = temp->Next;             //Смена адреса на адрес следующего элемента
    }
    cout << "\n";
}
int main()
{
    List lst; //Объявляем переменную, тип которой есть список
    int sw;
    int a, b;
    for (int i = 0; i < 11; i++) //Аналог нашей функции fill_list
        lst.Add(i);
    while (1)
    {
        cout << "1 - show(), 2 - func(a,b), 3 - exit" << endl;
        cin >> sw;
        switch (sw) {
            case 1:
                lst.Show();
                break;
            case 2:
                cout << "Input a, b " << endl;
                cin >> a;
                cin >> b;
                lst.func(a, b);
                break;
            case 3:
                exit(0);
        }
    }
    system("PAUSE");
    return 0;
}
READ ALSO
Двойное нажатие ЛКМ

Двойное нажатие ЛКМ

Я хочу сделать программу, которая при одном клике делает второй(нужно для копирования от 1 клика)Но,что я не пробовал, всё-равно выполняется...

81
Java. Прозрачность формы. @Override

Java. Прозрачность формы. @Override

Новый вопросЕсть появляющаяся форма (на ней элементы), задача сделать ее полупрозрачной

53
Установка библиотек Spring на сервер

Установка библиотек Spring на сервер

Каждый раз когда мне надо обновить Spring приложение, мне необходимо закачивать на сервер файл размером 30 мегабайт, 29 из которых занимают библиотеки...

106
MyFrame is not abstract and does not override abstract method actionPerfomed (ActionEvent) Action Listener, new level

MyFrame is not abstract and does not override abstract method actionPerfomed (ActionEvent) Action Listener, new level

Самостоятельно изучаю java с помощью книжкиТакая проблема и до этого выскакивала, я просто сменил версию, не помогло

200