2021-06-16-C语言链表

1. 链表的基本概念

在这里插入图片描述
数组修改起来不方便,需要进行大量移动,但是数组有下标,查找第几号数据比较方便,链表对于数组操作比较快,但是不能按下标进行快速查找。
在这里插入图片描述
在这里插入图片描述
拿到链表的第一个节点,就相当于拿到整个链表。
如果链表没有头部,在插入节点时,要判断插入的位置是不是第一个位置。
如果链表有头部节点,在第一个位置插入新节点,也就是在头部节点的下一个位置插入,头节点的next永远是第一个元素。
在这里插入图片描述

2. 静态链表

#include<iostream>
using namespace std;

// 静态链表
struct LinkNode
{
	int data;
	struct LinkNode* next;
};

// 创建链表
void test()
{
	// 拿到node1就相当于拿到整个链表
	struct LinkNode node1 = { 10,NULL };
	struct LinkNode node2 = { 20,NULL };
	struct LinkNode node3 = { 30,NULL };
	struct LinkNode node4 = { 40,NULL };
	struct LinkNode node5 = { 50,NULL };
	struct LinkNode node6 = { 60,NULL };

	node1.next = &node2;
	node2.next = &node3;
	node3.next = &node4;
	node4.next = &node5;

	// 如何遍历链表?--判断指针域指向的是否为空
	// 先定义一个辅助指针变量
	struct LinkNode* pCurrent = &node1;
	while (pCurrent != NULL)
	{
		printf("%d  ", pCurrent->data);
		// 指针移动到下一个元素的首地址
		pCurrent = pCurrent->next;
	}
}

int main()
{
	test();
	system("pause");
	return EXIT_SUCCESS;
}

输出:
在这里插入图片描述

3. 动态链表

在这里插入图片描述
在这里插入图片描述

头文件LinkList.h

#pragma once  // 防止头文件重复包含
#include<iostream>
using namespace std;

// 定义节点数据类型
struct MyLinkNode
{
	int data;
	struct MyLinkNode* next;
};

// 初始化链表
struct MyLinkNode* MyInit_LinkList();
//在值为oldval的位置插入一个新的数据newval,此时需要设置三个节点
void InsertByValue_LinkList(struct MyLinkNode* header, int oldval, int newval);
//删除值为val的节点
void RemoveByValue_LinkList(struct MyLinkNode* header, int deValue);
//遍历
void MyForeach_LinkList(struct MyLinkNode* header);
//销毁
void Destroy_LinkList(struct MyLinkNode* header);
//清空
void Clear_LinkList(struct MyLinkNode* header);


函数编写文件LinkList.cpp

#include "LinkList.h"
#include<iostream>
using namespace std;

// 初始化链表
struct MyLinkNode* MyInit_LinkList()
{
	//创建头节点
	struct MyLinkNode* header = (struct MyLinkNode*)malloc(sizeof(struct MyLinkNode));
	header->data = -1;
	header->next = NULL;

