Loading

数据结构 线性表

尾插法

//实现方式
Node* createListTailInsert() {
    Node* head = (Node*)malloc(sizeof(Node));  // 创建头节点
    head->next = NULL;

    int n, data;
    printf("请输入要插入的节点数: ");
    scanf("%d", &n);

    Node* tail = head;  // 尾指针初始化为头节点

    for (int i = 0; i < n; ++i) {
        printf("请输入第 %d 个节点的数据: ", i + 1);
        scanf("%d", &data);

        // 创建新节点
        Node* newNode = (Node*)malloc(sizeof(Node));
        newNode->data = data;
        newNode->next = NULL;

        // 插入到尾部
        tail->next = newNode;
        tail = newNode;  // 更新尾指针
    }

    return head;
}

假设:
尾指针和闯红灯指挥员

简单理解:

typedef struct Node {
    int data;           // 数据域
    struct Node* next;  // next指针域
} Node;

Node *node1 = (Node*)malloc(sizeof(Node));
Node *node2 = (Node*)malloc(sizeof(Node));
Node *node3 = (Node*)malloc(sizeof(Node));

node1->data = 10;
node2->data = 20;
node3->data = 30;

// 设置next指针
node1->next = node2;
node2->next = node3;
node3->next = NULL;  // 最后一个节点的next指向NULL

这个时候加入了尾指针 tail

tail:是一个辅助指针,用于动态跟踪链表的最后一个节点

想象一下 如果第一个闯红灯后一直被留到最后,而后面闯红灯没有被罚会有多崩溃,所以每次后闯红灯的人都会接替前一个闯红灯的人
此时我们需要tail = newNode时, 将 tail 更新为指向新插入的节点,确保 tail 始终指向链表的最后一个节点。

typedef struct Node {
    int data;           // 数据域
    struct Node* next;  // next指针域
} Node;

// 创建头节点
Node* head = (Node*)malloc(sizeof(Node));
head->data = 0;  // 头节点通常不存储实际数据,这里用0表示
head->next = NULL;

// 添加数据节点
Node* node1 = (Node*)malloc(sizeof(Node));
node1->data = 10;
node1->next = NULL;

Node* node2 = (Node*)malloc(sizeof(Node));
node2->data = 20;
node2->next = NULL;

// 更新链表的连接关系
head->next = node1;
node1->next = node2;

Node* tail = head; // 尾指针初始化为头节点
tail 指向head ,tail 类似于 head 的副本一样,拥有 head->next = NULL; 也就是 tail->next = NULL;

head -> [0] -> NULL
tail ----^

添加第一个数据节点

// 创建第一个数据节点
Node* node1 = (Node*)malloc(sizeof(Node));
node1->data = 10;
node1->next = NULL;

// 更新尾指针
tail->next = node1; // 将当前尾部(即头节点)的next指向新的节点
tail = node1;       // 更新尾指针,使其指向新的最后一个节点

此时 tail(也是head) 指向 node1 节点, tail 接替 node1

head -> [0] -> [10] -> NULL
                    ^
                  tail

添加第二个数据节点

// 创建第二个数据节点
Node* node2 = (Node*)malloc(sizeof(Node));
node2->data = 20;
node2->next = NULL;


tail->next = node2;  // 将当前尾部(即node1)的next指向新的节点
tail = node2;        // 更新尾指针,使其指向新的最后一个节点

此时的 tail 指针(是node1指针) 更新尾指针后 tail 就变成了 node2

head -> [0] -> [10] -> [20] -> NULL
                               ^
                             tail

为什么要更新尾指针?
如果不更新尾指针,尾指针将无法正确指向链表的最后一个节点,导致后续操作出现问题

tail->next = node1;  // 正确地将头节点的next指向node1
// 缺少 tail = node1; 这一步

在这种情况下,链表结构虽然暂时看起来正确:

head -> [0] -> [10] -> NULL
                    ^
                  tail (still points to head)

但是当尝试添加第二个节点时

tail->next = node2;  // 错误!仍然试图通过头节点的next来连接

实际会变成

head -> [0] -> [20] -> NULL
          |
         [10]

这是因为尾指针仍然指向头节点,而不是node1,所以新的节点被错误地插入到了头节点之后,而不是node1之后

参考:
https://bbs.huaweicloud.com/blogs/280936?utm_source=zhihu&utm_medium=bbs-ex&utm_campaign=other&utm_content=content

posted @ 2025-03-21 21:22  androllen  阅读(29)  评论(0)    收藏  举报