首页 > 其他分享 >【数据结构】C语言单链表的实现

【数据结构】C语言单链表的实现

时间:2024-03-26 13:59:45浏览次数:23  
标签:pphead 单链 SLTNode void pos C语言 链表 next 数据结构

有时我们不用顺序表,而使用链表,是因为顺序表存在一定的问题

1、顺序表的中间/头部的插入、删除需要挪动数据

2、扩容需要申请新空间,拷贝数据,释放旧空间,存在性能的消耗

3、会有空间的浪费

单链表:不带头单向循环链表

双链表:带头双向循环链表

单链表的具体实现:

1、单链表的创建:

2、单链表的打印:

3、结点的申请:

4、链表的尾插、头插:

5、尾删、头删


6、链表的查找:

7、在指定位置之前插入数据:

8、在指定位置之后插入数据:

9、删除pos结点:

10、删除pos之后的结点

11、销毁链表

具体代码实现如下:

1、SList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>

typedef int SLTDataType;
//链表是由结点组成
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;
//打印
void SLTPrint(SLTNode* phead);

//链表的尾插、头插
void SLTPushBack(SLTNode** pphead,SLTDataType x);
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//尾删、头删
void SLTPopBack(SLTNode** pphead);
void SLTPopFront(SLTNode** phead);
//查找
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x);
//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos);
//删除pos之后的结点
void SLEraseAfter(SLTNode* pos);
//销毁链表
void SListDestroy(SLTNode** pphead);

2、方法的具体实现:.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
#include<assert.h>
void SLTPrint(SLTNode* phead)
{
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}
//申请新的结点
SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	//内存不够时,申请不成功
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
//链表的尾插、头插
//用二级指针接收一级指针plist的地址
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	//链表为空
	if(*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
	//链表不为空
	SLTNode* ptail = *pphead;
	while (ptail->next)
	{
		ptail = ptail->next;
	}
	ptail->next = newnode;
}
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}
//尾删、头删
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	//链表不能为空
	assert(*pphead);
	//链表只有一个结点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	//有多个结点
	SLTNode* ptail = *pphead;
	SLTNode* prev = NULL;
	while (ptail->next)
	{
		prev = ptail;
		ptail = ptail->next;
	}
	prev->next = NULL;
	//销毁尾结点
	free(ptail);
	ptail = NULL;

}
void SLTPopFront(SLTNode** pphead)
{
	assert(pphead);
	//链表不能为空
	assert(*pphead);
	//让第二个结点成为新的头
	//把旧的头结点释放掉
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;

}
//查找
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	//遍历链表
	SLTNode* pcur = *pphead;
	while (pcur)
	{
		if (pcur->data == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	//没有找到
	return NULL;
}
//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	//链表不能为空
	assert(*pphead);
	//pos刚好是头结点
	if (pos == *pphead)
	{
		//头插
		SLTPushFront(pphead, x);
		return;
	}
	SLTNode* newnode = SLTBuyNode(x);
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = newnode;
	newnode->next = pos;
}
//在指定位置之前插入数据:
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	//pos刚好是头结点,没有前驱结点,执行头删
	if (*pphead == pos)
	{
		//头删
		SLTPopFront(pphead);
		return;
	}
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = pos->next;
	free(pos);
	pos = NULL;
}
//删除pos之后的结点
void SLEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);
	SLTNode* del = pos->next;
	pos->next = pos->next->next;
	free(del);
	del = NULL;
}
//销毁链表
void SListDestroy(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	SLTNode* pcur = *pphead;
	while (pcur)
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

感谢观看,如有疑问,我一定尽力解答!

标签:pphead,单链,SLTNode,void,pos,C语言,链表,next,数据结构
From: https://blog.csdn.net/GxySkywalker/article/details/137024928

相关文章

  • 1 初识C语言
    1.1C语言的起源C语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发UNIX操作系统而设计的。C语言最开始是于1972年在DECPDP-11计算机上被首次实现。1.2C语言的特点易于学习。结构化语言。它产生高效率的程序。它可以处理底层的活动。它可......
  • 【C语言】Infiniband驱动__mlx4_init_one函数
    一、注释Linux内核驱动程序中的部分,属于Mellanox网卡驱动mlx4的初始化过程。//Mellanox以太网驱动主程序代码staticint__mlx4_init_one(structpci_dev*pdev,intpci_dev_data,structmlx4_priv*priv){interr;//错误码变量intnvfs[ML......
  • 根号数据结构与根号平衡入门指南
    本文为本人为应付学校科技节写的屑作。写得比较仓促,可能存在不严谨或错误之处,欢迎批评指正。在本文中若无特殊说明,\(n\)表示元素数量,\(m\)表示询问数量,\(V\)表示值域范围为\([1,V]\)。一、分块分块,即将数据划分为多个块,并在操作时对整个块进行整体处理的思想。分块并非一......
  • 数据结构-哈希表-007
    1哈希表-通讯录1.1哈希结点结构体定义/*=====自定义数据类型=====*/typedefstructperson_information{charname[32];charsex;intage;chartel[32];charaddr[64];}DATA_TYPE;/*=====定义一个哈希数据结点=====*/typedefstructhash_......
  • 数据结构——二叉搜索树详解
    一、二叉搜索树定义二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:1.非空左子树上所有节点的值都小于根节点的值。2.非空右子树上所有节点的值都大于根节点的值。3.左右子树也都为二叉搜索树。如下图所示:二、二叉搜索树的操作二叉搜索树结构:t......
  • C语言 ---- 位操作处理
    在C语言中,位操作是一种对整数的二进制位进行直接操作的技术。它们通常用于对位表示的数据进行快速、高效的操作。以下是C语言中常用的位操作:按位与(BitwiseAND):用&运算符执行,将两个操作数的对应位进行逻辑与操作,结果为1时,结果位为1,否则为0。result=num1&num2;按位或(B......
  • C语言 ---- 指针
    在C语言中,指针是一个用于存储变量地址的特殊数据类型。指针可以用于直接访问和修改内存中的数据,是实现动态内存分配和高效数据处理的重要工具。以下是指针的定义和声明方式:指针的定义:指针定义时必须指定指针所指向变量的数据类型。定义指针使用一个星号(*)来表示。示例:int......
  • C语言 ---- 数据类型
    1基本数据类型C语言中的基本数据类型包括整型、浮点型和字符型,每种类型都有不同的存储大小和表示范围。以下是它们的常见表示形式和特点:整型(IntegerTypes):包括有符号和无符号整数。有符号整型可以表示正数、负数和零,无符号整型仅能表示非负数(零和正数)。常见的整型包括:c......
  • c语言应用,函数综合应用(2)
    c语言刚开始学习的时候,一般来说,我们如果只是在一个源文件里面编程,那么我们都会将包装的模块化函数都放在上面,把主函数放在下面的位置,目的是为了让编译软件知道主函数里调用的函数位置但是,若是我们将这些包装的模块化函数放在主函数的下面会发生什么情况呢?虽然程序依然可以继续......
  • c语言中的goto语句,goto语句的使用
    在c语言中,goto语句与分支语句if,switch不同,也和循环语句while,for,do...while不同,goto语句被称为无条件转移语句,也被称为转向语句,其实和break,return语句是同一个类型。goto语句的使用一般都需要一个again进行配合,当使用goto语句时,程序会转跳回again处重新运行again后的程序。got......