C语言数据结构-单链表

链表的概念

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
下面开始单链表
在这里插入图片描述
先创建一个结构体

typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType data;
	struct SListNode* next;
}SListNode;

动态申请结点

SListNode* BuySListNode(SLTDateType x)
{
	SListNode* node = (SListNode*)malloc(sizeof(SListNode));
	//判断开辟节点是否成功
	if (node == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	node->data = x;
	node->next = NULL;
	return node;
}

单链表的尾插

怎么尾插呢?
尾插的思想:
1.常规尾插:给个plist指针指向头结点,通过plist指针找到后面的结点。在定义一个tail指针找到尾结点,让尾节点指向新结点
2.链表为空,先指向新结点,在进行尾插
在这里插入图片描述

在将图的思路转换成代码

void SListPushBack(SListNode** pplist, SLTDateType x)
{
	assert(pplist);//地址不能为空
	//链表为空
	if (*pplist==NULL)
	{
		SListNode* newnode = BuySListNode(x);
		*pplist = newnode;
	}
	else
	{
		SListNode* tail = *pplist;
		//找尾
		while (tail->next !=NULL)
		{
			tail = tail->next;
		}
		SListNode* newnode = BuySListNode(x);
		tail->next = newnode;
	}
}
```c
//测试代码
void test()
{
	SListNode *plist = NULL;
	SListPushBack(&plist, 1);
	SListPushBack(&plist, 2);
	SListPushBack(&plist, 3);

在这里插入图片描述
这是单链表的尾插。

单链表的头插

在这里插入图片描述

// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{
	assert(pplist);
	SListNode* newnode = BuySListNode(x);
   //pplist存plist的地址,解引用找到plist
	newnode->next = *pplist;
	*pplist = newnode;
}
	SListPushFront(&plist, -1);
	SListPrint(plist);

在这里插入图片描述
头插就成功了。

单链表的尾删

在这里插入图片描述
尾删的思路:
定义一个tail指针,找到尾。直接判断tail->next是不是为空,为空就结束循环。我们直接释放tail->next->next,在把tail->next=NULL.还有一个结点的情况,释放然后置空就可以了。

void SListPopBack(SListNode** pplist)
{
	assert(pplist);
	assert(*pplist);//链表为空不能尾删
	if ((*pplist)->next==NULL)
	{
		free(*pplist);
		*pplist = NULL;
	}
	else
	{
		SListNode* tail = *pplist;
		while (tail->next->next)
		{
			tail = tail->next;
		}
		free(tail->next->next);
		tail->next = NULL;
	}
}

测试一下

	SListPopBack(&plist);
	SListPopBack(&plist);
	SListPrint(plist);

在这里插入图片描述

单链表的头删

在这里插入图片描述
头删:定义一个next指针先保存d1->next,在让plist指向d2,如果不保存就先释放d1就找不到d2了。

void SListPopFront(SListNode** pplist)
{
	assert(pplist);
	assert(*pplist);//链表为空就不能删了
	SListNode* next = (*pplist)->next;
	
	free(*pplist);
	(*pplist) = next;
}
    SListPopFront(&plist);
	SListPrint(plist);

在这里插入图片描述
-1就删除成功了。

单链表的查找及修改

查找:直接遍历一遍

//单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
	SListNode *cur = plist;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
	return NULL;
}

我们找到的话就可以修改了

SListNode* pos = SListFind(plist,2);
	if (pos)
	{
		printf("找到了\n");
	}
	else
	{
		printf("没找到\n");
	}
	pos->data = 20;//修改
	SListPrint(plist);

我们找一下2,并修改为20
在这里插入图片描述

单链表在pos位置之后插入值

在这里插入图片描述
将newnode指向d3,再将pos指向newnode

void SlistInsertAfter(SListNode* pos, SLTDateType x)
{
	assert(pos);
	SListNode *newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

我们测试在3的后面插入30

    pos = SListFind(plist, 3);
	if (pos)
	{
		SlistInsertAfter(pos, 30);
	}
	SListPrint(plist);

在这里插入图片描述
就成功插入30了。

单链表在pos位置之后插入值

在这里插入图片描述
搞个next来保存pos->next->next,在释放掉next.

void SlistEraseAfter(SListNode* pos)
{
	assert(pos);
	SListNode *next = pos->next;
	pos->next = next->next;
	free(next);
	next = NULL;
}

测试一下把1后的删除

pos = SListFind(plist, 1);
	if (pos)
	{
		SListEraseAfter(pos);
	}
	SListPrint(plist);

在这里插入图片描述
之前的20就删除成了。
本篇的单链表就结束了!
在这里插入图片描述

单链表是一种常见的数据结构,它由一个或多个节点组成,每个节点包含一个数据域和一个指针域,指针域指向下一个节点。 实现单链表的查找位序算法函数需要以下步骤: 1. 定义一个指针p指向链表的头节点,并定义一个变量count,用于计数。 2. 从头节点开始,遍历链表,当p指向某个节点时,计数器count加1。 3. 如果p指向的节点的数据与目标数据相等,则返回当前的计数器count,即为目标数据的位序。 4. 如果p指向的节点不是目标数据,则将p指向下一个节点,重复步骤3。 5. 如果遍历完链表后仍未找到目标数据,则返回-1,表示未找到。 下面是C语言实现单链表查找位序算法函数的代码示例: ```c #include <stdio.h> #include <stdlib.h> // 定义单链表节点结构 typedef struct Node { int data; // 数据域 struct Node* next; // 指针域 } Node; // 查找位序的算法函数 int findPosition(Node* head, int target) { Node* p = head; // 指向头节点 int count = 0; // 计数器初始化为0 while (p != NULL) { count++; // 计数器加1 if (p->data == target) { return count; // 找到目标数据,返回当前计数器的值 } p = p->next; // 指向下一个节点 } return -1; // 遍历完链表未找到目标数据,返回-1 } int main() { // 创建链表 Node* head = (Node*)malloc(sizeof(Node)); head->data = 1; // 头节点数据为1 Node* node1 = (Node*)malloc(sizeof(Node)); node1->data = 2; Node* node2 = (Node*)malloc(sizeof(Node)); node2->data = 3; head->next = node1; node1->next = node2; node2->next = NULL; // 查找位序示例 int target = 3; // 目标数据为3 int position = findPosition(head, target); if (position != -1) { printf("目标数据 %d 的位序为 %d\n", target, position); } else { printf("未找到目标数据 %d\n", target); } // 释放链表内存 free(node2); free(node1); free(head); return 0; } ``` 在上述代码中,我们首先定义了一个指向头节点的指针p和一个计数器count,然后使用while循环遍历链表。当p指向某个节点时,计数器加1,并判断该节点的数据是否与目标数据相等。如果找到了目标数据,则返回当前计数器的值,即为目标数据的位序。如果遍历完链表仍未找到目标数据,则返回-1表示未找到。最后在主函数中演示了调用该算法函数的示例。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_End丶断弦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值