学习链表的基本使用,初始化,遍历,插入,删除,清空,销毁。
链表基本使用:
带头节点链表 好处在于,头节点永远都是固定的
初始化链表 struct LinkNode* pHeader = init_LinkList();
遍历链表 void foreach_LinkList(struct LinkNode * pHeader);
插入链表 void insert_LinkList(struct LinkNode *pHeader, int oldval, int newval);
Insert_LinkList(pHeader, 10, 100); //在old前插入 newVal,如果没有oldVal,就进行尾插
删除链表 void delete_LinkList(struct LinkNode *pHeader, int val);
用户提供的有效数据 删除掉
无效数据 直接return
清空链表void clear_LinkList(struct LinkNode* pHeader);将所有数据的节点释放掉
销毁链表void destroy_LinkList(struct LinkNode* pHeader);将整个链表都释放掉
链表反转 通过3个辅助指针变量实现链表的反转
统计链表长度, int size_LinkList(struct LinkNode* pHeader);
linkList.h头文件:
#pragma once
#define _CRT_SECURE_NO_WARNINGS //vs不建议使用传统库函数,如果不用这个宏,会出现一个错误,编号:C4996
#include <stdio.h> //std标准 i input 输入 o output 输出
#include <string.h> //strcpy strcmp strcat strstr 字符串相关处理
#include <stdlib.h> //malloc free 标准库文件
//节点声明
struct LinkNode
{
int num;
struct LinkNode* next;
};
//初始化链表
struct LinkNode* init_LinkList();
//遍历链表
void foreach_LinkList(struct LinkNode* pHeader);
//插入链表
void insert_LinkList(struct LinkNode* pHeader, int oldval, int newval);
//删除链表
void delete_LinkList(struct LinkNode* pHeader, int val);
//清空链表
void clear_LinkList(struct LinkNode* pHeader);
//销毁链表
void destroy_LinkList(struct LinkNode* pHeader);
//反转链表
void reverse_LinkList(struct LinkNode* pHeader);
//返回链表长度
int size_LinkList(struct LinkNode* pHeader);
linkList.c源文件:
#include "linkList.h"
//初始化链表
struct LinkNode* init_LinkList()
{
struct LinkNode* pHeader = malloc(sizeof(struct LinkNode));
if (pHeader == NULL)
{
return NULL;
}
pHeader->num = -1; //头节点不维护数据域
pHeader->next = NULL; //头节点初始化指针域为NULL
//创建一个尾节点,利于后期添加数据
struct LinkNode* pTail = pHeader;
int val = -1;
while (1)
{
printf("请输入数据 -1代表输入结束:\n");
scanf("%d", &val);
if (val == -1)
{
break;
}
//创建新节点
struct LinkNode* newNode = malloc(sizeof(struct LinkNode));
newNode->num = val;
newNode->next = NULL;
//建立关系
pTail->next = newNode;
//更新新的尾节点
pTail = newNode;
}
return pHeader;
}
//遍历链表
void foreach_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return;
}
//pCurrent 起始指向的是第一个有真实数据的节点
struct LinkNode* pCurrent = pHeader->next;
while (pCurrent != NULL)
{
printf("%d\n", pCurrent->num);
pCurrent = pCurrent->next;
}
}
//插入链表
void insert_LinkList(struct LinkNode* pHeader, int oldval, int newval)
{
if (pHeader == NULL)
{
return;
}
//创建两个辅助指针变量
struct LinkNode * pPrev = pHeader;
struct LinkNode* pCurrent = pHeader->next;
while (pCurrent != NULL)
{
if (pCurrent->num == oldval) //找到插入位置
{
break;
}
//如果没有找到位置让辅助指针后移
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
//创建新节点
struct LinkNode * newNode = malloc(sizeof(struct LinkNode));
newNode->num = newval;
newNode->next = NULL;
//建立关系 更新指针的指向
newNode->next = pCurrent;
pPrev->next = newNode;
}
//删除链表
void delete_LinkList(struct LinkNode* pHeader, int val)
{
if (pHeader == NULL)
{
return;
}
struct LinkNode* pPrev = pHeader;
struct LinkNode* pCurrent = pHeader->next;
while (pCurrent != NULL)
{
if (pCurrent->num == val)
{
break;
}
pPrev = pCurrent;
pCurrent = pCurrent->next;
}
//无效数据 就直接return
if (pCurrent == NULL)
{
return;
}
//更改指针的指向
pPrev->next = pCurrent->next;
free(pCurrent);
pCurrent = NULL;
}
//清空链表
void clear_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return;
}
//创建临时指针
struct LinkNode* pCurrent = pHeader->next;
while (pCurrent != NULL)
{
//先保存住待删除节点的后面的节点
struct LinkNode* nextNode = pCurrent->next;
free(pCurrent);
pCurrent = nextNode;
}
pHeader->next = NULL;
}
//销毁链表
void destroy_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return;
}
//先清空链表
clear_LinkList(pHeader);
//再释放头节点
free(pHeader);
pHeader = NULL;
}
//反转链表
void reverse_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return;
}
struct LinkNode* pPrve = NULL;
struct LinkNode* pCurrent = pHeader->next;
struct LinkNode* pNext = NULL;
while (pCurrent != NULL)
{
pNext = pCurrent->next;
pCurrent->next = pPrve;
pPrve = pCurrent;
pCurrent = pNext;
}
pHeader->next = pPrve;
}
//返回链表长度
int size_LinkList(struct LinkNode* pHeader)
{
if (pHeader == NULL)
{
return -1;
}
struct LinkNode* pCurrent = pHeader->next;
int num = 0;
while (pCurrent != NULL)
{
num++;
pCurrent = pCurrent->next;
}
return num;
}
测试文件:
#include <stdlib.h>
#include "linkList.h"
void test01()
{
struct LinkNode* pHeader = init_LinkList();
//遍历链表
printf("遍历链表的结果为:\n");
foreach_LinkList(pHeader);
//插入数据
//100 10 200 20 30 300
insert_LinkList(pHeader, 10, 100);
insert_LinkList(pHeader, 20, 200);
insert_LinkList(pHeader, -1, 300);
printf("插入数据后,遍历链表的结果为\n");
foreach_LinkList(pHeader);
//测试 删除
delete_LinkList(pHeader, 30);
delete_LinkList(pHeader, 100);
delete_LinkList(pHeader, 1000);
//10 200 20 300
printf("删除数据后,遍历链表的结果为\n");
foreach_LinkList(pHeader);
//清空链表
clear_LinkList(pHeader);
printf("清空数据后,遍历链表的结果为\n");
foreach_LinkList(pHeader);
insert_LinkList(pHeader, 111, 111);
insert_LinkList(pHeader, 222, 222);
insert_LinkList(pHeader, 333, 333);
printf("清空后再次使用链表,遍历链表的结果为\n");
foreach_LinkList(pHeader);
//销毁链表
destroy_LinkList(pHeader);
pHeader = NULL;
}
void test02()
{
struct LinkList* pHeader = init_LinkList();
//10 20 30
//反转后 结果应该为 30 20 10
reverse_LinkList(pHeader);
printf("反转链表后结果为:\n");
foreach_LinkList(pHeader);
printf("链表的长度为:%d\n", size_LinkList(pHeader));
}
//程序入口
int main(void)
{
//test01();
test02();
system("pause"); //按任意键暂停 阻塞功能
return EXIT_SUCCESS;
}
使用环境,vs2019
下方欢迎扫码关注《迈克尔升学编程》,与我一起学习,共同进步,领略编程世界的魅力艺术。