链表类型我分为四种来讲:单链表,单循环链表,双链表,双循环链表。
单链表
定义介绍
单链表是由一系列节点(Node)组成的线性集合,每个节点包含两部分:
- 数据域(Node->data):存储实际的数据。
- 指针域(Node->next):存储下一个节点的地址。
链表中的最后一个节点指向 null (NULL)表示链表的结束。
为了使我们使用链表时更加方便,我个人喜欢定义一个头节点,在这个头节点里,第一个data的值是链表中数据储存的个数,地址指向我们储存的第一个结点的数据。
链表是环环相扣的,你要一个一个访问,只有访问到前一个链表才可以拿到“钥匙”(也就是下一个链表Node->data的地址)。理论上链表可以不断一个套下一个,可以无限长。
链表的本质
链表的本质是构建结构体,在这个结构体中含两种变量,一种是指针,一种是我们储存的数据
拿到链表题,我们要做的第一件事就是定义一个名为Node的结构体。
typedef struct Node
{
int data;
struct Node* next;
}Node;
这个结构体Node->data是我们储存数据,Node->next是下一个结点的地址。
创建单链表
Node* initlist()
{
Node* list = (Node*)malloc(sizeof(Node));
list -> data = 0;
list -> next = NULL;
return list;
}
这个代码首先定义一个类型为结构体Node的指针变量list,是list的结构特性能担当起链表的作用,我们首先要给他使用malloc函数动态分配一个Node类型大小的内存空间,并将其地址转换为Node*类型,赋值给指针变量list。
我们最初创建的结点什么都没有,所有我们要给其赋值,先给数据域赋值
list -> data = 0;
再给指针域赋值,由于我们是初始化一个链表,这是它的第一个结点,后面没有结点让他指向,所有它指向为空
list -> next = NULL;
最后返回指向初始化后的头节点的指针
return list;
头插法
void headInsert(Node* list,int data)
{
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = list -> next;
list -> next = node;
list -> data++;
}
尾插法
void tailInsert(Node* list, int data)
{
Node* head = list;
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = NULL;
list = list -> next;
while(list->next)
{
list = list -> next;
}
list -> next = node;
head -> data++;
}
删除数据
void delete(Node* list,int data)
{
Node* pre = list;
Node* current = list -> next;
while(current)
{
if(current -> data == data)
{
pre -> next = current -> next;
free(current);
break;
}
pre = current;
current = current -> next;
}
list -> data--;
}
遍历打印每一个结点
void printList(Node* list)
{
list = list -> next;
while(list -> next)
{
printf("%d ",list -> data);
list = list -> next;
}
printf("\n");
}
测试案例
int main()
{
Node* list = initlist();
headInsert(list, 1);
headInsert(list, 2);
headInsert(list, 3);
headInsert(list, 4);
headInsert(list, 5);
tailInsert(list, 6);
tailInsert(list, 7);
tailInsert(list, 8);
tailInsert(list, 9);
tailInsert(list, 10);
printList(list);
delete(list, 4);
printList(list);
}
运行截图
单循环链表
定义结构体
typedef struct Node
{
int data;
struct Node* next;
}Node;
创建链表
Node* initList()
{
Node* L = (Node*)malloc(sizeof(Node));
L -> data = 0;
L -> next = L;
return L;
}
头插法
void headInsert(Node* L, int data)
{
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
node -> next = L -> next;
L -> next = node;
L -> data ++;
}
尾插法
void tailInsert(Node* L, int data)
{
Node* n = L;
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
while(n -> next != L)
{
n = n -> next;
}
node -> next = L;
n -> next = node;
L = n;
}
删除数据
int delete(Node* L, int data)
{
Node* preNode = L;
Node* node = L -> next;
while(node != L)
{
if(node -> data == data)
{
preNode -> next = node -> next;
free(node);
return 1;
}
preNode = node;
node = node -> next;
}
return 0;
}
遍历打印每一个结点
void printList(Node* L)
{
Node* node = L -> next;
while(node != L)
{
printf("%d->",node -> data);
node = node -> next;
}
printf("NULL\n");
}
测试案例
int main()
{
Node* L = initList();
headInsert(L, 1);
headInsert(L, 2);
headInsert(L, 3);
headInsert(L, 4);
headInsert(L, 5);
printList(L);
tailInsert(L, 6);
tailInsert(L, 7);
tailInsert(L, 8);
tailInsert(L, 9);
printList(L);
delete(L, 3);
printList(L);
}
运行截图
双链表
定义结构体
typedef struct Node
{
int data;
struct Node* pre;
struct Node* next;
}Node;
创建链表
Node* initList()
{
Node* L = (Node*)malloc(sizeof(Node));
L -> data = 0;
L -> pre = NULL;
L -> next = NULL;
return L;
}
头插法
void headInsert(Node* L, int data)
{
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
if(L -> data == 0)
{
node -> next = NULL;
node -> pre = L;
L -> next = node;
L -> data++;
}
else
{
node -> pre = L;
node -> next = L -> next;
L -> next -> pre = node;
L -> next = node;
L -> data++;
}
}
尾插法
void tailInsert(Node* L, int data)
{
Node* node = L;
Node* n = (Node*)malloc(sizeof(Node));
n -> data = data;
n -> next = NULL;
while(node -> next)
{
node = node -> next;
}
node -> next = n;
n -> pre = node;
L -> data++;
}
删除数据
int delete(Node* L, int data)
{
Node* node = L -> next;
while(node)
{
if(node -> data == data)
{
node -> pre -> next = node -> next;
node -> next -> pre = node -> pre;
free(node);
return 1;
}
node = node -> next;
}
return 0;
}
遍历打印各节点
void printList(Node* L)
{
Node* node = L -> next;
while(node)
{
printf("%d -> ",node -> data);
node = node -> next;
}
printf("NULL\n");
}
测试代码
int main()
{
Node* L =initList(L);
headInsert(L, 1);
headInsert(L, 2);
headInsert(L, 3);
headInsert(L, 4);
tailInsert(L, 5);
tailInsert(L, 6);
printList(L);
delete(L, 3);
printList(L);
}
运行截图
双循环链表
定义结构体
typedef struct Node
{
int data;
struct Node* pre;
struct Node* next;
}Node;
创建链表
Node* initList()
{
Node* L = (Node*)malloc(sizeof(Node));
L -> data = 0;
L -> pre = L;
L -> next = L;
return L;
}
头插法
void headInsert(Node* L, int data)
{
Node* node = (Node*)malloc(sizeof(Node));
node -> data = data;
if(L -> data == 0)
{
node -> pre = L;
node -> next = L;
L -> next = node;
L -> pre = node;
L -> data++;
}
else
{
node -> next = L -> next;
node -> pre = L;
L -> next -> pre = node;
L -> next = node;
L -> data++;
}
}
尾插法
void tailInsert(Node* L, int data)
{
Node* node = L;
while(node -> next != L)
{
node = node -> next;
}
Node* n = (Node*)malloc(sizeof(Node));
n -> data = data;
n -> pre = node;
n -> next = L;
node -> next = n;
L -> pre = n;
L -> data++;
}
删除数据
int delect(Node* L, int data)
{
Node* node = L -> next;
while(node != L)
{
if(node -> data == data)
{
node -> pre -> next = node -> next;
node -> next -> pre = node -> pre;
free(node);
L -> data--;
return 1;
}
node = node -> next;
}
return 0;
}
遍历打印各节点
void printList(Node* L)
{
Node* node = L -> next;
while(node != L)
{
printf("%d ",node -> data);
node = node -> next;
}
printf("NULL\n");
}
测试案例
int main()
{
Node* L = initList(L);
headInsert(L, 1);
headInsert(L, 2);
headInsert(L, 3);
printList(L);
tailInsert(L, 4);
tailInsert(L, 5);
tailInsert(L, 6);
tailInsert(L, 7);
printList(L);
delect(L, 3);
printList(L);
}