C/C++数据结构与算法——线性表之单链表 代码+注释

单链表 C语言代码+注释 如果对你有帮助:点赞+收藏+评论+关注~ 感谢!欢迎各位与博主友好讨论! 


 单链表相比顺序表优点:用指针将各个结点串在一起。

单链表缺点:查找任意位置的结点地址时很麻烦。

 

头文件 S.h

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

typedef int SLTDataType;

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;//指针
}SLTNode;

//打印
void SlistPrint(SLTNode* phead);
//创建空间
SLTNode* CreatSListNode(SLTDataType x);
//尾插
void SListPushBack(SLTNode**pphead, SLTDataType x);
//头插
void SListPushFront(SLTNode** pphead, SLTDataType x);
//尾删
void SListPopBack(SLTNode** pphead);
//头删
void SListPopFront(SLTNode** pphead);
//查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x);
//任意的pos节点前面插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//任意pos节点删除
void SListErase(SLTNode** pphead, SLTNode* pos);

 

函数实现 S.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include "S.h"

//打印
void SlistPrint(SLTNode* phead)
{
	SLTNode* current = phead;
	while (current != NULL)
	{
		printf("%d -> ", current->data);
		current = current->next;
	}
	printf("NULL\n\n");
}

//开辟空间
SLTNode* CreatSListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

//尾插
void SListPushBack(SLTNode** pphead, SLTDataType x)
//(SLTNode*phead, ) pphead是phead(plist)的地址,*pphead是phead的内容
{
	/*SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->data = x;
	newnode->next = NULL;*/
	SLTNode* newnode=CreatSListNode(x);

	if (*pphead == NULL)//phead==NULL
	{
		*pphead = newnode;
	}
	else
	{//找尾节点的指针
		SLTNode* tail = *pphead;

		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		//尾结点,链接新节点
		tail->next = newnode;
	}
}

//头插
void SListPushFront(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = CreatSListNode(x);
	newnode->next = *pphead;//先前头结点的地址放入现在新的头结点
	*pphead = newnode;//把新的第一个结点地址给phead
}

//尾删
void SListPopBack(SLTNode** pphead)
{
	//1.空链表,就别删了
	if (*pphead == NULL)
	{
		return ;
	}
	//2.只有一个结点,注意空指针
	else if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	//3.一个以上结点
	else
	{
		SLTNode* prev = NULL;
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		prev->next = NULL;
	}
}

//头删
void SListPopFront(SLTNode** pphead)
{
	SLTNode* next = (*pphead)->next;//把第二个结点的地址给保存起来
	//如果直接释放,不保存下一个的地址的话:头结点里还保存着下一个节点地址,这样就会找不到第二个结点了
	free(*pphead);//释放第一个结点
	*pphead = next;//把保存好的第二个结点的地址放入定义的头指针
}

//查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* current = phead;
	while (current != NULL)
	{
		if (current->data == x)
		{
			return current;
		}
		current = current->next;
	}

	return NULL;
}

//任意的pos节点前面插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	SLTNode* newnode = CreatSListNode(x);
	if (pos == *pphead)//只有一个结点
	{
		SListPushFront(pphead, x);//就当做头插
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;
	}
}

//任意pos节点删除
void SListErase(SLTNode** pphead, SLTNode* pos)
{
	if (pos == *pphead)
	{
		SListPopFront(pphead);//当只有一个结点,没有前一个结点,使用头删
	}
	SLTNode* prev = *pphead;//prev是pos的前一个结点
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = pos->next;
	free(pos);
}

 

 测试 test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "S.h"

void TestSlist1()
{
	SLTNode* plist = NULL;//第一个节点指针置为空
	SListPushBack(&plist, 1); //实参传递地址,改变形参才会改变实参
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 4);
	SListPushFront(&plist, 0);
	SlistPrint(plist);

	//SListPopFront(&plist);
	//SListPopFront(&plist);
	//SListPopFront(&plist);
	//SListPopFront(&plist);
	SListPopFront(&plist);
	//SlistPrint(plist);
	//
	//SListPopBack(&plist);
	//SlistPrint(plist);

	//在2前面插入20
	SLTNode* pos = SListFind(plist,2);
	if (pos)
	{
		SListInsert(&plist,pos,20);
	}
	SlistPrint(plist);	

	pos = SListFind(plist, 20);
	if (pos)
	{
		SListErase(&plist, pos);
	}
	SlistPrint(plist);
}

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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值