一(3)理解 newNode->next = head 和 Node* temp = head 的区别
1. 指针变量的本质:存储内存地址
在 C 语言中,指针变量(如 head
、temp
、newNode->next
)的本质是存储内存地址的变量。它们的值是一个“地址编号”(比如 0x1000
、0x2000
),表示它们指向的内存位置。
Node* head = NULL; // head 存储的地址是 NULL(0x0)
Node* temp; // temp 未初始化(存储随机地址)
当执行 Node* temp = head;
时:
temp
被赋值为head
的当前值(即NULL
)。- 此时
temp
和head
存储的地址相同(都是0x0
),但它们是 两个不同的指针变量(内存中占用不同的空间)。
2. 链表节点的结构:数据 + 指针
单链表的每个节点(struct Node
)包含两部分:
- 数据域(
data
):存储实际数据(如int
类型的值)。 - 指针域(
next
):存储 下一个节点的内存地址(类型是Node*
)。
例如,一个节点 A
的结构可能如下:
节点 A 的内存地址:0x1000
节点 A 的 data 域:存储值 10(假设是 int 类型)
节点 A 的 next 域:存储下一个节点 B 的地址 0x2000
此时,head
指针变量存储的地址是 0x1000
(指向节点 A),因此 head
被称为“头指针”(指向链表的第一个节点)。
3. Node* temp = head
的含义:复制头指针的地址
Node* temp = head;
这行代码的作用是:
让临时指针 temp
存储头指针 head
当前的地址值(即 temp
和 head
指向同一个内存位置)。
示例:
假设原链表头指针 head
存储的地址是 0x1000
(指向节点 A):
Node* head = (Node*)0x1000; // head 指向节点 A(地址 0x1000)
Node* temp = head; // temp 存储的地址也是 0x1000(和 head 相同)
此时:
head
和temp
是两个不同的指针变量(内存中占用不同空间)。- 但它们的值相同(都是
0x1000
),因此都指向节点 A。
4. newNode->next = head
的含义:连接新节点到原链表头部
newNode->next = head
这行代码的作用是:
将新节点 newNode
的 next
指针域(存储下一个节点地址的位置)设置为头指针 head
当前的地址值(即让新节点的下一个节点是原链表的头节点)。
示例:
假设我们要插入新节点 X
(地址 0x3000
),原链表头指针 head
存储的地址是 0x1000
(指向节点 A):
Node* newNode = (Node*)0x3000; // 新节点 X 的地址是 0x3000
newNode->data = 20; // X 的数据域存储 20
newNode->next = head; // X 的 next 域设置为 head 的值(0x1000)
此时:
- 新节点
X
的next
域存储的地址是0x1000
(指向原头节点 A)。 - 因此,
X
的下一个节点是A
,链表结构变为:X → A → ...
。
5. 头插法的完整逻辑:移动头指针
头插法的最终目标是将新节点 X
变为链表的新头节点。因此,在 newNode->next = head
之后,需要更新头指针 head
的值为新节点 X
的地址。
示例:
void insertAtHead(int data) {Node* newNode = createNode(data); // 创建新节点 X(地址 0x3000)newNode->next = head; // X 的 next 指向原头节点 A(地址 0x1000)head = newNode; // 头指针更新为 X 的地址(0x3000)
}
执行后:
- 头指针
head
存储的地址变为0x3000
(指向新节点 X)。 - 链表结构变为:
head → X → A → ...
(X 是新的头节点)。
6. 关键总结:指针的“指向”是地址的复制
-
Node* temp = head
:temp
复制了head
的地址值(两者指向同一个节点)。-
newNode->next = head
:newNode
的next
域复制了head
的地址值(新节点的下一个节点是原头节点)。-
head = newNode
:head
复制了newNode
的地址值(头指针指向新节点,新节点成为新头)。
用图示更直观理解
假设原链表结构为:
head(地址 0x4000) → A(地址 0x1000,data=10) → B(地址 0x2000,data=20) → NULL
步骤 1:创建新节点 X
Node* newNode = createNode(30); // X 的地址是 0x3000,next 初始化为 NULL
此时内存结构:
head → 0x4000 → A → 0x1000 → B → 0x2000 → NULL newNode → 0x3000 → next → NULL
步骤 2:执行 newNode->next = head
head
的值是 0x4000
(指向 A),因此 newNode->next
被设置为 0x4000
。
此时内存结构:
newNode → 0x3000 → next → 0x4000(指向 A)
步骤 3:执行 head = newNode
head
被更新为 0x3000
(指向 X)。
最终链表结构:
head → 0x3000 → X(data=30) → next → 0x4000 → A(data=10) → next → 0x2000 → B(data=20) → NULL
总结
-
Node* temp = head
:临时指针temp
复制头指针head
的地址,用于后续操作(如遍历或删除头节点时保留原头节点)。 -
newNode->next = head
*:新节点的next
指针复制头指针head
的地址,使新节点连接到原链表的头部位置。 -
head = newNode
:头指针更新为新节点的地址,使新节点成为链表的新头节点。