Функция списка STL, которая удаляет N-й элемент из списка и заменяет его M-м элементом из того же списка C . Необходимо использовать перелинковку

#c #function #linked-list #stl

#c #функция #linked-list #stl

Вопрос:

итак, я столкнулся с проблемой, я могу удалить N-й элемент, используя приведенный ниже код, но я совершенно не представляю, как повторно связать ссылки, чтобы получить желаемый результат.

Пример с необходимым результатом. Итак, список равен {1,3,5,4}, мне нужно иметь возможность передавать 2 параметра в функции N и M. Например, N равно 2, что в данном случае равно 3, берется последовательно, M равно 4, что также берется последовательно и в этом случае равно 4. И результат, на который я надеюсь, равен {1,4,5} или, по крайней мере, {1,4,5,4} (жестко, я не уверен, нужны ли дополнительные шаги для второго результата).Я прикрепил свой код ниже, и функция, над которой я работал, — это deleteNode, я был бы очень благодарен, если бы кто-нибудь мог мне помочь.

 using namespace std;

#include <stdio.h>
#include <stdlib.h>

struct Node
{
    int data;
    struct Node *next;
};

void push(struct Node** head_ref, int new_data)
{
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
    new_node->data  = new_data;
    new_node->next = (*head_ref);
    (*head_ref)    = new_node;
}

void deleteNode(struct Node **head_ref, int N)
{
    // Store head node
    struct Node* temp = *head_ref, *prev;


    if (temp != NULL amp;amp; temp->data == N)
    {
        *head_ref = temp->next;
        free(temp);
        return;
    }


    while (temp != NULL amp;amp; temp->data != N)
    {
        prev = temp;
        temp = temp->next;
    }


    if (temp == NULL) return;

    prev->next = temp->next;

    free(temp);
}


void printList(struct Node *node)
{
    while (node != NULL)
    {
        printf(" %d ", node->data);
        node = node->next;
    }
}

int main()
{
    struct Node* sar = NULL;

    push(amp;sar,4);
    push(amp;sar, 5);
    push(amp;sar, 3);
    push(amp;sar, 1);

    puts("Linked lists: ");
    printList(sar);
    deleteNode(amp;sar, 3);
    puts("nList after deletion: ");
    printList(sar);
    return 0;
}
  

Комментарии:

1. Если вы удалите using namespace std; (что в любом случае бесполезно в вашем коде), у вас будет C, а не C . Вы не struct Node* new_node в C . Вы можете удалить начало struct . Вы также должны использовать new , а не malloc . У вас недостаточно продуманное поведение в вашем коде, потому что вы обрабатываете необработанную память так, как это было Node . Это не так. Это C , а не C, опять же.

2. Заголовок вашего вопроса начинается с функции списка STL — Где находится STL в любом из этого кода? В C STL имеет std::list .

3. Скопируйте значение M в N, затем удалите M.

4. Тем не менее, лучший способ решить проблемы, связанные с указателем: возьмите бумагу и ручку. Обработайте это, нарисовав прямоугольники и стрелки.

5. Что означает «функция списка STL» в этом контексте?

Ответ №1:

Если это STL std::list, то следует использовать итератор. Используйте std::next() для продвижения итератора из std::list::begin() к нужному узлу. Используйте std::list::erase() для удаления узла. Используйте два итератора с std::list::splice() для перемещения узла.

Ответ №2:

Я думаю, что если вы немного поработаете, вам будет намного лучше с решением, предложенным rcgldr.

При этом, если вы заинтересованы в использовании своего самодельного списка и совсем не используете C , вы можете попробовать что-то в этом роде:

Внимание, это решение намного менее элегантно, чем что-либо, использующее std::list (опять же, см. Ответ rcgldr), и я не тестировал его должным образом, вы знаете упражнение, не используйте это как есть 🙂

 int replaceNode(int indexToReplace, int indexToReplaceWith, Node **head_ref) {
  assert(head_ref != nullptr amp;amp; "don't pass nulls for head_ref");

  auto freeNode = [](Node **node) {
    assert(node != nullptr amp;amp; "don't pass nulls for node");
    delete *node;
    *node = nullptr;
  };

  Node *toReplace = nullptr, *toReplaceWith = nullptr,
       *previousFromToReplaceWith = nullptr;

  int index = 1; // 1 based or so it seems

  for (Node *cursor = *head_ref, *previous = nullptr; cursor != nullptr;) {
    // search for both nodes in one go
    if (index == indexToReplace) {
      toReplace = cursor;
    }
    if (index == indexToReplaceWith) {
      toReplaceWith = cursor;
      // for the one we delete, we also keep its previous
      previousFromToReplaceWith = previous;
    }

    // you can and should break early in here, by checking agains null
    if (toReplaceWith != nullptr amp;amp; toReplace != nullptr) {
      break;
    }
      index;

    previous = cursor;
    cursor = cursor->next;
  }

  if (toReplaceWith == nullptr || toReplace == nullptr) {
    // set errors, maybe even set a string error, or god forbid, throw :p
    return -1;
  }

  // if it's not the first item, skip it
  if (previousFromToReplaceWith) {
    previousFromToReplaceWith->next = toReplaceWith->next;
  }
  // you only want the value, right? 
  // won't work that well for other types where you'd just switch 
  // the nodes by doing iterator things, i.e. using some 'std::list<T>::splice' 
  // but works for your 'int' case
  toReplace->data = toReplaceWith->data;
  freeNode(amp;toReplaceWith);
  return 0;
}

  

Вероятно, вы можете учесть некоторые из вещей, которые я добавил, и объединить их с вашим узлом удаления.

Также для этого требуется C 11, но я считаю, что в 2020 году это не требует многого, тем не менее, скомпилируйте с вашим любимым компилятором, добавив ваш конкретный стандартный флаг.