#c #linked-list #self
#c #связанный список #self
Вопрос:
#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
Node* addNode(Node*amp; head, int data , intamp; count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count ; // keep track of number of node
head = q;
return q;
}
int main()
{
int a, count=0;
int data;
bool repeat;
Node *head= NULL;
//^^ assuming thats creating the first node ^^
do
{
cout << "please enter the data for the next node" <<endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >>repeat;
}
while (repeat == true);
// assuming this is the print function
while(head != NULL)
{
cout << "output" << temp->item << endl;
cout << temp->next << endl;
}
system("pause");
return 0;
}
окей, я попытался добавить новый элемент в список, как бы мне переместить заголовок, как память LIFO (стек), чтобы последний элемент находился на самом верху..
любая помощь была бы оценена! Указатели и узлы в последнее время не дают мне покоя….
Комментарии:
1. Чтобы использовать кнопку code
{}
, вы должны выбрать весь код.2. Пожалуйста, в следующий раз используйте более подходящий язык.
3. простой поиск в Google может показать вам множество уже готовых примеров C
4. я пытаюсь сделать это сам, поэтому я знаю, как это сделать с нуля
5. обновлено … попытался поместить все в функцию
Ответ №1:
temp
является неинициализированным указателем. Итак —
temp-> item = a; // temp is not initialized or pointing to a memory location
// that has Node object to use operator ->
Во-первых, temp
необходимо выделить ячейку памяти с помощью new
.
temp = new Node;
temp -> item = a;
А теперь назначьте его head
. Аналогичным образом выделите память и для дочерних узлов в while
цикле. И верните все ресурсы, полученные от дочернего элемента, в head с помощью delete
перед завершением программы.
Комментарии:
1. о, моя ошибка, я делал это на лету, не обращал внимания на типы данных
Ответ №2:
Похоже, у вас здесь есть некоторые недоразумения:
Ваша «голова» — это начало списка. Это всегда начало.
Вы Добавить добавляйте элементы в связанный список, присваивая их next
указателю последнего узла.
В-третьих, вы ничего не выделяете.
Node *head= new Node();
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
head->next = temp;
Итак… чтобы добавить следующее, вам нужно либо отслеживать последний узел (хвост), либо пройти по списку, чтобы найти последний узел.
Node *nextNode = new Node();
nextNode->item = 0.0;
Node *i;
for (i = head; i->next != null; i = i->next);
i->next = nextNode;
Это O (n) времени выполнения. Отслеживая хвост, вы делаете его O (1):
Node *head= new Node();
Node *tail = head;
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
tail->next = temp;
tail = temp;
Node *nextNode = new Node();
nextNode->item = 0.0;
tail->next = nextNode;
tail = nextNode;
РЕДАКТИРОВАТЬ: Как указывалось, если вы хотите добавить дополнение к списку, вы бы:
temp->next = head;
head = temp;
Комментарии:
1. Я не согласен. Если бы вы повторили свой код, вы бы создали утечки памяти, поскольку вы переопределяете элемент в <code> head->next</code> несколько раз. Ricedragon сделал это в основном правильно, поскольку он вставляет в начало списка, а затем присваивает заголовку новое значение. По сути, это функция push_front() от std::list . Редактировать: Извините, не увидел ваше последнее предложение с первого раза. Тем не менее, я все еще думаю, что способ Ricedragons работает, за исключением отсутствующего выделения.
2. Я согласен с вами, если вы хотите
push
функциональности. Я описывал добавление ::shrug :: зависит от того, что вы ищете. Раньше я всегда просто отслеживал хвост, чтобы упростить это.3. @Thilo я немного изменил исходный код и не смог разобраться, как добавлять новые элементы в заголовок. @Brian Roach ty это очень помогает, кажется, я понял, в чем дело, теперь я добавил новый код (модификацию исходного, не могли бы вы, пожалуйста, взглянуть на него?)
Ответ №3:
Поскольку я не уверен, что каждый ответ полностью отвечает на него, вот реализация связанного списка (написанная без тестирования:
// your (correct) structure
struct Node
{
float item; // storage for the node's item
Node* next; // pointer to the next node
};
Теперь нам нужны два указателя где-нибудь, чтобы следить за списком:
/* some pointers */
struct List
{
Node* head;
Node* tail;
};
Теперь нам нужно создать некоторые элементы. Как уже говорили другие, вы можете сделать это с помощью new:
/* create some elements we want to link in */
Node* elem1 = new Node();
Node* elem2 = new Node();
Node* elem3 = new Node();
/* maybe even set their properties! */
elem1->item = 3.14;
elem2->item = 3.14;
elem3->item = 3.14;
Заметили, что я еще не пытался добавить эти элементы в список? Это потому, что я имею в виду функцию, которая выглядит следующим образом:
void addtolist(List amp;list, Node* node)
{
/* if no head, initialise the list */
if ( list->head == NULL )
{
list->head = node;
list->tail = node;
}
else if ( list->head != NULL amp;amp; list->tail != NULL )
{
/* access the tail element and set its
next to this ptr.
Move tail to this node */
list->tail->next = node;
list->tail = node;
}
else
{
/* probably raise an exception! */
}
}
Вы можете вызвать это, выполнив это:
List l;
addtolist(l, elem1); /* etc */
Удаление элементов несколько сложнее, поскольку вам нужно перейти к этому элементу, запомнить его предыдущий элемент, захватить его следующий элемент, объединить их и удалить узел *, на котором вы находитесь.
Теперь для обхода списков… ваша терминология HEAD|TAIL
напоминает мне Erlang и хвостовую рекурсию, где текущий элемент называется head, а остальная часть — tail. Если я напишу:
Node* cur = l.head;
while ( cur != NULL )
{
// do something with cur.item ?
cur = cur->next;
}
Вы можете видеть, как это происходит. Замена cur
на head
здесь была бы безвредной благодаря List
структуре.
Наконец, я использовал здесь подход, очень похожий на C, но есть возможности для шаблонов:
template<typename T>
struct node
{
T item; // storage for the node's item
Node<T>* next; // pointer to the next node
};
и инкапсуляция List
структуры как класса:
template<typename T>
class List
{
protected:
Node<T>* head;
Node<T>* tail;
public:
void addtolist(Node<T>* node);
Node<T>* gethead();
Node<T>* gettail();
}
Что немного приближает вас к std::list
.
Комментарии:
1. очень хорошее объяснение, но я не буду делать это грамотно, я ненавижу рекурсию. рекурсивный продолжает морочить мне голову…
2. @ricedragon этот конкретный фрагмент кода не является рекурсией. Рекурсия предполагает использование функций. Просто вы использовали терминологию, очень похожую на идею Erlang о хвостовой рекурсии в списках. Но этот цикл while не является рекурсией, он просто постоянно ищет следующий элемент.
3. @Ninefingure я немного раньше сегодня изучал рекурсивный, да, я понял, что нет. Но это первый раз, когда я вижу хвост и начало в новом узле. Я все еще новичок, поэтому пока буду придерживаться базового, жду вашего ответа
Ответ №4:
Дополнительно обратите внимание, что вы выполняете неявное приведение от int
к float
вкл
temp-> item = a;
as a
является int
, в то время как temp->item
является double
.
Чтобы решить вашу проблему: вы хотите выделить новую структуру перед доступом temp
, таким образом
temp = new Node();
Комментарии:
1. хорошо, я попробую это, а затем отправлю ответ, если у меня возникнут дополнительные проблемы