	// 初始化尾部指针为头部指针
	struct MyLinkNode* pRear = header;
	int val = -1;
	while (true)
	{
		cout << "输入插入的数据:" << endl;
		cin >> val;
		if (val == -1)
		{
			break;
		}

		// 先创建新节点
		struct MyLinkNode* newNode = (struct MyLinkNode*)malloc(sizeof(struct MyLinkNode));
		newNode->data = val;
		newNode->next = NULL;

		//LinkNode
		pRear->next = newNode;

		//更新尾部指针指向
		pRear = newNode;
	}
	return header; //返回头部链表
}
//在值为oldval的位置插入一个新的数据newval
void InsertByValue_LinkList(struct MyLinkNode* header, int oldval, int newval)
{
	if (NULL == header)
	{
		return;
	}

	// 两个辅助指针变量
	struct MyLinkNode* pPrev = header;
	struct MyLinkNode* pCurrent = pPrev->next;
	while (pCurrent != NULL)
	{
		if (pCurrent->data == oldval)
		{
			break;
		}
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}

#if 0  //注释掉此段,可以实现:如果没有oldval,直接将其插入尾部
	// 如果pCurrent为空,说明链表中不存在值为oldval的节点
	if (pCurrent == NULL)
	{
		return;
	}
#endif

	// 先创建新节点
	struct MyLinkNode* newnode = (struct MyLinkNode*)malloc(sizeof(struct MyLinkNode));
	newnode->data = newval;
	newnode->next = NULL;

	//新节点插入到链表中
	//pPrev地址域放newnode地址,newnode地址域放pCurrent地址,也就是当前oldval地址
	newnode->next = pCurrent;
	pPrev->next = newnode;

}
//删除值为val的节点
void RemoveByValue_LinkList(struct MyLinkNode* header, int deValue)
{
	if (NULL == header)
	{
		return;
	}
	struct MyLinkNode* pPrev = header;
	struct MyLinkNode* pCurrent = pPrev->next;

	while (pCurrent != NULL)
	{
		if (pCurrent->data == deValue)
		{
			break;
		}
		//移动两个指针
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}
	if (pCurrent == NULL)
	{
		return;
	}
	//重新建立待删除节点的前驱和后继节点关系
	pPrev->next = pCurrent->next;
	//释放删除的节点内存
	free(pCurrent);
	pCurrent = NULL;
}
//遍历
void MyForeach_LinkList(struct MyLinkNode* header)
{
	if (NULL == header)
	{
		return;
	}

	//辅助指针变量
	struct MyLinkNode* pCurrent = header->next;//还是header->next?
	while (pCurrent != NULL)
	{
		cout << pCurrent->data << endl;
		pCurrent = pCurrent->next;
	}
}
//销毁--需要设置两个移动节点
void Destroy_LinkList(struct MyLinkNode* header)
{
	if (NULL == header)
	{
		return;
	}
	// 辅助指针变量
	struct MyLinkNode* pCurrent = header->next;
	while (pCurrent != NULL)
	{
		// 先保存当前节点的下一个节点地址
		struct MyLinkNode* pNext = pCurrent->next;
		//释放当前节点内存
		cout << "节点" << pCurrent->data << "被销毁" << endl;
		free(pCurrent);
		//指针向后移动
		pCurrent = pNext;
	}
}
//清空--只保留头节点
void Clear_LinkList(struct MyLinkNode* header)
{
	if (NULL == header)
	{
		return;
	}

	// 辅助指针变量
	struct MyLinkNode* pCurrent = header->next;
	while (pCurrent != NULL)
	{
		// 先保存当前节点的下一个节点地址
		struct MyLinkNode* pNext = pCurrent->next;

		//释放当前节点内存
		free(pCurrent);
		//pCurrent指向下一个节点
		pCurrent = pNext;
	}
	header->next = NULL;
}

主程序TestLink.cpp

#include<iostream>
using namespace std;
#include"LinkList.h"
#include<string>

void test()
{
	//初始化链表 100 200 666 300 400 500 600
	struct MyLinkNode* header = MyInit_LinkList();
	//打印链表
	MyForeach_LinkList(header);
	//插入数据
	InsertByValue_LinkList(header, 200, 666);
	cout << "--------------------------" << endl;
	//打印链表
	MyForeach_LinkList(header);
	//清空链表
	Clear_LinkList(header);
	cout << "--------------------------" << endl;
	MyForeach_LinkList(header);
	InsertByValue_LinkList(header, 1000, 111);
	InsertByValue_LinkList(header, 1000, 211);
	InsertByValue_LinkList(header, 1000, 311);
	InsertByValue_LinkList(header, 1000, 411);
	cout << "--------------------------" << endl;
	MyForeach_LinkList(header);

	//删除deValue
	RemoveByValue_LinkList(header, 311);
	cout << "--------------------------" << endl;
	MyForeach_LinkList(header);

	RemoveByValue_LinkList(header, 211);
	cout << "--------------------------" << endl;
	MyForeach_LinkList(header);

	//销毁链表
	Destroy_LinkList(header);
}

int main()
{
	test();

	system("pause");
	return EXIT_SUCCESS;
}

在这里插入图片描述

输出:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力学习的代码小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值