单链表的实现(数据结构)

本篇博客主要是单链表(无头单项不循环)的实现的代码分享

说明:因为此单链表无头(哨兵位),可以说成没有初始化也可以说初始化时没有一个有效地址作为单链表的起始地址 例如下面代码中的plist == NULL。

  所以在后面函数(链表为空时,头插、尾插、插入)实现过程中需要将plist(单链表头结点地址)修改,就需要传址操作(在这里需要传单链表节点地址的地址),而且为了代码接口的一致性,在单链表函数实现中全部传了单链表节点地址的地址!

图解:

	SLNode* plist = NULL;//只是定义了一个单向链表节点的地址,而且地址还==NULL


	SLNodePushBack(&plist,1);

头文件Single List.h

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

typedef int SLNodeDataType;
typedef struct Single_Linked_ListNode
{
	SLNodeDataType data;
	struct Single_Linked_ListNode* next;
}SLNode;

//
void SLNodePushBack(SLNode** pphead, SLNodeDataType x);
void SLNodePushFront(SLNode** pphead, SLNodeDataType x);

void SLNodePopBack(SLNode** pphead);
void SLNodePopFront(SLNode** pphead);

SLNode* SLNodeBuyNode(SLNodeDataType x);
void SLNodePrint(SLNode** pphead);

SLNode* SLNodeFind(SLNode** pphead,SLNodeDataType x);

void SLNodeInsert(SLNode** pphead, SLNode* pos, SLNodeDataType x);
void SLNodeErase(SLNode** pphead, SLNode* pos);

void SLNodeInsertAfter(SLNode** pphead, SLNode* pos, SLNodeDataType x);
void SLNodeEraseAfter(SLNode** pphead, SLNode* pos);
     
void SListDestroy(SLNode** pphead)

源文件Single Link.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Single List.h"


SLNode* SLNodeBuyNode(SLNodeDataType x)
{
	SLNode* tmp = malloc(sizeof(SLNode));
	if (tmp == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	tmp->data = x;
	tmp->next = NULL;
	return tmp;
};
void SLNodePushBack(SLNode** pphead, SLNodeDataType x)
{
	assert(pphead);
	SLNode* pnewnode = SLNodeBuyNode(x);
	//链表为空,新节点做头节点
	if (*pphead == NULL)
	{
		*pphead = pnewnode;
		return;
	}

	//链表不为空,找尾节点
	SLNode* ptail= *pphead;
	while (ptail->next != NULL)
	{
		ptail = ptail->next;
	}
	ptail->next = pnewnode;

	
};
void SLNodePushFront(SLNode** pphead, SLNodeDataType x)
{
	assert(pphead);
	SLNode* pnewnode = SLNodeBuyNode(x);
	//链表为空,新节点做头节点
	if (*pphead == NULL)
	{
		*pphead = pnewnode;
		return;
	}
	//链表不为空
	pnewnode->next = *pphead;
	*pphead = pnewnode;

}

void SLNodePopBack(SLNode** pphead)
{
	assert(pphead);
	assert(*pphead);//确保有节点
	//只有一个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);//置空前不要忘了释放空间
		*pphead = NULL;
		return;//不需要再走了
	}
	//多节点,找尾节点前一个节点
	SLNode* ptailprev = *pphead;
	while ((ptailprev->next->next) != NULL)
	{
		ptailprev = ptailprev->next;
	}
	free(ptailprev->next);
	ptailprev->next = NULL;

}
void SLNodePopFront(SLNode** pphead)
{
	assert(pphead);
	assert(*pphead);//必须有节点
	一个节点
	//if ((*pphead)->next == NULL)
	//{
	//	free(*pphead);
	//	*pphead = NULL;
	//	return;
	//}
	多个节点
	SLNode* tmp = (*pphead)->next;
	free(*pphead);
	*pphead = tmp;

}


