数据结构---单向链表

news2024/11/18 1:47:41

思路分析: 

1. 设计

        struct LinkNode                 节点结构体
        strut LList                          链表结构体
        typedef void  *LinkList       给用户使用链表指针

2. 初始化链表

LinkList mylist = init_LinkList();

3. 插入链表

void insert_LinkList(LinkList list, int pos, void* data)

4. 遍历链表 

void foreach_LinkList(LinkList list,void (*myForeach)(void *))

5. 删除链表

按位置删除

void removeByPos_Linklist(LinkList list, int pos)

按值删除

void removeByValue_Linklist(LinkList list, void* data, int(*myCompare)(void*, void*))

6. 清空

void clear_LinkList(LinkList list)

7. 返回链表长度

int size_LinkList(LinkList list)

8. 销毁

int destroy_LinkList(LinkList list)

代码如下:

#define _CRT_SECURE_NO_WARNINGS  
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//节点结构体
struct LinkNode
{
	//数据域
	void* data;
	//指针域
	struct LinkNode *next;
};

//链表结构体
struct LList
{
	//头节点
	struct LinkNode pHeader;
	//链表长度
	int m_size;
};

typedef void* LinkList;

//初始化链表
LinkList init_LinkList()
{
	struct LList* myList = malloc(sizeof(struct LList));
	if (myList == NULL)
	{
		return NULL;
	}

	myList->pHeader.data = NULL;
	myList->pHeader.next = NULL;
	myList->m_size = 0;

	return myList;
}

//插入链表
void insert_LinkList(LinkList list, int pos, void* data)
{
	if (list == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}
	//将list还原成struct LList数据类型
	struct LList* myList = list;
	if (pos<0 || pos>myList->m_size)
	{
		//无效位置强制作尾插
		pos = myList->m_size;
	}

	//找到插入节点的前驱节点位置
	struct LinkNode* pCurrent = &myList->pHeader;

	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
		//pCurrent 要插入节点的前驱
	}

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

	//建立节点关系
	newNode->next = pCurrent->next;
	pCurrent->next = newNode;

	//更新链表长度
	myList->m_size++;
}

//遍历链表
void foreach_LinkList(LinkList list,void (*myForeach)(void *))
{
	if (list == NULL)
	{
		return;
	}

	struct LList* mylist = list;
	
	struct LinkNode* pCurrent = mylist->pHeader.next;

	for (int i = 0; i < mylist->m_size; i++)
	{
		myForeach(pCurrent->data);
		pCurrent = pCurrent->next;
	}
}


//删除链表 按位置
void removeByPos_Linklist(LinkList list, int pos)
{
	if (list == NULL)
	{
		return;
	}
	struct LList* mylist = list;

	if (pos < 0 || pos > mylist->m_size - 1)
	{
		return;
	}

	//找到待删除节点的前驱节点
	struct LinkNode* pCurrent = &mylist->pHeader;

	for (int i = 0; i < pos; i++)
	{
		pCurrent = pCurrent->next;
	}

	//记录待删除的节点
	struct LinkNode* pDel = pCurrent->next;

	//重新建立节点关系
	pCurrent->next = pDel->next;

	free(pDel);
	pDel = NULL;

	//更新链表长度
	mylist->m_size--;	
}

