связанный список C , вопрос самообучения

#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. хорошо, я попробую это, а затем отправлю ответ, если у меня возникнут дополнительные проблемы