void SLNodePrint(SLNode** pphead)
{
	SLNode* pcur = *pphead;
	while (pcur)
	{
		printf("%d->",pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}

SLNode* SLNodeFind(SLNode** pphead,SLNodeDataType x)
{
	assert(pphead);
	//遍历链表
	SLNode* pcur = *pphead;
	while (pcur)
	{
		if (pcur->data == x)
		{
			return pcur;
		}
		pcur=pcur->next;
	}
	//没找到
	return NULL;
}
void SLNodeInsert(SLNode** pphead, SLNode* pos, SLNodeDataType x)
{
	assert(pphead);
	assert(pos);
	//链表不为空
	assert(*pphead);
	SLNode* pnewnode = SLNodeBuyNode(x);
	//头节点插入
	if (pos == *pphead)
	{
		SLNodePushFront(pphead,x);
		return;
	}
	//其他节点

	SLNode* prev = *pphead;
	while (prev->next!=pos)
	{
		prev = prev->next;
	}
	prev->next = pnewnode;
	pnewnode->next = pos;
}
void SLNodeErase(SLNode** pphead, SLNode* pos)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);

	if (*pphead == pos)
	{  
		SLNodePopFront(pphead);
		return;
	}
	SLNode* prev= *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	SLNode* pnext = pos->next;
	pos->next = NULL;
	free(pos);
	pos = NULL;
	prev -> next = pnext;
}

void SLNodeInsertAfter(SLNode** pphead, SLNode* pos, SLNodeDataType x)
{
	
	assert(pphead);
	assert(pos);
	SLNode* pnewnode = SLNodeBuyNode(x);
	SLNode* pnext = pos->next;
	pos->next = pnewnode;
	pnewnode->next = pnext;


}
void SLNodeEraseAfter(SLNode** pphead, SLNode* pos)
{

	assert(pphead);
	assert(pos);
	assert(pos->next);
	//pos pnext pnextnext
	SLNode* pnext = pos->next;
	SLNode* pnextnext = pnext->next;
	pos->next = pnextnext;
	pnext->next = NULL;
	free(pnext);
	pnext = NULL;

}

void SListDestroy(SLNode** pphead)
{
	assert(pphead);
	assert(*pphead);

	SLNode* pcur = *pphead;
	while (pcur)
	{
		SLNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

测试test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Single List.h"



int main()
{
	SLNode* plist = NULL;
	SLNodePushBack(&plist,1);
	SLNodePushBack(&plist,2);
	SLNodePushBack(&plist,3);
	SLNodePushBack(&plist,4);
	SLNodePushBack(&plist,5);

	SLNodePrint(&plist);
	SLNodePushFront(&plist, 100);
	SLNodePushFront(&plist, 200);
	SLNodePushFront(&plist, 300);
	SLNodePushFront(&plist, 400);
	SLNodePrint(&plist);
	SLNodePopBack(&plist);
	SLNodePopBack(&plist);



	SLNodePrint(&plist);
	SLNodePopFront(&plist);
	SLNodePopFront(&plist);
	SLNodePopFront(&plist);


	SLNodePrint(&plist);
	SLNode* findinex = SLNodeFind(&plist,100 );
	if (findinex)
	{
		printf("找到了\n");
	}
	else
	{
		printf("未找到\n");
	}
	SLNodeInsert(&plist,findinex,1000);
	SLNodePrint(&plist);
	SLNodeErase(&plist,findinex);
	SLNodePrint(&plist);
	SLNode* findinex2 = SLNodeFind(&plist, 1000);
	if (findinex2)
	{
		printf("找到了\n");
	}
	else
	{
		printf("未找到\n");
	}
	//SLNodeErase(&plist, findinex2);
	SLNodePrint(&plist);
	SLNodeInsertAfter(&plist, findinex2, 666);
	SLNodePrint(&plist);
	SLNode* findinex3 = SLNodeFind(&plist,1000);
	if (findinex3)
	{
		printf("找到了\n");
	}
	else
	{
		printf("未找到\n");
	}
	SLNodeEraseAfter(&plist, findinex3);
	SLNodePrint(&plist);
	return 0;
	SListDestroy(&plist);
}

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助

欢迎各位点赞,收藏和关注哦

如果有疑问或有不同见解,欢迎在评论区留言哦

后续我会一直分享双一流211西北大学本科生我自己的软件学习过程(C,数据结构,C++,Linux,MySQL)的学习干货以

及重要代码的分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一码归—码

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

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

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

打赏作者

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

抵扣说明:

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

余额充值