导读单向链表,顾名思义,它是单向的。因为单链表的每个结点只有一个数据域和一个指针域,而该指针域只存储了下一个结点的地址,所以我们只能通过某结点找到其直接后继结点,却不能通过某节点找到其直接前驱结点。此外,

单向链表,顾名思义,它是单向的。

因为单链表的每个结点只有一个数据域和一个指针域,而该指针域只存储了下一个结点的地址,所以我们只能通过某结点找到其直接后继结点,却不能通过某节点找到其直接前驱结点。

此外,由于单链表到尾结点(链表的最后一个结点)结束,所以尾结点的指针域是 NULL,以此来表示链表的终止,这就导致我们遍历到尾结点的时候,如果想再次遍历,只能手动回到头结点再开始遍历。

为了弥补单链表的上面两个缺点,下面介绍两种链表,它们都是单链表的变形,如果你理解了单链表,那么会很容易理解这两种变形。

数据结构:图文详解教你花样玩链表

voidinsert_at_head(Node **p_head, intelem){ Node *new= create_node(elem); Node *head_node = *p_head; //头结点//新结点插入头结点之后new->next = head_node->next; head_node->next = new; }

【尾插法】

因为为了尽量简单,所以我们并没有设置指向尾结点的尾指针,所以在尾插之前,需要先借助某个指针,遍历至尾结点,然后再插入。

void insert_at_tail(Node **p_head, int elem) { Node *new= create_node(elem); Node *head_node = *p_head; //头结点Node *tail = head_node; //tail指针指向头结点while(tail->next != head_node) { //tail遍历至链表尾tail = tail->next; } //尾插new->next = tail->next; tail->next = new; }

1.5. 删除操作

删除的本质是“跳过”待删除的结点,所以我们要找到待删除结点的直接前驱结点,然后让其直接前驱结点的 next指针指向其直接后继结点,以此来“跳过”待删除结点,最后保存其数据域,释放结点,即完成删除。

这里只演示头删法。

因为删除的是头结点的直接后继结点,所以我们不必再费力寻找待删除结点的直接前驱结点了。

数据结构:图文详解教你花样玩链表

代码如下:

void insert_at_head(Node **p_head, int elem) { Node *new= create_node(elem); Node *head_node = *p_head; //头结点if(head_node->next != NULL) { //不为空链表Node *first_node = head_node->next; //首结点:头结点的下一个结点//首结点的prev指针指向new结点first_node->prev = new; //new结点的next指针指向首结点new->next = first_node; } //new结点的prev指针指向头结点new->prev = head_node; //头结点的next指针指向new结点head_node->next = new; }

2.5. 删除操作

这里只演示头删法。下图是将一个有两个元素结点的双向链表头删为空链表的过程:

ed9b1066d6354d63befd6445e5a251b3

代码如下:

void delete_from_head(Node **p_head, int *elem) { Node *head_node = *p_head; //头结点Node *first_node = head_node->next; //待删除的首结点:头结点的下一个结点if(head_node->next == NULL) { //判空printf("空链表,无元素可删。n"); return; } *elem = first_node->data; //保存数据if(first_node->next != NULL) { first_node->next->prev = first_node->prev; } first_node->prev->next = first_node->next; free(first_node); }

2.6. 遍历操作

有了 next指针域,我们可以一路向后遍历;有了 prev指针域,我们可以一路向前遍历。

这里不再展示代码了。

3. 总结

了解了单向循环链表和双向链表,就像拿搭积木一样,我们还可以创造出来双向循环链表。这里就不再演示了,读者可以自行尝试。只要你搞懂上面三种链表,这绝非难事。