Простой связанный список C++

C ++ не является контекстно-свободным. Я узнал это некоторое время назад в лекции компиляторов. Быстрый поиск дал эту ссылку, где раздел «Синтаксис или семантика» объясняет, почему C и C ++ не являются контекстно-свободными:

Обсуждение Википедии: Грамматика без контекста

С уважением,
Ованес

7
задан John Calsbeek 8 July 2009 в 04:31
поделиться

9 ответов

Сначала в connectedList :: addNode , у вас есть конструкция if (head = NULL) , которая завершится присвоением head ; вам нужен оператор == .

Во-вторых, о строке:

head = &(Node (value, NULL));

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

head = new Node(value, NULL);

Если вы добавляете метод удаления узла, убедитесь, что вы удалили узел, затем - он не будет автоматически обрабатываться сборщиком мусора, как в Java.

Боковая панель: Подумайте, что происходит следующим образом: когда вы выполняете Node (value, NULL) , вы используете временная переменная, объявленная так:

 Node hiddenTempNode (значение, NULL);

При этом не выделяется место для объекта где-либо, кроме стека - это очень похоже на выделение места для int и узла * в стеке как отдельных переменных. В результате, как только вы выйдете из метода, объект исчезнет, ​​и указатель на него будет делать странные вещи при использовании.

В-третьих, будьте осторожны: вы можете установить next = NULL в вашем однопараметрический конструктор, чтобы всегда иметь значение. Аналогично для вашего конструктора по умолчанию.

Четвертый: ваш метод connectedList :: print зацикливается до тех пор, пока p-> next не станет NULL и не распечатает значение p-> следующий ; те появления p->

6
ответ дан 6 December 2019 в 15:25
поделиться

Вы не распределяете память. Вы должны использовать new для ее распределения.

Еще одна ошибка в if (head = NULL), она должна быть if (head == NULL)

void addNode(int value){
            Node *p;
            if(head == NULL)
                    head =  new Node (value, NULL);
            else{
                    p=head;
                    while(p->next !=NULL)
                            p=p->next;
                    p->next = new Node (value, NULL);
                    }
            }
1
ответ дан 6 December 2019 в 15:25
поделиться

вы берете адрес переменных в стеке

head = &(Node (value, NULL));

следует изменить на

head = new Node(value, NULL);

, то же самое для кода p-> next. Затем вы захотите удалить эти узлы в своем деструкторе.

Что касается печати, попробуйте

while(p != NULL)
{
   cout << p->data << "\n";
   p = p->next;
}
3
ответ дан 6 December 2019 в 15:25
поделиться

Для начала

if(head = NULL)

- это задание, а не проверка на равенство. Измените его на

if(head == NULL)

Во-вторых,

head = &(Node (value, NULL));

Не имеет смысла * измените это на

head = new Node (value, NULL);

* это фактически создает временный объект, дает вам адрес, а затем уничтожает этот вновь созданный объект.

В-третьих,

Node(int x) { data = x; }

] Оставьте следующий без значения, измените эту строку на

Node(int x) { data = x; next = NULL; }
2
ответ дан 6 December 2019 в 15:25
поделиться

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

Node* node = new Node(value, NULL);

Вы должны освободить все, что вы размещаете в куче, как только оно вам не понадобится, чтобы предотвратить утечку памяти:

delete node;
2
ответ дан 6 December 2019 в 15:25
поделиться

Я хотел бы добавить две проблемы, которые еще не упоминались:

  • когда вы «создаете» объекты, вы должны в какой-то момент «удалить» их.
  • все три ваших конструкторов должны инициализировать обе переменные-члены.
1
ответ дан 6 December 2019 в 15:25
поделиться

Ваш оператор удаления на самом деле не выполняет никакой очистки. К тому времени, когда вы назовете это p == null. Если вы хотите очистить список, вам нужно будет реализовать отдельный метод для перебора и удаления каждого узла.

Что-то вроде этого:

void ClearList ()
{
    Node * c = head;
    Node * n;

    while (c != NULL)
    {
        n = c->next;
        delete c;
        c = n;
    }
}
1
ответ дан 6 December 2019 в 15:25
поделиться

Теперь код работает, но пытается используйте

delete p;

в конце connectedList :: addNode приводит к ошибке сегментации на время выполнения. Просто любопытно, знал ли кто почему?

Что ж, это проблема, потому что цель функции добавления узла состояла в том, чтобы динамически выделить новый узел в конце LinkedList. Итак, вы делаете это правильно, теперь поставив 'delete p;' вы удаляете только что добавленный узел (что, как я полагаю, вам на самом деле не нужно). Однако, чтобы ответить на ваш вопрос, почему это вызывает ошибку сегментации:

Вы добавляете узел, вы говорите head указать на этот новый узел. Теперь вы удаляете этот новый узел, не сообщая head, что он снова должен указывать на NULL. Таким образом, в следующий раз, когда вы добавите узел или попытаетесь распечатать свой список, он немедленно попытается посмотреть, на что указывает голова, которая на самом деле является освобожденной (удаленной) памятью, kaboom?

Правильное (или хотя бы одно правильное) использование delete в вашем списке - это деструктор,

0
ответ дан 6 December 2019 в 15:25
поделиться

Решение: не создавайте собственный связанный список. Используйте тот, который предоставляется стандартной библиотекой.

-2
ответ дан 6 December 2019 в 15:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: