C语言实现单链表的增删查改算法

博客提及了SList.c、SList.h和main.c文件,结合标签可知,这些文件可能与C语言的数据结构和算法相关。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SList.c

#include"singlist.h"

SLTNode* BuyListNode(SLDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//扩容
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;//把插入的元素赋值newnode
	newnode->next = NULL;//把插入的数的next至NULL
	return newnode;
}

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->",cur->data);
		cur = cur->next;//打印完让其指向下一个元素,直到找到NULL,打印完
	}
	printf("NULL\n");
}

void SListPushBack(SLTNode** pphead, SLDataType x)//因为要改变pphead的值因此要传二级指针
{
	assert(pphead);
	SLTNode* newnode=BuyListNode(x);
	if (*pphead == NULL)//头为空
	{
		*pphead = newnode;//只有头为空时,才需要改变
	}
	else//头不为空,则找到尾节点
	{
		//找到尾节点
		SLTNode* tail = *pphead;
		while (tail->next != NULL)//找到NULL,即找到最后一个数据
		{
			tail = tail->next;//把第一个next给下一个tail
		}
		tail->next = newnode;//把尾元素的next指向插入元素的data
	}
}

void SListPushFront(SLTNode** pphead, SLDataType x)//因为要改变pphead的值因此要传二级指针
{
	assert(pphead);
	SLTNode* newnode = BuyListNode(x);//创建一个新的节点
	newnode->next = *pphead;//把新节点的next指向旧头节点
	*pphead = newnode;//把头节点指向新的头节点
}

void SListPopFront(SLTNode** pphead)//头删
{
	assert(pphead);
	assert(*pphead != NULL);
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

void SListPophBack(SLTNode** pphead)//尾删
{
	assert(pphead);
	assert(*pphead != NULL);//1.一个节点
	if ((*pphead)->next == NULL)//2.二个节点
	{
		free(*pphead);
		*pphead = NULL;
	}
	else //3.二个以上的节点
	{
		SLTNode* prev = NULL;//记录上一个节点,为了防止无法找到上一个节点
		SLTNode* tail = *pphead;//记录第二个节点
		while (tail->next)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail->next);//释放最后一个节点
		tail = NULL;//最后一个节点至NULL
		prev->next = NULL;//最后一个节点的上一个节点也至NULL
	}
}

SLTNode* SListFind(SLTNode* phead, SLDataType x)//找到了也可以修改其值, 这就是为什么要传址
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
	return NULL;
}


void SListInsertAfter(SLTNode* pos, SLDataType x)//在pos后插入,更适合单链表
{
	assert(pos);
	SLTNode* newnode = BuyListNode(x);
	newnode->next = pos->next;//先把下一个节点记录,为了防止找不到
	pos->next = newnode;
}
void SListInsert(SLTNode** pphead, SLTNode* pos, SLDataType x)
{
	assert(pphead);
	assert(pos);

	SLTNode* newnode = BuyListNode(x);
	if (*pphead == pos)//如果插入的为头节点
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else//插入不是头节点
	{
		SLTNode* posPrev = *pphead;//posPrev记录前一个节点
		while (posPrev->next != pos)
		{
			posPrev = posPrev->next;
		}
		posPrev->next = newnode;
		newnode->next = pos;
	}
}

void SListEraseAfter(SLTNode* pos)//删除pos后一个位置
{
	assert(pos->next!=NULL);
	SLTNode* next = pos->next;
	pos->next = next->next;
	free(next);
	next = NULL;//至空不至空都行
}
void SListErase(SLTNode** pphead, SLTNode* pos)//删除前一个位置
{
	assert(pphead);
	assert(pos);

	if (*pphead == pos)//如果删除的为头节点
	{
		SListPopFront(pphead);
	}
	else//删除不是头节点
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}
//void SListErase(SLTNode** pphead, SLTNode* pos)//删除前一个位置
//{
//  assert(pphead);
//	assert(pos);
// 
//	SLTNode* cur = *pphead;
//	if (*pphead == pos)//如果删除的为头节点
//	{
//		cur = (*pphead)->next;
//		free(*pphead);
//		*pphead = cur;
//	}
//	else//删除不是头节点
//	{
//		SLTNode* posPrev = *pphead;
//		while (posPrev->next != pos)
//		{
//			posPrev = posPrev->next;
//		}
//		posPrev->next = posPrev->next->next;
//		free(pos);
//	}
//}

void SListDestory(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);	
		cur = next;
	}
	*pphead = NULL;
}

SList.h

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

typedef int SLDataType;

typedef struct SListNode
{
	SLDataType data;//数据
	struct SListNode* next;//指向下一个数的结点
}SLTNode;

void SListPrint(SLTNode* phead);
void SListPushBack(SLTNode** pphead,SLDataType x);//尾插
void SListPushFront(SLTNode** pphead, SLDataType x);//头插
void SListPopFront(SLTNode** pphead);//头删
void SListPophBack(SLTNode** pphead);//尾删

SLTNode* SListFind(SLTNode* phead, SLDataType x);//查找
void SListInsertAfter(SLTNode* pos, SLDataType x);//在pos后位置插入
void SListInsert(SLTNode** pphead,SLTNode* pos,SLDataType x);//在pos前插入
void SListEraseAfter(SLTNode* pos);//把pos后删除
void SListErase(SLTNode** pphead, SLTNode* pos);//把pos前删除
void SListDestory(SLTNode** pphead);//销毁表

main.c

#include"singlist.h"

void TestList1()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);//尾插
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPrint(plist);

	//SListPophBack(&plist);
	//SListPophBack(&plist);
	//SListPophBack(&plist);
	//SListPophBack(&plist);
	//SListPrint(plist);

	//SListPushFront(&plist, 1);//头插
	//SListPushFront(&plist, 2); 
	//SListPushFront(&plist, 3);
	//SListPrint(plist);

	SListPopFront(&plist);
	SListPopFront(&plist);
	SListPopFront(&plist);
	SListPrint(plist);
}

void TestList2()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);//尾插
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPrint(plist);

	//找到有几个x
	SLTNode* pos = SListFind(plist,2);
	int i = 1;
	while (pos)
	{
		printf("第%d个节点:%p->%d\n",i++,pos,pos->data);
		pos = SListFind(pos->next,2);
	}
	
	//找到了也可以修改其值,这就是为什么要传址
	pos = SListFind(plist,3);
	if (pos)
	{
		pos->data = 30;
	}
	SListPrint(plist);
}

void TestList3()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);//尾插
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPrint(plist);

	//找到了,在3的位置前插入30
	SLTNode* pos = SListFind(plist,3);
	if (pos)
	{
		SListInsert(&plist,pos,30);
	}
	SListPrint(plist);

	 pos = SListFind(plist, 1);//在头节点插入
	if (pos)
	{
		SListInsert(&plist, pos, 40);
	}
	SListPrint(plist);
}

void TestList4()
{
	SLTNode* plist = NULL;
	SListPushBack(&plist, 1);//尾插
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);
	SListPrint(plist);

	//找到了,在3的位置前插入30
	SLTNode* pos = SListFind(plist, 2);
	if (pos)
	{
		SListErase(&plist, pos);
	}
	SListPrint(plist);

}

int main()//单链表
{
	//TestList1();
	//TestList2();
	//TestList3();
	TestList4();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值