相信很多刚找工作时的同学,都遇到过面试时被问链表的情景,有些面试官还喜欢直接要你在纸上写。今天,就给大家详细讲解下链表。
链表实现了物理存储上非连续,可以通过当前节点索引下一个节点,最后一个元素为空,在C语言实现上,用指针来索引下一个节点,今天也通过C语言来讲解链表的实现。
在上篇中,我们来实现一个简单版的,假如每个节点存储一个int的值。则一个节点可以这样定义:
typedef struct Node
{
int val;
struct Node *next;
}Node;
这样,一个节点不但保存值信息,还保存下一个节点的信息。
所有节点链接起来,我们称为链表。
头节点
我们把链表中的第一个节点称为头节点,
尾节点 自然把最后一个节点称为尾节点。
在实际的应用中,为了操作的方便,第一个节点经常不用来存储有用信息,而是作为索引方便,尾节点也是。
今天的代码,就假设链表中的第一个节点不存储有用信息,而是为了操作方便,来演示链表的头插法。
先定义一个链表
typedef struct LinkList
{
struct Node head;
struct Node tail;
}LinkList;
为了头插法和尾插的方便,我们在尾部也增加一个辅助节点。
头插法代码
LinkList* LinkListInsertHead(LinkList *mylist, int inval)
{
struct Node *node = (Node*)malloc(sizeof(Node));
node->val = inval;
if (mylist->head.next != &mylist->tail)
{
node->next = mylist->head.next;
mylist->head.next = node;
}
else
{
mylist->head.next = node;
node->next = &mylist->tail;
mylist->tail.next = node;
}
return mylist;
}
尾插法
LinkList* LinkListInsertTail(LinkList *mylist, int inval)
{
if (!mylist)
return NULL;
Node *node = (Node*)malloc(sizeof(Node));
node->val = inval;
Node *tmp = mylist->tail.next;
tmp->next = node;
node->next = &mylist->tail;
mylist->tail.next = node;
return mylist;
}
说明:
尾节点指向的是有效节点中的最后一个,所以初始化的时候,指向的是头节点。
所以,头插法的时候,要判断链表中是否为空,如果为空,尾节点指向的节点就是新插入的节点了,同时头节点也指向的是新插入的节点。
尾插法的时候,就比较简单,找到最后一个节点,让最后一个节点指向新节点,然后尾节点也指向新节点。
代码:
代码地址 https://github.com/jxdeng3264/Blog
【赞赏】