c++小白数据结构——————2单链表

1.前言 

课程主要来自于b站,链接2-02 循环链表思路_哔哩哔哩_bilibili

用的是Visual studio2022版本,自己用c++敲出来的代码。

2.代码组成

1.SingleLinkList.h(头文件中)

#pragma once
#include<iostream>
//链表节点
typedef struct LINKNODE
{
	LINKNODE* next;
	void* data;//指向任何数据类型
}LinkNode;
//链表结构体
typedef struct LINKLIST
{
	LinkNode* head;
	int size;
}LinkList;

//打印函数指针
typedef void(*PRINTLINKNODE)(void*);
//初始化链表
LinkList* Init_LinkList();
//指定位置插入
void Insert_LinkList(LinkList* list, int pos, void* value);
//删除指定位置的数值
void DeleteByPos_LinkList(LinkList* list, int pos);
//获得链表的长度
int Size_LinkList(LinkList* list);
//查找
int Find_LinkList(LinkList* list, void* data);
//返回第一个节点
void* Front_LinkList(LinkList* list);
//打印链表
void Print_LinkList(LinkList* list,PRINTLINKNODE print);
//释放链表内存
void Free_LinkList(LinkList* list);

2.SingleLinkList.cpp(源文件中)

#include"SingleLinkList.h"

//初始化链表
LinkList* Init_LinkList()
{
	LinkList* list = new LinkList;
	list->size = 0;

	list->head = new LINKNODE;
	list->head->data = NULL;
	list->head->next = NULL;
	return list;
}
//指定位置插入
void Insert_LinkList(LinkList* list, int pos, void* data)
{
	if (list == NULL) { return ; }
	if (data == NULL) { return ; }
	if (pos<0 || pos>list->size) {
		pos = list->size;
	}
	//创建新节点
	LINKNODE* newnode = new LINKNODE;
	newnode->data = data;
	newnode->next = NULL;

	//找节点
	//辅助指针变量
	LINKNODE* pCurrent = list->head;
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	newnode->next = pCurrent->next;
	pCurrent->next = newnode;
	list->size++;
}
//删除指定位置的数值
void DeleteByPos_LinkList(LinkList* list, int pos) 
{
	if (list == NULL) { return; }
	if (pos<0 || pos>=list->size) {
		return;
	}
	//查找删除节点的前一个节点
	LINKNODE* pCurrent = list->head;
	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}
	//缓存删除的节点
	LinkNode* pDel = pCurrent->next;
	pCurrent->next = pDel->next;
	delete pDel;

	list->size--;
}
//获得链表的长度
int Size_LinkList(LinkList* list)
{
	return list->size;
}
//查找
int Find_LinkList(LinkList* list, void* data)
{
	if (list == NULL) { return -1; }
	if (data == NULL) { return -1; }
	//遍历查找
	LinkNode* pCurrent = list->head->next;
	int i = 0;
	while (pCurrent != NULL) {
		if (pCurrent->data == data) {
			break;
		}
		i++;
			pCurrent = pCurrent->next;
	}
	return i;
}
//返回第一个节点
void* Front_LinkList(LinkList* list)
{
	return list->head->next->data;
}
//打印链表
void Print_LinkList(LinkList* list, PRINTLINKNODE print)
{
	if (list == NULL) { return; }
	LinkNode* pCurrent = list->head->next;
	while (pCurrent != NULL) {
		print(pCurrent->data);
		pCurrent = pCurrent->next;
	}
}
//释放链表内存
void Free_LinkList(LinkList* list)
{
	if (list == NULL) { return; }
	LinkNode* pCurrent = list->head->next;
	while (pCurrent!=NULL)
	{
		//缓存下一个节点
		LinkNode* pNext = pCurrent->next;
		delete  pCurrent;
		pCurrent = pNext;
	}
	list->size = 0;
	delete list;
}

3.test.cpp(源文件中)

