链表基本使用学习

学习链表的基本使用,初始化,遍历,插入,删除,清空,销毁

链表基本使用:

带头节点链表 好处在于,头节点永远都是固定的

初始化链表 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

下方欢迎扫码关注《迈克尔升学编程》,与我一起学习,共同进步,领略编程世界的魅力艺术。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值