1.什么是链表
链表是一种常见的数据结构。它与常见的数组是不同的,使用数组时先要指定数组包含元素的个数,即为数组的长度,但是如果向这个数组中加入的元素超过了数组的大小时,便不能将内容全部保存。
链表这种存储方式,其元素个数是不受限定的,当进行添加元素的时候存储的个数就会随之改变。
在链表中有一个头指针,这个指针指向链表的第一个结点,每个结点包括两个部分:数据域和指针域,指针域存放下一个结点的地址,最后一个结点的指针域必须为NULL
2.设计链表
2.1 创建结点(结构体)
struct Node
{
int data;
struct Node* next;
};
2.2定义全局链表头尾指针方便调用
struct Node* head = NULL;//头指针
struct Node* end = NULL;//尾指针
2.3创建链表,实现在链表增加结点
法一:头插法
void AddList(int i)//头插法
{
struct Node* tmp = (struct Node*)malloc(sizeof(struct Node));
if (tmp == NULL)
{
return;
}
tmp->data = i; //赋值
tmp->next = NULL;
if (head == NULL)
{
head = tmp;
end = tmp;
}
else
{
tmp->next = head;
head = tmp;
}
}
法二:尾插法
void AddList(int i)//尾插法
{
struct Node* tmp = (struct Node*)malloc(sizeof(struct Node));
if (tmp == NULL)
{
return;
}
tmp->data = i;
tmp->next = NULL;
if (head == NULL)
{
head = tmp;
end = tmp;
}
else
{
end->next = tmp;
end = tmp;
}
}
2.4查询指定的结点
这个直接上代码吧
struct Node* FindListNode(int i)
{
struct Node* tmp = head;
while (tmp != NULL)
{
if (i == tmp->data)
{
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
2.5插入操作
void ListInsert(int i,int number)//在第i个位置之前插入number这个数据
{
if (head == NULL||i<=1||i>MAX)
{
printf("无法插入\n");
return;
}
struct Node* tmp = (struct Node*)malloc(sizeof(struct Node));
if (tmp == NULL)
{
return;
}
tmp->data =number;
struct Node* p = head;
int j = 1;
while (j < i-1)
{
p = p->next;
j++;
}
tmp->next = p->next;
p->next = tmp;
}
2.5删除尾结点
void ListDeleTail()
{
if (head == NULL)//判断是不是空链表
{
printf("空链表\n");
return;
}
if (head == end)//链表只有一个结点
{
free(head);
head = NULL;
end = NULL;
}
else//链表有多个结点
{
struct Node* tmp = head;
while (tmp->next != end)
{
tmp = tmp->next;//找尾结点前一个结点
}
free(end);//释放尾巴
end = tmp;//重新标记尾结点
end->next = NULL;//将尾结点指针域置为空指针
}
}
尾删除的过程首先应判断这个链表是不是为空或者只有一个节点,若只有一个节点则直接置NULL,若不为空,则先通过遍历找到倒数第二个节点,将最后一个节点释放内存,再将倒数第二个节点设置为end,然后将它的指针指向NULL。
2.6删除第一个结点
void ListDeleHead()
{
struct Node* tmp = head;//标记原来头的位置
if (head == NULL)//判断是否为空链表
{
printf("空链表\n");
return;
}
head = head->next;
free(tmp);
tmp = NULL;
}
2.7删除指定的结点
void ListDele(int i)
{
if (head==NULL)//判断是不是空链表
{
printf("空链表\n");
return;
}
struct Node* tmp = FindListNode(i);//查找结点位置
if (tmp == NULL)
{
printf("查无\n");
return;
}
if (head == end)//链表只有一个结点
{
free(head);
head = NULL;
end = NULL;
}
else if (head->next==end)//链表有两个结点
{
if (head == tmp)//判断删头还是尾
{
ListDeleHead();
}
else if (end == tmp)
{
ListDeleTail();
}
}
else
{
if (head == tmp)//判断删头还是尾
{
ListDeleHead();
}
else if (end == tmp)
{
ListDeleTail();
}
else
{
struct Node* p = head;//找要删除的前一个结点
while (p->next != tmp)
{
p = p->next;
}
p->next = tmp->next;
free(tmp);
tmp = NULL;
}
}
}
剩下的函数实现就没什么难的,下面上全部代码
#define _CRT_SECURE_NO_WARNINGS 1
#define MAX 10
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* head = NULL;//头指针
struct Node* end = NULL;//尾指针
//void AddList(int i)//头插法
//{
// struct Node* tmp = (struct Node*)malloc(sizeof(struct Node));
// if (tmp == NULL)
//{
// return;
//}
// tmp->data = i; //赋值
// tmp->next = NULL;
// if (head == NULL)
// {
// head = tmp;
// end = tmp;
// }
// else
// {
// tmp->next = head;
// head = tmp;
// }
//}
void AddList(int i)//尾插法
{
struct Node* tmp = (struct Node*)malloc(sizeof(struct Node));
if (tmp == NULL)
{
return;
}
tmp->data = i;
tmp->next = NULL;
if (head == NULL)
{
head = tmp;
end = tmp;
}
else
{
end->next = tmp;
end = tmp;
}
}
void ListInsert(int i,int number)//在第i个位置之前插入number这个数据
{
if (head == NULL||i<=1||i>MAX)
{
printf("无法插入\n");
return;
}
struct Node* tmp = (struct Node*)malloc(sizeof(struct Node));
if (tmp == NULL)
{
return;
}
tmp->data =number;
struct Node* p = head;
int j = 1;
while (j < i-1)
{
p = p->next;
j++;
}
tmp->next = p->next;
p->next = tmp;
}
struct Node* FindListNode(int i)
{
struct Node* tmp = head;
while (tmp != NULL)
{
if (i == tmp->data)
{
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
void ListDeleHead()
{
struct Node* tmp = head;//标记原来头的位置
if (head == NULL)//判断是否为空链表
{
printf("空链表\n");
return;
}
head = head->next;
free(tmp);
tmp = NULL;
}
void ListDeleTail()
{
if (head == NULL)//判断是不是空链表
{
printf("空链表\n");
return;
}
if (head == end)//链表只有一个结点
{
free(head);
head = NULL;
end = NULL;
}
else//链表有多个结点
{
struct Node* tmp = head;
while (tmp->next != end)
{
tmp = tmp->next;//找尾结点前一个结点
}
free(end);//释放尾巴
end = tmp;//重新标记尾结点
end->next = NULL;//将尾结点指针域置为空指针
}
}
void ListDele(int i)
{
if (head==NULL)//判断是不是空链表
{
printf("空链表\n");
return;
}
struct Node* tmp = FindListNode(i);//查找结点位置
if (tmp == NULL)
{
printf("查无\n");
return;
}
if (head == end)//链表只有一个结点
{
free(head);
head = NULL;
end = NULL;
}
else if (head->next==end)//链表有两个结点
{
if (head == tmp)//判断删头还是尾
{
ListDeleHead();
}
else if (end == tmp)
{
ListDeleTail();
}
}
else
{
if (head == tmp)//判断删头还是尾
{
ListDeleHead();
}
else if (end == tmp)
{
ListDeleTail();
}
else
{
struct Node* p = head;//找要删除的前一个结点
while (p->next != tmp)
{
p = p->next;
}
p->next = tmp->next;
free(tmp);
tmp = NULL;
}
}
}
void ListPrint()
{
struct Node* tmp = head;
while (tmp != NULL)
{
printf("%d\n", tmp->data);
tmp = tmp->next;
}
}
void ListFree()
{
struct Node* tmp = head;
if (head == NULL)
{
printf("链表已空\n");
return;
}
while (tmp != NULL)
{
struct Node* p = tmp;
tmp = tmp->next;
free(p);
p = NULL;
}
head = NULL;
end = NULL;
printf("清空成功\n");
}
int main()
{
int i = 0;
for (i = 0; i < MAX; i++)//创10个结点
{
AddList(i);
}
ListInsert(4,14);//在第4个位置之前插入14这个数据
struct Node* find;
find = FindListNode(4);
if (find != NULL)
{
printf("找到%d\n", find->data);
}
else
{
printf("没找到\n");
}
ListDele(3);//删除第3个结点
ListPrint();//输出链表
ListFree();//删除整个链表
return 0;
}