首页 > 其他分享 >讲解如何用C语言实现带头单向单链表

讲解如何用C语言实现带头单向单链表

时间:2024-08-31 19:22:36浏览次数:16  
标签:ptail 单向 pos next 单链 SListNode C语言 plist

目录

链表的结构组成:

链表的常用接口:

初始化带头单链表的头指针:

动态申请一个结点(用于后续数据的插入):

单链表打印:

单链表尾插:

单链表的头插:

单链表的尾删:

单链表头删:

单链表查找符合值的第一个节点,没找到时返回NULL:

单链表在pos位置之后插入x:

单链表删除pos位置之后的值:

致谢:


链表的结构组成:

在学习链表之前,我们先来简单认识一下链表这个结构(本篇文章均用链表存储整型数据进行讲解)(本篇文章针对的是带头单向单链表的实现)

#pragma once
#include <stdio.h>
typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType data;
	struct SListNode* next;
}SListNode;

链表整体结构是由一个头结点,和多个结点连接到一起构成的一种数据结构,尾结点的next指针指向空。每个结点由携带数据和next指针构成。是一种便于头部插入删除的一种数据结构。

链表的常用接口:

下面是我们要实现的链表的一些常用接口:

//初始化带头单链表的头指针
void SListNodeInit(SListNode** pplist);
// 动态申请一个结点(用于后续数据的插入)
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode* plist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode* plist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode* plist);
// 单链表头删
void SListPopFront(SListNode* plist);
// 单链表查找符合值的第一个节点
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos);

初始化带头单链表的头指针:

带头单链表结构的头指针指向的是一个不存放数据的无效结点,只是为了方便头部的插入删除操作。

//初始化带头单链表的头指针
void SListNodeInit(SListNode** pplist)
{
	(*pplist) = (SListNode*)malloc(sizeof(SListNode));
	(*pplist)->next = NULL;
}

从上面的代码我们可以看出来一个问题,那就是我为什么在这个函数里传的参数是二级指针呢?

答:因为上面函数的目的是要改变单链表的头指针的指向,我要去改变这个头指针的话只能传这个头指针的地址,运用传址调用函数这个方法改变头指针。

动态申请一个结点(用于后续数据的插入):

// 动态申请一个结点(用于后续数据的插入)
SListNode* BuySListNode(SLTDateType x)
{
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

单链表打印:

单链表的打印我们只需要从第一个有效节点去遍历这个链表就可以了。

我们这里只需要从这里的newphead这个节点开始遍历就可以了。

// 单链表打印
void SListPrint(SListNode* plist)
{
	SListNode* newphead = plist->next;
	SListNode* ptail = newphead;
	while (ptail!=NULL)
	{
		printf("%d->", ptail->data);
		ptail = ptail->next;
	}
	printf("NULL\n");
}

结束条件就是ptail指针指向NULL的时候。

单链表尾插:

// 单链表尾插
void SListPushBack(SListNode* plist, SLTDateType x)
{
	SListNode* newnode = BuySListNode(x);
	SListNode* ptail = plist;
	while (ptail->next != NULL)
	{
		ptail = ptail->next;
	}
	ptail->next = newnode;
}

单链表的头插:

头插由于有一个头结点,所以头插比较容易一些。

头插一定注意先保留plist->next给newnode->next,因为如果先对头结点的next指针进行操作的话会导致后面的数据丢失。

// 单链表的头插
void SListPushFront(SListNode* plist, SLTDateType x)
{
	SListNode* newnode = BuySListNode(x);
	newnode->next = plist->next;
	plist->next = newnode;
}

单链表的尾删:

// 单链表的尾删
void SListPopBack(SListNode* plist)
{
	assert(plist->next);
	SListNode* ptail = plist;
	while (ptail->next->next)
	{
		ptail = ptail->next;
	}
	free(ptail->next);
	ptail->next = NULL;
}

单链表头删:

思路:先拿ptail指针记录下第二个有效节点的位置,然后删除第一个数据,最后将plist节点和ptail节点连接上。

// 单链表头删
void SListPopFront(SListNode* plist)
{
	assert(plist->next);
	SListNode* ptail = plist;
	ptail = ptail->next->next;
	free(plist->next);
	plist->next = ptail;
}

单链表查找符合值的第一个节点,没找到时返回NULL:

这个接口也是遍历链表。

// 单链表查找符合值的第一个节点,没找到返回NULL
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
	SListNode* ptail = plist->next;
	while (ptail)
	{
		if (ptail->data == x)
		{
			return ptail;
		}
		ptail = ptail->next;
	}
	printf("抱歉,没有找到\n");
	return NULL;
}

单链表在pos位置之后插入x:

这个插入方法和我上面讲解的头插方法类似,因此直接代码奉上,不做过多讲解。

// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
	SListNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

单链表删除pos位置之后的值:

这个删除方法和我上面讲解的头删方法类似,因此直接代码奉上,不做过多讲解。

// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos)
{
	assert(pos->next);
	SListNode* ptail = pos;
	ptail = ptail->next->next;
	free(pos->next);
	pos->next = ptail;
}

致谢:

至此,我们的带头单向单链表的常用接口就已经实现完毕了,后续,本管家还会持续更新数据结构方面的内容,同时也会穿插着数据结构常见的算法题进行讲解。

同时也希望读者能够在评论区给我的文章提出一些建议,也可以在我讲解内容方面哪里做的比较好的地方在评论区点出来,我会继续发扬光大,不好的地方我也会接受批评;读者的一些点赞、收藏和评论也是对本管家的一些支持与鼓励,如果您看完这篇有所收获,还请您点个免费的赞和收藏,我会更有动力!感谢观看!!!

标签:ptail,单向,pos,next,单链,SListNode,C语言,plist
From: https://blog.csdn.net/GGbond665/article/details/141685061

相关文章

  • 主元素问题(C语言)
    主元素问题(C语言)题目参考代码#include<stdio.h>intmain(){//主元素问题intn,s[400002],num=1,max=0,maxNum=0;scanf("%d",&n);for(inti=0;i<n;i++)scanf("%d",&s[i]);for(inti=0;......
  • c语言分支与循环详解
    使用if、switch实现分支结构,使用for、while、dowhile实现循环结构分支:1.1if语句的语法if(表达式) 语句;在c语言中0表示假,则语句不执行。非0表示真,语句执行1.2else与if对应,比如说一个数不是奇数就是偶数了if(表达式) 语句1;else 语句2;表达式成立则执行语句1,不成......
  • 7-1 素数对猜想(C语言)
    7-1素数对猜想题目参考代码#include<stdio.h>intmain(){ //一、用埃拉托斯特尼筛法,找出所有的素数 intnum[100002]; intN; scanf("%d",&N); for(inti=2;i<N+2;i++)//赋初值为1,表示均为素数 num[i]=1; //把未标记的数的的倍数,全部标记为非素......
  • 【华为OD机试真题E卷】31、最大社交距离 | 机试真题+思路参考+代码分析(E卷复用)(C语言、
    文章目录一、题目......
  • 数据结构-单链表-详解-2
    数据结构-单链表-详解-21.前言2.创建新结点3.头插与尾插3.1头插3.2尾插空链表找尾4.头删与尾删4.1头删4.2尾删1.前言在数据结构-单链表-详解-1中,我们不仅了解了单链表的基本概念,还掌握了如何创建和打印单链表。今天,我将详细讲解如何对单链表进行头尾部的插入、......
  • Python比C语言到底有什么优势?为什么越来越多人都学python?
    Python作为一种高级编程语言,在众多编程语言中脱颖而出,主要得益于其多方面的优势。以下是Python相比于其他语言的一些显著优势:简单易学:Python的语法清晰、简洁,易于阅读和编写,这使得它成为初学者的首选语言。其语法结构接近于自然语言,减少了学习曲线的陡峭度。丰富的库和框......
  • C语言(vs2022、Vc++6.0、DevC++)连接MySql
    本文c++(OraOla编写)与Java(Wideskyzz编写)由于csdn的排版太垃圾了,所以可以直接看资料上传资料也麻烦,所以可直接访问我的giteeC语言连接MySql:C语言(vs2022、Vc++6.0、DevC++)连接MySqlhttps://gitee.com/gyhjim/c-language-connection---my-sql一定要自己实践当你发现与我的......
  • CCF-CSP 2024 --重塑矩阵1,2c语言题解
     创作想法是因为像我当初大一时候想参加一些比赛但是奈何只学了c和c相关数据结构,但是对于许多竞赛的题目的题解往往都是c++或者其他面向对象的编程语言,让我们难以在c语言基础上入手这些比较复杂的题目。 创造的目的是为了帮助各位同时提高我对c语言编程的理解和锻炼个人......
  • C语言 ——— 文件的顺序读写
    目录顺序读写函数介绍​编辑测试fputc函数​编辑测试fgetc函数​编辑测试fputs函数​编辑测试fputs 函数​编辑测试fgets函数​编辑顺序读写函数介绍 测试fputc函数第一个参数是传递字符,第二个参数传递文件指针 #include<stdio.h>intmain(){ //......
  • 单链表应用
    基于单链表实现通讯录项目//Contact.c#define_CRT_SECURE_NO_WARNINGS1#include"contact.h"#include"list.h"//初始化通讯录voidInitContact(contact**con){ con=NULL; }//添加通讯录数据voidAddContact(contact**con){ PeoInfoinfo; printf("addres......