线性结构之单链表详解


在这里插入图片描述

前言

我们前面学习了顺序表的实现,那么今天我们来学习单链表,当然单链表也有许多种类,在这里我当然是讲不完的,在这里我只介绍单链表最常见的无头单向非循环链表


一.单链表的结构体

typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;//指向下一个节点的指针
}SLN;

在这里插入图片描述

二、单链表的基本接口

1.SListMalloc(申请节点)

SLN* SListMalloc(SLTDataType x)
{
	SLN* newnode = (SLN*)malloc(sizeof(SLN));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

我这里的命名可能不规范,你按照自己的命名习惯来

2.SListPushBack(尾插)

void SListPushBack(SLN** pphead ,SLTDataType x)
{
	SLN*newnode= SListMalloc(x);
	if (*pphead== NULL)//头结点如果为空
	{
		*pphead = newnode;
	}
	else
	{
		SLN* tail = *pphead;
		while (tail->next != NULL)//找到含有NULL节点的位置;即最后的位置;
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

这个函数为什么传参的时候需要二级指针呢?头节点如果为空,我们是需要修改头结点的内容的,头节点是一个一级指针,那么我们修改他就需要二级指针

3.SListPushFront(头插)

void SListPushFront(SLN** pphead, SLTDataType x)
{
	SLN* newnode = SListMalloc(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
}

在这里插入图片描述

真理不管头指针是不是空指针,我们都是需要修改头指针的,当头插时,我们将新的节点的next指向phead之后,我们就要修改头指针为新的节点,所以我们都需要修改头指针

4.SListPopBack(尾删)

void SListPushBack(SLN** pphead ,SLTDataType x)
{
	SLN*newnode= SListMalloc(x);
	if (*pphead== NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLN* tail = *pphead;
		while (tail->next != NULL)//找到含有NULL节点的位置;即最后的位置;
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

5.SListPopFront(头删)

void SListPushFront(SLN** pphead, SLTDataType x)
{
	SLN* newnode = SListMalloc(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
}

既然需要改变头部指针指向,那么就需要传二级指针

6.SListInsert(插入)

void SListInsert(SLN** pphead, SLN* pos, SLTDataType x)//在pos的前面插入
{
	if (pos = *pphead)
	{
		SListPushFront(pphead, x);
	}
	else
	{
		SLN* newnode = SListMalloc(x);
		assert(newnode != NULL);
		SLN* prev = *pphead;
		while (prev->next != pos)//这里需要找到pos的前面的位置,遍历
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;
	}
}

7.SListErase(删除)

void SListErase(SLN** pphead, SLN* pos)
{
	if (*pphead == pos)
	{
		SListPopBack(pphead);
	}
	else
	{
		SLN* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
	}
}

8.SListFind(查找)

SLN* SListFind(SLN** pphead, SLTDataType x)
{
	SLN* temp = *pphead;
	while (temp)
	{

		if(temp->data == x)
		{
			return temp;
		}
		else
		{
			temp = temp->next;
		}
		
	}
	return NULL;//如果没有找到就返回一个NULL
}

9.SListPrint(打印)

void SListPrint(SLN*phead)
{
	//遍历链表
	SLN* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
}

这里是我个人加的接口,遍历一遍链表

10.SListDestroy(销毁)

void SListDestroy(SLN** pphead)
{
	assert(*pphead != NULL);
	while(*pphead!=NULL)
	{
		SLN* next = (*pphead)->next;
		free(*pphead);
		*pphead = next;
	}
}

这里销毁指的是整个链表的删除

三、整体结构

1.头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLN;
SLN* SListMalloc(SLTDataType x);
void SListPrint(SLN* phead);
void SListPushBack(SLN** phead, SLTDataType x);
void SListPushFront(SLN** pphead, SLTDataType x);
void SListPopBack(SLN** pphead);
void SListPopFront(SLN** pphead);
SLN* SListFind(SLN** pphead,SLTDataType x);
void SListInsert(SLN** pphead, SLN* pos, SLTDataType x);
void SListErase(SLN** pphead, SLN* pos);
void SListDestroy(SLN** pphead);

2.源文件

#include"SList.h"
#include<assert.h>
SLN* SListMalloc(SLTDataType x)
{
	SLN* newnode = (SLN*)malloc(sizeof(SLN));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
void SListPrint(SLN*phead)
{
	//遍历链表
	SLN* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
}
void SListPushBack(SLN** pphead ,SLTDataType x)
{
	SLN*newnode= SListMalloc(x);
	if (*pphead== NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLN* tail = *pphead;
		while (tail->next != NULL)//找到含有NULL节点的位置;即最后的位置;
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}
void SListPushFront(SLN** pphead, SLTDataType x)
{
	SLN* newnode = SListMalloc(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
}
void SListPopBack(SLN** pphead)//这里需要考虑NULL,只有一个和两个及两个以上
{
	SLN* tail=*pphead;
	SLN* prev = NULL;
	assert(*pphead != NULL);
	if ((*pphead)->next == NULL)
	{
		*pphead = NULL;
	}
	else
	{
		while (tail->next !=NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		prev->next = NULL;
	}
}
void SListPopFront(SLN** pphead)//这里不需要用考虑只有一个节点的情况,因为没有引用next
{
	SLN* temp = *pphead;
	assert(*pphead != NULL);
	*pphead = (*pphead)->next;	
	free(temp);
}
SLN* SListFind(SLN** pphead, SLTDataType x)
{
	SLN* temp = *pphead;
	while (temp)
	{

		if(temp->data == x)
		{
			return temp;
		}
		else
		{
			temp = temp->next;
		}
		
	}
	return NULL;
}
void SListInsert(SLN** pphead, SLN* pos, SLTDataType x)//在pos的前面插入
{
	if (pos = *pphead)
	{
		SListPushFront(pphead, x);
	}
	else
	{
		SLN* newnode = SListMalloc(x);
		assert(newnode != NULL);
		SLN* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;
	}
}
void SListErase(SLN** pphead, SLN* pos)
{
	if (*pphead == pos)
	{
		SListPopBack(pphead);
	}
	else
	{
		SLN* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
	}
}
void SListDestroy(SLN** pphead)
{
	assert(*pphead != NULL);
	while(*pphead!=NULL)
	{
		SLN* next = (*pphead)->next;
		free(*pphead);
		*pphead = next;
	}
}



结语

说实话,感觉写的有点水,如果有什么好的提议欢迎讨论

  • 32
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 36
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ruiren.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值