关于单链表的增删查改等操作(c语言版)

目录

1、关于单链表

2.单链表的优缺点

3.单链表的初始化

4.申请新结点

5.关于单链表的插入(尾插)

6.单链表的头插

7.单链表的尾删

7.单链表的头删

8.单链表的查找

 9.在某一的数字的前面插入新数据

10.在某一结点之后插入数据

11.删除某个结点

12.打印单链表        

13.销毁单链表

完整代码如下(含菜单)

后言

1、关于单链表

        顺序表的插入删除操作需要移动大量的元素,影响了运行效率,因此引入了线性表的链式存储——单链表。单链表通过一组任意的存储单元来存储线性表中的数据元素,不需要使用地址连续的存储单元,因此它不要求在逻辑上相邻的两个元素在物理位置上也相邻。

        

2.单链表的优缺点

优点:1.按需申请空间,不用则释放,较为灵活。

           2.相较于顺序表,对于头/中部的数据插入删除操作无需移动数据。

缺点:1.每有一个数据都需要一指针链接之后的结点。

           2.不支持随机访问。

3.单链表的初始化

typedef int SListData;//重定义数据类型,便于不同类型数据的存储

typedef struct SListNode
{
	SListData data;//数据域
	SListNode* next;//指针域,存储下一结点的地址

}SListNode;

4.申请新结点

    由于对单链表插入数据时,总需要向内存动态申请一块空间存储数据及下一结点的地址,所以将的的此操作封装成函数,便于代码的简洁易读。

SListNode* BuySListNode()//申请一块空间并返回结点的指针
{
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));//动态申请内存
	if (newnode == NULL)
	{
		printf(" SListPushBack::%s", strerror(errno));
		exit(-1);//申请空间失败,错误退出
	}
	newnode->data = 0;
	newnode->next = NULL;
	return newnode;
}

  函数动作内容:动态申请内存后返回结点的指针,并将该结点的数据域初始化为零,指针域

初始化为NULL。

5.关于单链表的插入(尾插)

void SListPushBack(SListNode** pphead, int data)//单链表尾插
{
	SListNode* tail = *pphead;//将*p拷贝一份,便于可读性

	assert(pphead);//断言p不能为空,否则错误退出

	SListNode* newnode=BuySListNode();
	newnode->data = data;//完成新结点数据域的更新

	if (tail == NULL)//此时链表为空
	{
		*pphead = newnode;
	}
	else//单链表不为空
	{
		while (tail->next != NULL)//循环找到tail的指针域为空的结点
		{
			tail = tail->next;
		}
		tail->next = newnode;//将找到的tail指针域链接新申请的newnode
	}
}

        assert:断言函数,若参数为假则中断程序并报错。pphead作为二级指针,在传递参数正确时不可能为NULL,一旦发生错误,则为传参错误,便于检验 。

         尾插可分两种情况讨论,第一:单链表为空,此时直接申请一块空间作为单链表的头部,此时链表的头指针需要发生变化为新申请的结点地址,为了保存新地址,因此我们需要二级指针作为参数来记忆新地址。     第二:单链表不为空,则直接找到单链表的尾部,即指针域为NULL的结点,将新申请的newnode结点链接到单链表末尾。  

6.单链表的头插

       此操作较为简单,对于空表和有数据的单链表来说,头插只需要先将新申请的结点newnode指针域赋值于原始头指针,再将原来的头指针更新为新申请的空间即可(注意更新顺序,否则要在申请变量存储原始的头指针,防止数据的更新导致找不到原来的头结点)。

void SListPushFront(SListNode** pphead, int data)//单链表头插
{
	assert(pphead);

	SListNode* newnode = BuySListNode();//申请新结点后直接完成数据更新和链接即可
	newnode->data = data;
	newnode->next = *pphead;
	*pphead = newnode;
}

7.单链表的尾删

        单链表的尾删要考虑三种情况。

        第一:单链表为空,此时没有数据可以删除

        第二:单链表只有一个结点,此时删除节点后,头结点释放并置空,因此要传入二级指针作为参数(传值和传址的区别)来记忆数据的更新。

        第三:普通的多个结点的情况,此时只需要找到指针域为NULL的结点,但注意,我们需要的是删除最后一个结点,即倒数第二个结点的指针域需要置NULL来作为新的表尾。因此,我们需要利用定义一个指针来记住倒数第二个结点的pos。

void SListPopBack(SListNode** pphead)//单链表尾删
{
	assert(pphead);

	SListNode* tail = *pphead;
	if (tail == NULL)//表空的情况
	{
		printf("表空,无法删除\n");
		return;
	}
//  assert(*pphead);//此时采取暴力的方式,即当表空时直接报错退出程序无法删除
	else
	{
		if (tail->next == NULL)//表中只有一个结点的情况
		{
			free(*pphead);
			*pphead = NULL;
			return;
		}
		else
		{
			SListNode* cur = 0;
			while (tail->next)
			{
				cur = t
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值