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