//按照值删除链表
void removeByValue_Linklist(LinkList list, void* data, int(*myCompare)(void*, void*))
{
	if (list == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	struct LList* mylist = list;
	//创建两个辅助指针
	struct LinkNode* pPrev = &mylist->pHeader;
	struct LinkNode* pCurrent = pPrev->next;

	for (int i = 0; i < mylist->m_size; i++)
	{
		//pCurrent->data data将两个指针比较利用回调交给用户
		if (myCompare(pCurrent->data, data))
		{
			pPrev->next = pCurrent->next;

			free(pCurrent);
			pCurrent = NULL;

			mylist->m_size--;
			break;
		}

		//辅助指针后移
		pPrev = pCurrent;
		pCurrent = pCurrent->next;
	}
}

//清空链表
void clear_LinkList(LinkList list)
{
	if (list == NULL)
	{
		return;
	}

	struct LList* mylist = list;
	struct LinkNode* pCurrent = mylist->pHeader.next;
	
	for (int i = 0; i < mylist->m_size;i++)
	{
		struct LinkNode* pNext = pCurrent->next;

		free(pCurrent);

		pCurrent = pNext;
	}

	mylist->pHeader.next = NULL;
	mylist->m_size = 0;
}

//返回链表长度
int size_LinkList(LinkList list)
{
	if (list == NULL)
	{
		return -1;
	}

	struct LList* mylist = list;
	return mylist->m_size;
}

//销毁链表
int destroy_LinkList(LinkList list)
{
	if (list == NULL)
	{
		return ;
	}

	//清空链表
	clear_LinkList(list);

	free(list);

	list = NULL;
}

//测试
struct Person
{
	char name[64];
	int age;
};

void myPrintPerson(void* data)
{
	struct Person* p = data;
	printf("姓名:%s 年龄:%d\n", p->name, p->age);
}

int myComparePerson(void* data1, void* data2)
{
	struct Person* p1 = data1;
	struct Person* p2 = data2;

	return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}

void test01()
{
	//准备数据
	struct Person p1 = { "亚瑟",18 };
	struct Person p2 = { "妲己",20 };
	struct Person p3 = { "安其拉",19 };
	struct Person p4 = { "凯",21 };
	struct Person p5 = { "孙悟空",999 };
	struct Person p6 = { "李白",999 };

	//初始化链表
	LinkList mylist = init_LinkList();

	printf("链表的长度为:%d\n", size_LinkList(mylist));

	//插入数据
	insert_LinkList(mylist, 0, &p1);
	insert_LinkList(mylist, 0, &p2);
	insert_LinkList(mylist, -1, &p3);
	insert_LinkList(mylist, 0, &p4);
	insert_LinkList(mylist, 1, &p5);
	insert_LinkList(mylist, 0, &p6);

	// 李白 凯 孙悟空 妲己 亚瑟 安琪拉

	//遍历
	foreach_LinkList(mylist, myPrintPerson);

	printf("链表的长度为:%d\n", size_LinkList(mylist));

	//测试删除
	removeByPos_Linklist(mylist, 4);

	printf("-----------------\n");

	foreach_LinkList(mylist, myPrintPerson);
	printf("链表的长度为:%d\n", size_LinkList(mylist));

	struct Person p = { "孙悟空",999 };
	removeByValue_Linklist(mylist, &p, myComparePerson);

	printf("-----------------\n");

	foreach_LinkList(mylist, myPrintPerson);
	printf("链表的长度为:%d\n", size_LinkList(mylist));

	//测试清空
	clear_LinkList(mylist);

	//返回链表长度
	printf("链表的长度为:%d\n", size_LinkList(mylist));

	//销毁
	destroy_LinkList(mylist);
	mylist = NULL;
}

int main(){
	test01();
	return 0;
}

输出如下所示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1712225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用python实现炫酷的渐变色

使用python实现炫酷的渐变色 1、前言2、所需条件3、实现步骤步骤1&#xff1a;定义渐变函数步骤2&#xff1a;将渐变应用于目标颜色步骤3&#xff1a;定义参数并执行 4、完整代码5、总结 1、前言 通过应用颜色渐变&#xff0c;可以大大提升图像的视觉效果。在这篇博客中&#…

2025第十届美陈展

展位又遭疯抢&#xff01;2025第十届美陈展释放“无界之美” 美是全球通用的语言&#xff0c;人类对美的追求始终如一&#xff0c;大众审美在经历了时代的变迁后开始趋同&#xff0c;东方文明深处的美学经济开始崛起。 在如今商业迈入存量阶段&#xff0c;以品牌为突破口打造…

基于VMware安装Linux虚拟机

1.准备Linux环境 首先&#xff0c;我们要准备一个Linux的系统&#xff0c;成本最低的方式就是在本地安装一台虚拟机。为了统一学习环境&#xff0c;不管是使用MacOS还是Windows系统的同学&#xff0c;都建议安装一台虚拟机。 windows采用VMware&#xff0c;Mac则采用Fusion …

有免费通配符证书吗?哪里可以申请?

市面上的免费SSL证书大多数为单域名证书&#xff0c;如果您的主域名拥有众多子域名&#xff0c;逐一申请单域名SSL证书不太现实&#xff0c;下面为介绍一款永久免费使用的通配符SSL证书申请流程 1 选择免费通配符证书提供商 免费通配符证书申请点击这里直接获取https://www.…

【DZ模板】价值288克米设计APP手机版DZ模板 数据本地化+完美使用

模版介绍 【DZ模板】价值288克米设计APP手机版DZ模板 数据本地化完美使用 腾讯官方出品discuz论坛DIY的后台设置&#xff0c;功能齐全&#xff0c;论坛功能不亚于葫芦侠&#xff0c;自定义马甲&#xff0c;自定义认证&#xff0c;自定义广告&#xff0c;完全可以打造出自己想…

据阿谱尔APO Research调研显示,2023年全球模塑纤维包装市场销售额约为60.4亿美元

根据阿谱尔 (APO Research&#xff09;的统计及预测&#xff0c;2023年全球模塑纤维包装市场销售额约为60.4亿美元&#xff0c;预计在2024-2030年预测期内将以超过2.7%的CAGR&#xff08;年复合增长率&#xff09;增长。 对永续和环保包装解决方案的需求不断增长&#xff0c;以…

Python | Leetcode Python题解之第103题二叉树的锯齿形层序遍历

题目&#xff1a; 题解&#xff1a; class Solution:def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:if not root: return []res, deque [], collections.deque()deque.append(root)while deque:tmp []# 打印奇数层for _ in range(len(deque)…

java8以上版本

java9及其以上版本 一、JDK17 LTS 常用新特性1、switch语句的增强2、字符串拼接3、判断类型instanceof自动类型转换4、密封类 关键字 sealed permits5、record类6、优化空指针异常7、ZGC垃圾收集器 一、JDK17 LTS 常用新特性 1、switch语句的增强 在 Java 17中&#xff0c;sw…

全面指南:IP SSL证书的申请与部署步骤

不同于常见的域名型SSL证书&#xff0c;IP SSL证书是专门用于为IP地址提供安全保护的SSL证书类型&#xff0c;适用于那些直接通过IP地址访问的网站或服务。本文将详细介绍IP SSL证书的申请步骤及其部署过程&#xff0c;帮助您轻松实现IP地址的安全加密。 一、了解IP SSL证书 …

CSS Canvas鼠标点击特效之天女散花(文本粒子动画)

1.效果 2.代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>body,html {margin: 0;padding: 0;w…

Docker HTTPS api V2 Manifest V 2, Schema 2 下的免装docker下载镜像的方法

目录 前言 下载镜像代码 使用方法 原代码中无法适配 Schema 2 的原因浅析 如何解决 相对原代码改动的东西 前言 本文提供代码主要是基于 https://github.com/NotGlop/docker-drag 提供的代码修改的。链接中提供的代码应该是是基于HTTPS api V2 Manifest V 2, Schema 1实…

【算法实战】每日一题:统计一个序列向某个方向的比他小的数的个数(非暴力)

题目 统计一个序列向某个方向的比他小的数的个数 思路 用单调栈&#xff0c;虽然这里说的是统计比他小的&#xff0c;但是是求和&#xff0c;所以我们可以用在用单调栈的时候统计里面所有比他大的元素 这两个级别上是一样的 伪代码 声明变量 n、num 和 sum 为整数。 声明…

实操专区-第15周-课堂练习专区-漏斗图与金字塔图

实操专区-第15周-课堂练习专区-漏斗图 下载安装ECharts&#xff0c;完成如下样式图形。 代码和截图上传 基本要求&#xff1a;下图3选1&#xff0c;完成代码和截图 完成 3.1.3.16 漏斗图中的任务点 基本要求&#xff1a;2个选一个完成&#xff0c;多做1个加2分。 请用班级学号姓…

vue组件的基本使用方法

组件 【1】组件是什么&#xff1f; 组件就是&#xff1a;扩展 HTML 元素&#xff0c;封装可重用的代码&#xff0c;目的是复用例如&#xff1a;有一个轮播图&#xff0c;可以在很多页面中使用&#xff0c;一个轮播有js&#xff0c;css&#xff0c;html组件把js&#xff0c;cs…

使用 Django 连接 MySQL 数据库

文章目录 步骤一&#xff1a;安装必要的库和驱动步骤二&#xff1a;配置数据库连接步骤三&#xff1a;执行数据库迁移步骤四&#xff1a;开始使用 MySQL 数据库创建一个模型迁移模型到数据库使用模型进行数据操作创建新记录&#xff1a;查询记录&#xff1a;更新记录&#xff1…

264 基于matlab的自适应语音盲分离

基于matlab的自适应语音盲分离&#xff0c;当a和b同时对着传声器A,B说话且传声器靠得很近时&#xff0c;传声器A,B会同时接受到a和b的声音&#xff0c;即a和b产生了混叠干扰&#xff0c;此时通过自适应语音盲分离系统可以将a,b的声音分离开&#xff0c;使得一个信道只有一个人的…

【并发程序设计】11.进程间通信

11.进程间通信 &#xff08;IPC&#xff0c;InterProcess Communication&#xff09;进程和进程之间交换信息。 常用通信方式 无名管道&#xff08;pipe&#xff09;有名管道 &#xff08;fifo&#xff09;信号&#xff08;signal&#xff09;共享内存(mmap)套接字&#xff0…

平衡二叉树的构建(理论,部分函数代码)

平衡二叉树是二叉排序树的一种特殊情况&#xff0c;平衡二叉树的出现是为了在最坏情况下的时间复杂度仍然是对数级别O(logn)&#xff0c;从而保证了高效的搜索、插入和删除操作。 举个例子&#xff0c;如果有一个数组是&#xff1a;1&#xff0c;2&#xff0c;3。如果只简单的…

数据库多表查询

多表查询&#xff1a; SELECT *FROM stu_table,class WHERE stu_table.c_idclass.c_id; 多表查询——内连接 查询两张表交集部分。 隐式内连接&#xff1a; #查询学生姓名&#xff0c;和班级名称&#xff0c;隐式调用 SELECT stu_table.s_name,class.c_name FROM stu_table…

vs code 中使用SSH 连接远程的Ubuntu系统

如下图&#xff0c;找到对应的位置 在电脑上找到以下位置 打开配置如下&#xff0c;记住&#xff0c;那个root为你的用户名&#xff0c;这个用户名&#xff0c;具体根据你的用户名来设置&#xff0c;对应的密码就是你登录Ubuntu时的密码 Host root192.168.0.64User rootHostNa…