struct address { char name[40]; char street[40]; struct address *next; } info; void Add(struct address *i, struct address **last) { if(!*last) *last = i; else (*last)->next = i; i->next = NULL; *last = i; } 

I study singly linked lists. I have difficulty with the function to add an item to the end of the list. As parameters, it is passed a pointer to an address type structure containing the new entry, and a pointer to the last element of the list. I'm not good at pointers and I don't understand why I need a pointer to a pointer in the function parameters?

For myself, I could not decipher only what this action means: if the last element is not zero, then assign the last value to the last one, otherwise (*last)->next = i; . Then we give the next element a zero value to initialize it as, I understood, and for some reason, the last line. Help please understand

    3 answers 3

    Why do I need a pointer to a pointer in the function parameters?

    Yes, very simple! Because the structure will change!

     void Add(struct address *i, struct address **last) { if (!*last) *last = i; // если last=null -> i - первый элемент else (*last)->next = i; // иначе элементы в списке и есть и пришиваем текущий элемент i в конец списка. i->next = NULL; // следующий элемент = NULL *last = i; // записать в указатель last указатель на структуру i } 

    Look about pointers.

     int f (int x) {x = 0;} int fp(int *x) {x = 0;} int fr(int &x) {x = 3;} ... int y = 1; f(y); // какое значение у y после выполнения f()? y = 1! fp(&y); // какое значение у y после выполнения fp()? y = 0! fr(y); // y = 3! 

      For your task, you need to define two more pointers - a pointer to the first and last element.

       struct data{ // Данные char name[40]; char street[40]; } struct list{ // Односвязанный список data lable; data *next } struct list *head = NULL, *last = NULL; // Указатель на начало и конец void add(list *last, data& data){ list *newPtr = new list; // новый узел в списке list->data = data; if (head == NULL){ // если список пуст указатель на головной элемент будет //указателем на новый узел head = newPtr; last = newPtr; } else{ // Добавляем новый элемент в конец списка last->next = newPtr; last = newPtr; } } 

      Boundary situations and possible exceptions are not provided.

        With this use of Add (), the idea is simple.

        The first argument is the address of the structure that is added to the end. The second address of the current end (in fact, the address of the address!). It (end address) will be changed to the address of the added element each time Add () is called. Therefore (to change the argument 2) and the address of the address is passed (pointer to the pointer (oil)).

        At the first call Add the list is not there yet, so we will pass the address of the pointer with a zero value. This is important (otherwise it will fall). This call replaces the zero address of the end with the address of the added (first argument) list item. Etc.

        Sometimes the Add () function is written a little differently (it’s more convenient for me)

         struct address *Add (struct address *new_elem, struct address *tail) 

        and it returns its first argument (the address of the element inserted at the end), and the next call Add () uses the result of the previous call as argument 2. And if there is no list yet, the 2nd argument is NULL.

        Try, in fact, convenient, especially when manipulating multiple lists.

        • Reasonable. In particular, I liked the idea of ​​storing the address of the last element of the list (some optimization in the speed of adding elements). - gecube