链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存放到下一个节点的指针(Pointer)。使用链表结构可以克服数组需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
链表有很多种不同的类型:单向链表,双向链表以及循环链表。
本章主要讲解单向链表
1、插入
其实现的过程考虑边界情况:
1)当L为空;
2)在链表的头部插入;
3)在链表的中间插入(包括在链表尾部插入的情况)。
2、删除
删除和插入是一个相反的过程,一般需要先找到删除结点的前驱(prev)。
1)当L为空;
2)删除链表的首结点;
3)删除链表的中间结点(包括删除链表尾结点的情况)。
链表形态
操作过程
// sll.h
#ifndef _MY_SSL_H
#define _MY_SSL_H
/* singly linked list */
typedef struct singly_linked_list_node {
struct singly_linked_list_node *next;
} SSL_NODE;
typedef struct singly_linked_list {
SSL_NODE *first;
SSL_NODE *last;
} SSL_LIST;
void list_init(SSL_LIST *list);
void list_insert_head(SSL_LIST *list, SSL_NODE *node);
void list_insert_tail(SSL_LIST *list, SSL_NODE *node);
void list_insert_after(SSL_LIST *list, SSL_NODE *pos, SSL_NODE *node);
void list_delete_head(SSL_LIST *list);
void list_delete(SSL_LIST *list, SSL_NODE *node);
int list_get_num(SSL_LIST *list);
#endif
// sll.c
#include <stdlib.h>
#include "sll.h"
void list_init(SSL_LIST *list)
{
list->first = NULL;
list->last = NULL;
}
void list_insert_head(SSL_LIST *list, SSL_NODE *node)
{
if (node == NULL) {
return;
}
node->next = list->first;
list->first = node;
if (list->last == NULL) {
list->last = node;
}
}
void list_insert_tail(SSL_LIST *list, SSL_NODE *node)
{
if (node == NULL) {
return;
}
if (list->last != NULL) {
list->last->next = node;
} else {
list->first = node;
}
list->last = node;
}
void list_insert_after(SSL_LIST *list, SSL_NODE *prev, SSL_NODE *node)
{
if (prev == NULL || node == NULL) {
return;
}
node->next = prev->next;
prev->next = node;
if (list->last == prev) {
list->last = node;
}
}
void list_delete_head(SSL_LIST *list)
{
SSL_NODE *head = list->first;
if (list->first != NULL) {
list->first = head->next;
head->next = NULL;
if (list->first == NULL) {
list->last = NULL;
}
}
}
SSL_NODE *list_find_prev(SSL_LIST *list, SSL_NODE *node)
{
SSL_NODE *iter = NULL;
/* 前驱不存在 */
if ((list->first == NULL) || (list->first == node)) {
return NULL;
}
iter = list->first; /* iter不为NULL */
while (iter->next != NULL) {
if (iter->next == node) {
break;
}
iter = iter->next;
}
return iter;
}
void list_delete(SSL_LIST *list, SSL_NODE *node)
{
SSL_NODE *prev = NULL;
if (node == NULL) {
return NULL;
}
prev = list_find_prev(list, node);
if (prev == NULL) {
if (list->first == node) { /* first node */
list->first = node->next;
node->next = NULL;
}
} else {
prev->next = node->next;
node->next = NULL;
}
if (list->last == node) { /* last node */
list->last = prev;
}
}
void list_delete2(SSL_LIST *list, SSL_NODE *node)
{
SSL_NODE *prev = NULL;
if ((list->first == NULL) || (node == NULL)) {
return NULL;
}
if (list->first == node) { /* first node */
list->first = node->next;
node->next = NULL;
if (list->last == node) { /* last node */
list->last = NULL;
}
} else {
prev = list->first;
while (prev->next != NULL) {
if (prev->next == node) {
prev->next = node->next;
node->next = NULL;
if (list->last == node) {
list->last = prev;
}
break;
}
prev = prev->next;
}
}
}
int list_get_num(SSL_LIST *list)
{
int num = 0;
SSL_NODE *iter = list->first;
while (iter != NULL) {
num++;
iter = iter->next;
}
return num;
}
#pragma once
#ifndef _MY_SSL2_H
#define _MY_SSL2_H
/* singly linked list */
typedef struct sll_node {
struct sll_node *next;
} SLL_NODE;
#define SLL_LIST SLL_NODE
void list_init(SLL_LIST *list);
void list_insert_head(SLL_LIST *list, SLL_NODE *node);
void list_insert_after(SLL_LIST *list, SLL_NODE *prev, SLL_NODE *node);
void list_delete_head(SLL_LIST *list);
void list_delete(SLL_LIST *list, SLL_NODE *node);
void list_delete2(SLL_LIST *list, SLL_NODE *node);
int list_get_num(SLL_LIST *list);
#endif
#if 1
#include <stdlib.h>
#include "sll4.h"
#if 0
/* singly linked list */
typedef struct sll_node {
struct sll_node *next;
} SLL_LIST;
#define SLL_LIST SLL_NODE
#endif
/*
参数:SLL_LIST *list
返回值:void
作用:初始化链表
*/
void list_init(SLL_LIST *list)
{
if (list == NULL) {
return;
}
list->next = NULL;
}
/*
参数:SLL_LIST *list, SLL_NODE *node
返回值:SLL_NODE *
作用:找到node节点的前驱
*/
SLL_NODE *list_find_prev(SLL_LIST *list, SLL_NODE *node)
{
SLL_NODE *prev = NULL;
if ((list == NULL) || (node == NULL)) {
return NULL;
}
prev = list;
while (prev->next != NULL) {
if (prev->next == node) {
break;
}
prev = prev->next;
}
return prev;
}
/*
参数:SLL_LIST *list, SLL_NODE *node
返回值:void
作用:在链表头部插入node节点
*/
void list_insert_head(SLL_LIST *list, SLL_NODE *node)
{
if ((list == NULL) || (node == NULL)) {
return;
}
node->next = list->next;
list->next = node;
}
/*
参数:SLL_LIST *list, SLL_NODE *pos, SLL_NODE *node
返回值:void
作用:在pos节点后面插入node节点
*/
void list_insert_after(SLL_LIST *list, SLL_NODE *prev, SLL_NODE *node)
{
if ((pos == NULL) || (node == NULL)) {
return;
}
node->next = prev->next;
prev->next = node;
}
/*
参数:SLL_LIST *list
返回值:void
作用:删除链表头节点
*/
void list_delete_head(SLL_LIST *list)
{
SLL_NODE *head = NULL;
if (list == NULL) {
return;
}
head = list->next;
if (head != NULL) {
list->next = head->next;
head->next = NULL;
}
}
/*
参数:SLL_LIST *list, SLL_NODE *node
返回值:void
作用:删除node节点
*/
void list_delete(SLL_LIST *list, SLL_NODE *node)
{
SLL_NODE *prev = NULL;
if ((list == NULL) || (node == NULL)) {
return ;
}
prev = list;
while (prev->next != NULL) {
if (prev->next == node) {
prev->next = node->next;
node->next = NULL;
break;
}
prev = prev->next;
}
}
/*
参数:SLL_LIST *list, SLL_NODE *node
返回值:void
作用:删除node节点
*/
void list_delete2(SLL_LIST *list, SLL_NODE *node)
{
SLL_NODE *prev = NULL;
if ((list == NULL) || (node == NULL)) {
return ;
}
prev = list_find_prev(list, node);
if (prev != NULL) {
prev->next = node->next;
node->next = NULL;
}
}
/*
参数:SLL_LIST *list
返回值:void
作用:初始化链表
*/
int list_get_num(SLL_LIST *list)
{
int num = 0;
SLL_NODE *iter = NULL;
if (list == NULL) {
return 0;
}
iter = list->next;
while (iter != NULL) {
num++;
iter = iter->next;
}
return num;
}
#endif
#if 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sll4.h"
typedef struct life {
SLL_NODE node;
int work;
int study;
int play;
} LIFE;
typedef struct all_life {
SLL_LIST list;
} ALL_LIFE;
void slist_print(ALL_LIFE *all_life)
{
SLL_NODE *iter = all_life->list.next;
LIFE *pLIFE = NULL;
int index = 0;
while (iter != NULL) {
pLIFE = (LIFE *)iter;
printf("%2d: work: %d, study: %d, play: %d\n",
++index, pLIFE->work, pLIFE->study, pLIFE->play);
iter = iter->next;
}
printf("\n");
}
int main()
{
int i = 0;
int arr[] = { 123, 4, 3, 34, 35, 7, 8, 9, 5, 4, 2, 1 };
int len = sizeof(arr) / sizeof(arr[0]);
struct all_life real_life = { 0 };
struct life *my_life = NULL;
for (i = 0; i < len; i++) {
my_life = (struct life *)malloc(sizeof(struct life));
if (my_life == NULL) {
printf("malloc error!\n");
return 1;
}
my_life->node.next = NULL;
my_life->work = arr[i];
my_life->study = arr[i] + 1;
my_life->play = arr[i] + 2;
list_insert_head(&(real_life.list), &(my_life->node));
}
slist_print(&real_life);
for (i = 0; i < len; i++) {
my_life = (LIFE *)GET_LIST_HEAD(real_life.list);
list_delete2(&(real_life.list), &(my_life->node));
free(my_life);
my_life = NULL;
slist_print(&real_life);
}
getchar();
return 0;
}
#endif
使用二级指针进行链表的删除操作,将各种情况归一化,可以简化代码,但理解起来有难度。(保存next的地址)
#ifndef _MY_LIST3_H
#define _MY_LIST3_H
typedef struct notify_node {
struct notify_node *next;
int key;
} NOTIFY_NODE;
typedef struct notify_list {
struct notify_node *head;
} NOTIFY_LIST;
void ListInsert(NOTIFY_LIST *list, NOTIFY_NODE *node);
void ListDelete(NOTIFY_LIST *list, NOTIFY_NODE *node);
NOTIFY_NODE *ListFindNode(NOTIFY_LIST *list, int key);
void ListMerge(NOTIFY_LIST *list1, NOTIFY_LIST *list2, NOTIFY_LIST *list);
#endif
#include <stdlib.h>
#include "sll3.h"
/*
参数:NOTIFY_LIST *list, NOTIFY_NODE *node
返回值:void
作用:插入node节点
*/
void ListInsert(NOTIFY_LIST *list, NOTIFY_NODE *node)
{
NOTIFY_NODE **iter = NULL;
if (list == NULL || node == NULL) {
return;
}
iter = &(list->head);
while ((*iter) != NULL) {
if ((*iter)->key > node->key) {
break;
}
iter = &((*iter)->next);
}
node->next = (*iter);
(*iter) = node;
}
/*
参数:NOTIFY_LIST *list, NOTIFY_NODE *node
返回值:void
作用:删除node节点
*/
void ListDelete(NOTIFY_LIST *list, NOTIFY_NODE *node)
{
NOTIFY_NODE **iter = NULL;
if (list == NULL || node == NULL) {
return;
}
iter = &(list->head);
while ((*iter) != NULL) {
if ((*iter) == node) {
(*iter) = node->next;
node->next = NULL;
break;
}
iter = &((*iter)->next);
}
}
/*
参数:NOTIFY_LIST *list, int key
返回值:NOTIFY_NODE *
作用:通过key查找节点
*/
NOTIFY_NODE *ListFindNode(NOTIFY_LIST *list, int key)
{
NOTIFY_NODE *iter = list->head;
while (iter != NULL) {
if (iter->key == key) {
break;
}
iter = iter->next;
}
return iter;
}
/*
参数:NOTIFY_LIST *list1, NOTIFY_LIST *list2, NOTIFY_LIST *list
返回值:void
作用:合并链表
*/
void ListMerge(NOTIFY_LIST *list1, NOTIFY_LIST *list2, NOTIFY_LIST *list)
{
NOTIFY_NODE **iter = &(list->head);
NOTIFY_NODE *iter1 = list1->head;
NOTIFY_NODE *iter2 = list2->head;
while (iter1 != NULL && iter2 != NULL) {
if (iter1->key < iter2->key) {
(*iter) = iter1;
iter1 = iter1->next;
} else {
(*iter) = iter2;
iter2 = iter2->next;
}
iter = &((*iter)->next);
}
if (iter1 != NULL) {
(*iter) = iter1;
}
if (iter2 != NULL) {
(*iter) = iter2;
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sll3.h"
typedef struct life {
NOTIFY_NODE node;
int work;
int study;
int play;
} LIFT;
typedef struct all_life {
NOTIFY_LIST list;
} ALL_LIFT;
void slist_print(ALL_LIFT *list)
{
NOTIFY_NODE *iter = list->list.head;
LIFT *plift = NULL;
int index = 0;
while (iter != NULL) {
plift = (LIFT *)iter;
printf("%2d: work: %d, study: %d, play: %d\n",
++index, plift->work, plift->study, plift->play);
iter = iter->next;
}
printf("\n");
}
LIFT *slist_find(ALL_LIFT *list, int key)
{
NOTIFY_NODE *iter = NULL;
iter = ListFindNode(&(list->list), key);
return (LIFT *)iter;
}
int main()
{
int i = 0;
int arr[] = { 123, 4, 3, 34, 35, 7, 8, 9, 5, 4, 2, 1 };
int len = sizeof(arr) / sizeof(arr[0]);
struct all_life real_life = { 0 };
struct life *my_life = NULL;
for (i = 0; i < len; i++) {
my_life = (struct life *)malloc(sizeof(struct life));
if (my_life == NULL) {
printf("malloc error!\n");
return 1;
}
my_life->node.key = arr[i];
my_life->node.next = NULL;
my_life->work = arr[i];
my_life->study = arr[i] + 1;
my_life->play = arr[i] + 2;
ListInsert(&(real_life.list), &(my_life->node));
}
slist_print(&real_life);
for (i = 0; i < len; i++) {
my_life = slist_find(&real_life, arr[i]);
ListDelete(&(real_life.list), &(my_life->node));
free(my_life);
my_life = NULL;
slist_print(&real_life);
}
getchar();
return 0;
}