对于所有的代码务必自己实现一遍
主要内容:链表的创建,销毁,链表的增删改查,链表的遍历
1、结构体定义:链表节点/链表
typedef struct ListNode{ //创建链表单独结点
int data; //数值域
struct ListNode* next; //下一个结点的指针域
}ListNode;
typedef struct LinkedList { //完整的链表
struct ListNode* head; //头结点,也就是一个单独结点
int len; //长度
}LinkedList;
2、创建一个链表
void Creat_LinkedList(LinkedList* list) //创建一个链表
{
//把头节点置空,长度置为0
list->head = NULL;
list->len = 0;
}
3、销毁一个链表
void Destroy_LinkList(LinkedList* list) //销毁一个链表
{
while (list->head) //当头节点不为空时
{
ListNode* temp = list->head; //用一个临时的结点指向此时的头节点
list->head = list->head->next; //将指针指向头指针的下一个结点
free(temp); //把临时变量释放,也就把此时的结点释放
}
list->len = 0; //链表长度归0;
}
3.1:销毁链表的图解。
4、插入一个节点
//在链表中插入一个元素,在第i个位置插入value值
void Insert_LinkList(LinkedList* list, int i, int value)
{
if (i<0 || i>list->len) //位置越界
{
printf("插入失败");
return;
}
//表明位置合法:1.创建结点->改变指针方向
ListNode* newNode=(ListNode*)malloc(sizeof(ListNode));
newNode->data = value;//把数据赋值给新创建的数值域
if (i == 0) //表明需要在头头节点的位置插入元素(即改变头指针的指向),使用头插法
{
newNode->next = list->head; //新生成的结点,指向链表头
list->head = newNode; //改变链表头作为新生成的结点。
}
else //从链表头开始,执行n-1次循环
{
ListNode* current=list->head; //定义一个迭代器寻找结点
for (int j = 0; j < i - 1; j++)
{
current = current->next;//找到插入结点的前驱结点;
}
newNode->next=current->next;//把新结点的后记变成cur的后继结点
current->next = newNode;//把cur的后继变为新生成的结点。
}
list->len++;
}
4.1:头插法图解:
4.2、else:尾插法图解:
5、删除节点:
//删除结点
void Delete_LinkList(LinkedList* list, int i)
{
if (i < 0 || i >= list->len)
{
printf("删除失败");
return;
}
if (i == 0) //删除链表的头节点
{
ListNode* temp = list->head->next;//把链表的头节点的后续结点进行一个缓存
free(list->head); //释放要删除的结点
list->head = temp; //把头节点指向第下一个结点
}
else //表示删除的不是头节点
{
ListNode* current = list->head; //定义一个迭代器
for (int j = 0; j < i - 1; j++)//找到需要删除节点的前驱节点
{
current = current->next;
}
ListNode* temp = current->next->next;//把要删除的后继节点存储起来
free(current->next);//利用free把要删除的节点给释放掉
current->next=temp;
}
list->len--;//长度减1
}
5.1、删除节点图解(头节点):
5.2:删除节点图解(非头节点)
6、查找元素:(通过链表的元素来查找,返回链表节点)
//通过元素来查找链表结点
ListNode* Find_element_Linked(LinkedList* list, int value)
{
ListNode* current = list->head;//先定义一个迭代器指向头节点
while (current) //当迭代器不为空时,也就是还没有遍历完整个链表
{
if (current->data == value) //找到了目标结点
{
return current;
}
current = current->next;//往下找;
}
return NULL;//表示没有找到
}
7、查找元素:(通过链表的下标来进行查找,返回链表的节点)
//通过下标来寻找链表的结点
ListNode* Find_Index_Linked(LinkedList* list, int i)
{
if (i < 0 || i >= list->len) //越界
{
printf("寻找错误");
return NULL;
}
ListNode* current = list->head;//迭代器
for (int j = 0; j < i; j++) //循环遍历寻找元素
{
current = current->next;//往后移
}
return current;
}
8、更新链表的结点值:
//更新链表的元素
void Update_LInked(LinkedList* list, int i, int value)
{
ListNode* temp = Find_Index_Linked(list, i);//直接调用通过下标来寻找链表节点的函数
if (temp) //如果节点存在
{
temp->data = value;//修改值即可
}
}
9、遍历链表:
void Print_Linked(LinkedList* list)
{
ListNode* current = list->head;//迭代器
while (current)
{
printf("%d ->", current->data);
current=current->next; //往下走
}
printf("NULL\n");
}
10、完整的代码实现:
至此,我们对于链表的功能已全部实现,欢迎大家勘误。下面是完整的代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode{ //创建链表单独结点
int data; //数值域
struct ListNode* next; //下一个结点的指针域
}ListNode;
typedef struct LinkedList { //完整的链表
struct ListNode* head; //头结点,也就是一个单独结点
int len; //长度
}LinkedList;
void Creat_LinkedList(LinkedList* list) //创建一个链表
{
//把头节点置空,长度置为0
list->head = NULL;
list->len = 0;
}
void Destroy_LinkList(LinkedList* list) //销毁一个链表
{
while (list->head) //当头节点不为空时
{
ListNode* temp = list->head; //用一个临时的结点指向此时的头节点
list->head = list->head->next; //将指针指向头指针的下一个结点
free(temp); //把临时变量释放,也就把此时的结点释放
}
list->len = 0; //链表长度归0
}
//在链表中插入一个元素,在第i个位置插入value值
void Insert_LinkList(LinkedList* list, int i, int value)
{
if (i<0 || i>list->len) //位置越界
{
printf("插入失败");
return;
}
//表明位置合法:1.创建结点->改变指针方向
ListNode* newNode=(ListNode*)malloc(sizeof(ListNode));
newNode->data = value;//把数据赋值给新创建的数值域
if (i == 0) //表明需要在头头节点的位置插入元素(即改变头指针的指向),使用头插法
{
newNode->next = list->head; //新生成的结点,指向链表头
list->head = newNode; //改变链表头作为新生成的结点。
}
else //从链表头开始,执行n-1次循环
{
ListNode* current=list->head; //定义一个迭代器寻找结点
for (int j = 0; j < i - 1; j++)
{
current = current->next;//找到插入结点的前驱结点;
}
newNode->next=current->next;//把新结点的后记变成cur的后继结点
current->next = newNode;//把cur的后继变为新生成的结点。
}
list->len++;
}
//删除结点
void Delete_LinkList(LinkedList* list, int i)
{
if (i < 0 || i >= list->len)
{
printf("删除失败");
return;
}
if (i == 0) //删除链表的头节点
{
ListNode* temp = list->head->next;//把链表的头节点的后续结点进行一个缓存
free(list->head); //释放要删除的结点
list->head = temp; //把头节点指向第下一个结点
}
else //表示删除的不是头节点
{
ListNode* current = list->head; //定义一个迭代器
for (int j = 0; j < i - 1; j++)//找到需要删除节点的前驱节点
{
current = current->next;
}
ListNode* temp = current->next->next;//把要删除的后继节点存储起来
free(current->next);//利用free把要删除的节点给释放掉
current->next=temp;
}
list->len--;//长度减1
}
//通过元素来查找链表结点
ListNode* Find_element_Linked(LinkedList* list, int value)
{
ListNode* current = list->head;//先定义一个迭代器指向头节点
while (current) //当迭代器不为空时,也就是还没有遍历完整个链表
{
if (current->data == value) //找到了目标结点
{
return current;
}
current = current->next;//往下找;
}
return NULL;//表示没有找到
}
//通过下标来寻找链表的结点
ListNode* Find_Index_Linked(LinkedList* list, int i)
{
if (i < 0 || i >= list->len) //越界
{
printf("寻找错误");
return NULL;
}
ListNode* current = list->head;//迭代器
for (int j = 0; j < i; j++) //循环遍历寻找元素
{
current = current->next;//往后移
}
return current;
}
//更新链表的元素
void Update_LInked(LinkedList* list, int i, int value)
{
ListNode* temp = Find_Index_Linked(list, i);//直接调用通过下标来寻找链表节点的函数
if (temp) //如果节点存在
{
temp->data = value;//修改值即可
}
}
void Print_Linked(LinkedList* list)
{
ListNode* current = list->head;//迭代器
while (current)
{
printf("%d ->", current->data);
current=current->next; //往下走
}
printf("NULL\n");
}
int main()
{
LinkedList list;//定义一个链表
Creat_LinkedList(&list);//初始化链表
Insert_LinkList(&list, 0, 10);//插入值
Insert_LinkList(&list, 1, 20);
Insert_LinkList(&list, 2, 30);
Insert_LinkList(&list, 3, 40);
printf("Original List:");//检验打印
Print_Linked(&list);
Delete_LinkList(&list, 2);
Update_LInked(&list, 1, 100);
printf("Change1 List:");
Print_Linked(&list);
ListNode* found = Find_element_Linked(&list, 30);
if (!found)
{
printf("此节点不存在\n");
}
system("pause");
return 0;
}