线性表的链式存储结构
为了表示每个数据元素与其直接后继数据元素之间的逻辑关系,除了存储本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。
我们把存储数据元素信息的位置称为数据域,把存储其直接后继信息的位置称为指针域。这两部分组成数据元素的结点(Node)。
头结点和头指针
-
头结点
头结点是为了操作的统一和方便而设立的,放在第一元素的节点之前,其数据域一般无意义;
有了头结点,对在第一个元素结点前插入和删除第一个结点的操作就与其他结点的操作统一了;
头结点不是链表的必须要有的;
-
头指针
头指针是指指向链表第一个结点的指针,若链表有头结点,则是指向头结点的指针;
无论链表是否为空,头指针均不为空。头指针是链表的必要元素;
链式存储结构
单链表
typedef int DateType;
//链表结点
typedef struct ListNode
{
DateType date;
struct ListNode* next;
}ListNode;
插入操作
尾插
思路:申请一个新节点newnode,判断单链表是否为空,若为空则直接插入*pplist=newnode,若不为空则寻找单链表的表尾(定义一个tail指针遍历链表,若tail->next=NULL则表示tail是单链表的表尾)再将新节点插入。
void ListPushBack(ListNode** pplist, DateType x)
{
//申请空间,创建一个新结点
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
//数据域、指针域赋值
newnode->date = x;
newnode->next = NULL;
//判断链表是否为空
if (*pplist == NULL)
{
*pplist = newnode;//若为空,则直接插入
}
else//若不为空,寻找链表位进行插入操作
{
//定义tail寻找链表尾
ListNode* tail = *pplist;
while (tail->next != NULL)
{
tail = tail->next;
}
//尾部插入新结点
tail->next = newnode;
}
}
头插
思路:创建一个新节点newnode ,让newnode的next指向原来的单链表头ppList