链表有两种实现方案,一是有头节点,二是无头节点。

重新温习链表_链表

方案一中有头节点,指向头节点的指针叫做头指针,但是头节点只是为了操作统一方便,头节点的数据域为空或者存储链表的长度等信息,只有头节点的链表叫做空链表。

方案二中没有头节点,空链表的意义为头指针指向NULL,

方案一源码

// 此头文件包含链表的基本操作
// 类型:单链表
#include<stdlib.h>
#include<stdio.h>
#include<malloc.h>
typedef int ElemType;
typedef struct linklist
{
 ElemType nodeData;   // 数据区域
 struct linklist *next;  // 指针区域,指向链表的下一个节点
} node;
// 构造一个空的链表
node *InitList()
{
 node *head;
 head=(node *)malloc(sizeof(node));
 head->nodeData=0;    // 头节点中的数据域表示这个链表中的长度
 head->next=NULL;
 return head;
}
// 销毁线性表
int ClearList(node *head)
{
 node *temp;
 while(!head)
 {
  temp=head;
  head=head->next;
  free(temp);
 }
 return 0;
}
// 链表判空,为空返回0,不空返回1
int LinkEmpty(node *head)
{
 return head->next==NULL?0:1;
}
// 返回链表的长度
int ListLength(node *head)
{
 return head->nodeData;
}
// 取回第i个节点的数据
ElemType GetElem(node *head,int i)
{
 node *temp;
 temp=head;
 if(i<0||i>head->nodeData)
 {
  printf("Parameter Error");
  exit(1);
 }
 while(i-->0)
 {
  temp=temp->next;
 }
 return temp->nodeData;
}
// 删除第i个节点
ElemType DeleteElem(node *head,int i)
{
 int ret;
 node *temp;
 temp=head;
 if(i<0||i>head->nodeData)
 {
  printf("Parameter Error");
  exit(1);
 }
 while(i-->0)
 {
  temp=temp->next;
 }
 ret=temp->nodeData;
 free(temp);
 return ret;
}
// 插入数据元素,head是头指针,dat是插入的数据,i是插入位置
ListInsert(node *head,ElemType dat,int i)
{
 node *temp,*TMP;
 TMP=head->next;     // 这个变量用于寻找插入位置的前驱节点
 temp=(node *)malloc(sizeof(node));  // 这是用于插入的节点
 temp->nodeData=dat;
 if(i<0||i>head->nodeData+1)
 {
  printf("Parameter Error");
  exit(1);
 }
 else if(i==1)
 {
  temp->next=head->next;
  head->next=temp;
  head->nodeData++;
 }
 else
 {
  while(--i>1)   // 找到要插入位置的前驱节点
  {
   TMP=TMP->next;
  }
  temp->next=TMP->next;
  TMP->next=temp;
  head->nodeData++;
 }
}
int main()
{
 node *head;
 head=InitList();
 ListInsert(head,3,1);
 printf("%d\n",GetElem(head,1));
}