链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行了。之后的每一个结点,其实就是上一个的后继指针指向的位置。
这里有个地方要注意,就是对头指针概念的理解,这个很重要。“链表中第一个结点的存储位置叫做头指针”,如果链表有头结点,那么头指针就是指向头结点数据域的指针。画一个图吧。

头指针就是链表的名字。头指针仅仅是个指针而已。

//这里插入关于链表中有无头节点进行初始化链表知识
//首先明白头指针与头结点的关系:http://www.nowamagic.net/librarys/veda/detail/1805
//定义结点的结构体
//typedef struct LNode{
// int data;
// struct LNode *next;
//}LNode,*LinkList;//则定义LinkList L;时,L为链表的头指针。
//
//L=(LinkList) malloc (sizeof(LNode)); //创建一个结点,此处返回给L的是一个指针,并且赋给了头指针。
//L->next=null; //这里说明我创建了一个头结点,即同时运用了头指针和头结点。
//这么方便只要加上->next就说明创建了头节点。不过你想想头指针是没有next的,只有头结点才有,所以就不难理解了
//带头结点初始化
//Node *head; //声明头结点
//首先第一眼看到(*head)->next=NULL;和我们刚才所说是不是一样,只要头指针一旦运用了next操作就自动创建了头结点
//但是我们今天的重点不在于这个,更多在于Node **head,对于两个指针的操作理解
//第一个指针*head,表明了head这个指针变量存储的是另外一个指向结构体NODE的指针,第二个指针,即*head作为一个整体
//其结果是一个指针,其指向的内容就是结构体NODE。经过这么一理解,对于头指针,头结点,首元节点的关系就非常明朗了
// void InitList(Node **head){
// *head=(Node *)malloc( sizeof(Node));//这里需要明确的第一点,申请内存返回的都是地址
// //第二点就是(Node *)表明了其返回的指针指向最后的结果是NODE的结构体,如果是指向int,那么我们就写(int *)
// (*head)->next=NULL;
//}
//带头结点尾方便了首元节点和其他节点一样,统一了操作
//方式一:
// void CreatList(Node **head){
// Node *r=*head,*s;//因为前面已经对头结点,头指针初始化过了,因此可以直接使用*head
// int a;
// while(scanf("%d",&a)){
// if(a!=0){
// s=(Node *)malloc(sizeof(Node));
// s->value=a;
// r->next=s;//这里没有着急设置s->next,原因在于后续还要插入数据。因此将s赋值给r
// r=s;
// }
// else{
// r->next=NULL;//如果后续输入的数据为空,则就将其设置为null
// break;
// }
// }
//}
//调用CreatList(&head);//这句话表明了形参Node **head,只有第一个*才是起作用了,第个*号是和head联系在一起,作为整体使用的
//方式二:
// void CreatList(Node *head){
// Node *r=head,*s;
// ... //下面的都一样
//}
//调用CreatList(head);
//
//不带头结点初始化
//方式一:
//void InitList(Node **head){
// *head=NULL;//这里直接就是指向的首元节点,还有之前自己一个误解,看到head就觉得它就是头指针了,其实它就是随便一个指针变量
//并不是像自己之前想的那样的
//从这里才发现,真正有无头节点的区别。
//*head=(Node *)malloc( sizeof(Node));//这里需要明确的第一点,申请内存返回的都是地址
//第二点就是(Node *)表明了其返回的指针指向最后的结果是NODE的结构体,如果是指向int,那么我们就写(int *)
//(*head)->next=NULL;
//}
//调用InitList(&head);
//
//方式二:
//void InitList(Node *head){
// head=NULL;
//}
//调用InitList(head);
//不带头结点尾插入,第一个节点与其他节点分开操作
//void CreatList(Node **head){
// Node *p,*t; /*p工作指针,t临时指针*/
// int a,i=1;
// while(scanf("%d",&a)){
// if(a!=0){
// t=(Node *)malloc(sizeof(Node));
// t->value=a;
// if(i==1){
// *head=t;
// }
// else{
// p->next=t;
// }
// p=t;
// }
// else{
// p->next=NULL;
// break;
// }
// i++;
// }
//}
//调用CreatList(&head);
//其实从上面就可以知道,其实有头结点对于我们来说是一种更加明智更加方便的操作
原文:https://www.cnblogs.com/shujuxiong/p/10926844.html