В односвязном списке функция дублирования не работает для последнего элемента

Нужно дублировать элементы списка поле дата которых есть чётное число (дубликат вставить перед нужным элементом)Мне казалось что функция(copy) рабочая , но когда я изменил число элементов в списке я заметил что последний элемент списка не дублируется в том случае если количество элементов не четное , не понимаю почему это происходит

Изначально список состоит из 3 элементов :(2,3,4) после функции copy выходит :(2,2,3,4) а должно:(2,2,3,4,4)

Изменил функцию copy : добавил еще один указатель для анализа работы по tmp а не по tmp->next , но почему-то не работает ,думаю, что это может быть из-за того , что я не правильно использовал указатель back .

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
struct TNode {
    int data;
    struct TNode *next;
};
typedef struct TNode Node;
void CreateNode(Node** head, int d)
{
    Node *tmp = (Node*)malloc(sizeof(Node));
    tmp->data = d;
    tmp->next = (*head);
    (*head) = tmp;
}
void copy(Node** head)
{
    Node *tmp;
    Node *back;
    tmp = (*head);
    back = (*head);
    while (tmp != NULL)
    {
        if (tmp = (*head) && tmp->data % 2 == 0)
        {
            Node *P1 = (Node*)malloc(sizeof(Node));
            P1->data = (*head)->data;
            P1->next = (*head);
            (*head) = P1;
        }
        else if (tmp->data % 2 == 0)
        {
            Node *P1 = (Node*)malloc(sizeof(Node));
            back->next = tmp;
            P1->data = back->next->data;
            P1->next = back->next;
            back->next = P1;
        }
        tmp = tmp->next;
    }
}
int main()
{
    setlocale(LC_ALL, "ukr");
    Node *head = NULL;
    for (int i = 0; i < 3; i++)
    {
        CreateNode(&head, i + 2);
    }
    Node *tmp = head;
    /*copy(&head);
    while (tmp)
    {
        printf("%d\n", tmp->data);
        tmp = tmp->next;
    }
    copy(&head);
    Node *i = head;
    while (i)
    {
        printf("  %d\n", i->data);
        i = i->next;
    }
    getchar();
    return 1;
} 

Ответы (2 шт):

Автор решения: Павел Ериков
  1. if (tmp = (*head) && tmp->data % 2 == 0) У вас опечатка, нужно использовать не знак присваивания, а сравнения ==.

  2. back это же предыдущий элемент относительно tmp, тогда его нужно обновлять также, как и tmp.

    back = tmp
    

    Обязательно перед tmp = tmp->next

И немного можно украсить код)

  1. Во 2-ом if можно написать так:

    Node* P1 = (Node*)malloc(sizeof(Node));
    P1->data = tmp->data;
    P1->next = tmp;
    back->next = P1;
    

    Я думаю тут понятно, что back->next = tmp была лишней и можно обращаться к tmp.

  2. Можно заметить, что есть похожие строчки кода, по этому избавимся от них

    if (tmp->data % 2 == 0) {
        Node* P1 = (Node*)malloc(sizeof(Node));
        P1->data = tmp->data;
        P1->next = tmp;
        if (tmp == (*head))
            (*head) = P1;
        else back->next = P1;
    }
    
→ Ссылка
Автор решения: avp

Если вставлять дубликат не до, а после элемента с четными данными, то программа будет более элегантна
(кстати, в этом случае в функцию копирования можно передавать не указатель на голову списка, а сам голову (указатель на элемент списка)).

void copy(Node* head) 
{
  for (Node *tmp = head; tmp; tmp = tmp->next)
    if (tmp->data % 2 == 0) {
       Node *p = (Node*)malloc(sizeof(Node));
       *p = *tmp; // да, структуры можно копировать, теперь p->next = tmp->next
       tmp->next = p;
       tmp = p;   // это для правильного перехода к следующему элементу
    }
}
→ Ссылка