链表中的头指针和头节点



线性表使用顺序(数组)存储时有个弊端,那就是在插入和删除时需要大量的移动数据,这显示是非常消耗时间的,所以可以采用链式存储,即有一个指针域(单链表),来记录下个结点的存储位置(地址),这样在插入和删除结点时只需要修改指针域即可,从而大量减少移动数据所消耗的时间。来看链表的定义:

struct node {
	int data;
	struct node *next;
};

其中有两个元素,data为数据域,用于存储数据,next为指针域,用于存储下个结点的位置(地址)。那么什么是头指针呢?我们把指向第一个结点的指针称为头指针,那么每次访问链表时都可以从这个头指针依次遍历链表中的每个元素,例如:

struct node first;
struct node *head = &first;

这个head指针就是头指针。
这个头指针的意义在于,在访问链表时,总要知道链表存储在什么位置(从何处开始访问),由于链表的特性(next指针),知道了头指针,那么整个链表的元素都能够被访问,也就是说头指针是必须存在的。示例如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. struct node {  
  4.     int data;  
  5.     struct node *next;  
  6. };  
  7.   
  8. int main(void)  
  9. {  
  10.     struct node *head, first, second;  
  11.   
  12.     head = &first;  
  13.     first.data = 1;  
  14.     first.next = &second;  
  15.       
  16.     second.data = 2;  
  17.     second.next = NULL;  
  18.       
  19.     while (head) {  
  20.         printf("%d\n", head->data);  
  21.         head = head->next;  
  22.     }  
  23.     return 0;  
  24. }  
需要着重注意的是while那部分(通过头指针遍历完整个链表)。

那么什么又是头结点呢?很多时候,会在链表的头部附加一个结点,该结点的数据域可以不存储任何信息,这个结点称为头结点,
头结点的指针域指向第一个结点,例如:

struct node head, first;
head.next = &first;
那么这里的头指针又是谁呢,不在是指向第一个结点的指针,而是指向头结点的指针,例如:

struct node *root = &head;

即root指针才是头指针。示例如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. struct node {  
  4.     int data;  
  5.     struct node *next;  
  6. };  
  7.   
  8. int main(void)  
  9. {  
  10.     struct node *root, head, first, second;  
  11.       
  12.     root = &head;  
  13.     root->data = 0;  
  14.     root->next = &first;  
  15.       
  16.     first.data = 1;  
  17.     first.next = &second;  
  18.       
  19.     second.data = 2;  
  20.     second.next = NULL;  
  21.       
  22.     while (root) {  
  23.         printf("%d\n", root->data);  
  24.         root = root->next;  
  25.     }  
  26.       
  27.     return 0;  
  28. }  






链接:http://blog.youkuaiyun.com/mcgrady_tracy/article/details/32130421




### 链表指针指针的功能与作用 #### 指针的作用 在链表的数据结构里,指针用于指向链表的第一个节点。这个节点可以是头结点或者是首元结点,具体取决于链表的设计是否有额外的头结点[^1]。通过指针能够访问到整个链表中的每一个元素,因为每个节点都保存着下一个节点的位置信息。 对于带有头结点的情况,指针实际上是指向了一个不存储实际数据的哨兵节点;而对于没有头结点的情形,则直接指向了第一个含有有效数据的节点。这样的设计简化了许多操作逻辑,比如插入新节点不需要特别处理边界条件。 ```c // 定义链表节点结构体 typedef struct Node { int data; struct Node* next; } Node, *LinkList; // 初始化一个空链表(带头结点) LinkList InitList() { LinkList L = (LinkList)malloc(sizeof(Node)); L->next = NULL; return L; } ``` #### 尾指针的作用 相比之下,尾指针总是指向链表最后一个节点,在某些实现方式下也可以设置成NULL来表示结束标志。拥有尾指针的主要优势在于提高特定场景下的效率: - 当频繁地在链表末端添加新的元素,利用尾指针可以直接定位到最后位置而无需遍历整条链路; - 如果需要快速判断某个列表是否为空,可以通过检测尾指针是否等于指针或为NULL来进行判定。 然而值得注意的是,并不是所有的应用场景都需要维护显式的尾指针变量——这通常会增加内存开销并使得程序更加复杂化。因此只有当确实能带来性能提升的情况下才会考虑引入这一机制。 ```c // 向链表末尾追加节点(假设已知尾指针) void Append(LinkList& tail, int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next = NULL; if (!tail || !tail->next) { // 若当前链表为空或只有一个头结点 tail->next = newNode; tail = newNode; // 更新尾指针至最新加入的节点处 } else { tail->next = newNode; tail = newNode; } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值