数据结构 线性表
尾插法
//实现方式
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之后

浙公网安备 33010602011771号