#include"SingleLinkList.h"
typedef struct PERSON
{
	char name[64];
	int age;
	int score;
}Person;
void Myprint(void* data)
{
	auto* p = (Person*)data;
	std::cout << "Name:" << p->name << " age:" << p->age << " score:" << p->score << std::endl;
}
void test_SingleLinkList()
{
	//创建链表
	LinkList* list = Init_LinkList();

	//创建数据
	Person p1 = { "a",24,100 };
	Person p2 = { "b",23,99 };
	Person p3 = { "c",22,98 };
	Person p4 = { "d",21,97 };
	Person p5 = { "e",20,96 };

	//插入链表
	Insert_LinkList(list, 0, &p1);
	Insert_LinkList(list, 0, &p2);
	Insert_LinkList(list, 0, &p3);
	Insert_LinkList(list, 0, &p4);
	Insert_LinkList(list, 0, &p5);

	//打印链表
	std::cout << "创建完五个链表的数值: " << std::endl;
	Print_LinkList(list, Myprint);
	//删除
	DeleteByPos_LinkList(list, 3);
	std::cout << "删除之后的链表数值: " << std::endl;
	Print_LinkList(list, Myprint);

	//返回第一个节点
	std::cout << "第一个节点的数值: " << std::endl;
	auto ret = (Person*)Front_LinkList(list);
	std::cout << "Name:" << ret->name << " age:" << ret->age << " score:" << ret->score << std::endl;
	//销毁链表
	Free_LinkList(list);
}
int main()
{
	test_SingleLinkList();
	return 0;
}

3.代码大概讲解

SingleLinkList.h就是用来声明一些功能函数

SingleLinkList.cpp是具体怎么实现这些功能函数的

test.cpp我把测试用到的一些函数又进行了封装,并没有在main函数中直接写出

3.1 LinkList* Init_LinkList()

首先是开辟堆空间,将list的大小设置为0,list->head也要开辟堆空间,将list->head的数值data和指向下一个链表的next都设置为NULL

3.2 void Insert_LinkList(LinkList* list, int pos, void* data)

  • 首先,函数检查链表指针 list 和数据指针 data 是否为 NULL,如果是,则直接返回,因为无法执行插入操作。
  • 接着,函数检查插入位置 pos 是否合法,如果小于 0或大于链表的大小size,则将插入位置设置为链表的尾部。
  • 创建一个新的节点 newnode,并将 void* data数据存储到新节点的 data 成员中,将新节点的 next 成员设置为 NULL。
  • 遍历链表,找到需要插入位置的前一个节点,使用辅助指针变量 pCurrent,从链表头部开始向后移动,直到移动到指定的插入位置。
  • 将新节点的 next 指向当前节点 pCurrent 的下一个节点,将当前节点 pCurrentnext 指向新节点,完成插入操作。
  • 最后,更新链表的大小 list->size++

3.3 void DeleteByPos_LinkList(LinkList* list, int pos) 

  • 首先,函数检查链表指针 list 和数据指针 data 是否为 NULL,如果是,则直接返回,因为无法执行插入操作。
  • 接着,函数检查插入位置 pos 是否合法,如果小于 0或大于链表的大小size,那么直接返回
  • 查找需要删除节点的前一个节点,使用辅助指针变量 pCurrent,从链表头部开始向后移动,直到移动到指定的删除位置的前一个节点
  • 缓存需要删除的节点 pDel,即当前节点 pCurrent 的下一个节点。
  • 将当前节点 pCurrentnext 指向需要删除节点的下一个节点,即跳过需要删除的节点。
  • 使用 delete 关键字释放需要删除的节点 pDel 的内存,防止内存泄漏。
  • size++

3.4 int Size_LinkList(LinkList* list) 

3.5 int Find_LinkList(LinkList* list, void* data)

LinkNode* pCurrent = list->head->next;这段代码是直接从第一个链表开始查找,list->head并不是第一个存放数据的链表,i是用来存储数值所在的位置,函数最后返回的是所在位置

3.6 void* Front_LinkList(LinkList* list)

3.7 void Print_LinkList(LinkList* list, PRINTLINKNODE print)

注意这里用了PRINTLINKNODE print函数指针,这个指针在头文件中已经声明了typedef void(*PRINTLINKNODE)(void*);

为什么要这么做?因为这样可以传入任意的数据类型给链表,在test.cpp中给出了这个函数的具体实现方法

void Myprint(void* data)
{
	auto* p = (Person*)data;
	std::cout << "Name:" << p->name << " age:" << p->age << " score:" << p->score << std::endl;
}

3.8 void Free_LinkList(LinkList* list)

初始化时开辟了几个堆空间,那么释放内存的时候就要释放几个内存空间,注意不要漏掉。

4.运行结果

  • 51
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值