【数据结构基础_有空头单向链表_(C语言实现)】

有空头单向链表_(C语言实现)

本文主要是针对(含空头)单向链表进行增、删、改、查操作

创建一个结构体当做节点
struct Node
{
	int iData;
	struct Node* pNext;
};

定义空头指针

//空头
struct Node stHead = { 0,NULL };

空头不参加任何增、删,

增加:1.尾添加

此处和之前无空头链表操作只有稍微差别,咱们这次就不要尾指针了(当然你也可以尝试添加空的尾指针也是可以的),记住一定要先连后断

//尾添加
void AddToTail(struct Node* stHead, int iData)
{
	//参数合法性检测
	if (NULL == stHead)
		return;
	//申请节点
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	if (pTemp == NULL)
		return;
	//空间赋值
	pTemp->iData = iData;
	pTemp->pNext = NULL;
	//节点连到链表
	struct Node* pT = stHead;
	//循环找到尾巴
	while (pT->pNext != NULL)
		pT = pT->pNext;
	pT->pNext = pTemp;
	//计数器++
	//(*iNodeCount)++;
	(stHead->iData)++;
}
增加:2.头添加
//头添加
void AddToHead(struct Node* stHead, int iData)
{
	//参数合法性检测
	if (NULL == stHead)
		return;
	//申请节点
	struct Node* pTemp = (struct Node*)malloc(sizeof(struct Node));
	if (pTemp == NULL)
		return;
	//空间赋值
	pTemp->iData = iData;
	pTemp->pNext = NULL;
	//链接链表
	pTemp->pNext = stHead->pNext;
	stHead->pNext = pTemp;
	//计数器++
	(stHead->iData)++;
}

此时咱们链表的最简单的两个添加,已经完成,我们可以遍历链表来查看,并且释放链表

遍历链表
//遍历链表
void Look(struct Node stHead)
{
	struct Node* pTemp = stHead.pNext;
	printf("共有 %d 个数据: ", stHead.iData);
	while (pTemp != NULL)
	{
		printf("%d  ", pTemp->iData);
		pTemp = pTemp->pNext;
	}
	putchar('\n');
}
释放链表
//释放链表
void FreeList(struct Node* stHead)
{
	//参数合法性检测
	if (NULL == stHead || 0 >= stHead->iData)
		return;
	struct Node* pTemp = stHead->pNext;
	if (pTemp == NULL)
		return;
	while (pTemp != NULL)
	{
		//记录当前节点
		struct Node* pT = NULL;
		if (pT== NULL)
			return;
		pT = pTemp;
		//节点下移
		pTemp = pTemp->pNext;
		//释放记录节点
		free(pT);
	}
	//对应数据置NULL
	stHead->pNext = NULL;
	//*iNodeCount = 0;
	stHead->iData = 0;
}

释放链表记得指针要置空哈

查找:1.根据下标查询
//根据下标查找节点
struct Node* FindNodeByIndex(struct Node* stHead, int iIndex)
{
	if (NULL == stHead || stHead->iData <= 0 || iIndex < 0 || iIndex > (stHead->iData) - 1)
		return NULL;
	struct Node* pTemp = stHead->pNext;
	for (int i = 0; i < iIndex; i++)
		pTemp = pTemp->pNext;
	return pTemp;
}
查找:2.根据数值查询
struct Node* FindNodeByData(struct Node* stHead, int iData)
{
	if (NULL == stHead || stHead->iData <= 0)
		return NULL;
	struct Node* pTemp = stHead->pNext;
	while (pTemp != NULL)
	{
		if (pTemp->iData == iData)
			break;
		pTemp = pTemp->pNext;
	}
	return pTemp;
}
升级版添加:1.在指定下标节点处添加节点
void AddByIndex(struct Node* stHead, int iPosIndex, int iIndex)
{
	//参数合法性检测
	if (NULL == stHead || iPosIndex > stHead->iData || iPosIndex < 0)
		return;
	//循环找位置
	struct Node* pTemp = stHead;
	for (int i = 0; i < iPosIndex; i++)
	{
		pTemp = pTemp->pNext;
	}
	//找到了 并添加
	AddToHead(pTemp, iIndex);
	pTemp->iData -= 1;
	stHead->iData += 1;
}
升级版添加:2.在指定数值添加一个或者多个节点

看着很高大上,其实你只需要调用头添加即可,此时的头非彼头;

//指定数据后面添加一个节点
void AddBehandData(struct Node* stHead, int iPosData, int iData)
{
	//参数合法性检测
	if (NULL == stHead)
		return;
	//遍历 找节点
	struct Node* pTemp = stHead->pNext;
	while (pTemp != NULL)
	{
		if (pTemp->iData == iPosData)
			break;
		pTemp = pTemp->pNext;
	}
	//判断是否找到
	if (NULL == pTemp)
		printf("查无此数据");
	else
	{
		AddToHead(pTemp, iData);
		pTemp->iData -= 1;
		stHead->iData += 1;
	}
}
//指定下标位置添加 n 个节点
void AddBySomeIndex(struct Node* stHead, int iPosIndex, int iCount, int iData)
{
	//参数合法性检测
	if (NULL == stHead || iPosIndex > stHead->iData || iPosIndex < 0)
		return;
	//循环找位置
	struct Node* pTemp = stHead;
	for (int i = 0; i < iPosIndex; i++)
	{
		pTemp = pTemp->pNext;
	}
	//找到了 并添加
	//循环插入
	for (int i = 0; i < iCount; i++)
	{
		AddToHead(pTemp, iData);
		pTemp->iData -= 1;
		stHead->iData += 1;
	}
}
修改:1.根据数值改变此节点数据
void ChangeByData(struct Node stHead, int iData, int iValue)
{
	if (stHead.iData <= 0)
		return;
	//循环找到对应下标位置
	struct Node* pTemp = stHead.pNext;
	for (int i = 0; i < stHead.iData; i++)
	{
		if (pTemp->iData == iData)
		{
			//修改数据
			pTemp->iData = iValue;
		}
		pTemp = pTemp->pNext;	
	}
}
修改:2.根据下标改变此节点
//根据下标修改修改节点的值
void ChangeByIndex(struct Node stHead, int iIndex, int iValue)
{
	if (stHead.iData <= 0 || iIndex < 0 || iIndex >stHead.iData - 1)
		return;
	//循环找到对应下标位置
	struct Node* pTemp = stHead.pNext;
	for (int i = 0; i < iIndex; i++)
		pTemp = pTemp->pNext;
	//修改数据
	pTemp->iData = iValue;
}
删除:1.删除指定下标节点
void DeleteByIndex(struct Node* stHead, int iIndex)
{
	//参数合法性检测
	if (NULL == stHead || iIndex < 0 || iIndex > stHead->iData - 1)
		return;
	//循环定位指定下标的前一个节点
	struct Node* pTemp = stHead;
	for (int i = 0; i < iIndex; i++)
	{
		pTemp = pTemp->pNext;
	}
	//节点扣下来
	struct Node* pT = pTemp->pNext;
	//链表重新连接
	pTemp->pNext = pT->pNext;
	//释放原节点
	free(pT);
	//节点数 -1
	stHead->iData -= 1;
}
删除:2.删除指定数据节点
void DeleteByValue(struct Node* stHead, int iValue)
{
	// 参数合法性检测
	if (NULL == stHead || stHead->iData < 0)
		return;
	//循环定位指定数据的前一个节点
	struct Node* pTemp = stHead;
	if (pTemp == NULL)
		return;
	while (pTemp->pNext != NULL)
	{
		if (pTemp->pNext == NULL)
			return;
		if (pTemp->pNext->iData == iValue)
		{
			//记录被删除的节点
			struct Node* pT = NULL;
			if (pT == NULL)
				return;
			pT = pTemp->pNext;
			//链表重新连接
			pTemp->pNext = pT->pNext;
			//释放原节点
			free(pT);
			//节点数 -1
			stHead->iData -= 1;
			continue;
		}
		pTemp = pTemp->pNext;
	}
}
删除:3.根据数值删除此节点(只删除一个哟)
struct Node* DeleteOneDataByData(struct Node** pHead, struct Node** pEnd, int iData)
{
	if (NULL == *pHead)
		return NULL;
	if ((*pHead)->iData == iData)
	{
		DeleteHead(pHead, pEnd);
		return *pHead;
	}
	else if ((*pEnd)->iData == iData)
	{
		DeleteEnd(pHead, pEnd);
		return *pHead;
	}
	else
	{
		//循环找节点
		struct Node* pTemp = *pHead;
		while (pTemp->pNext != NULL)
		{
			if (pTemp->pNext->iData == iData)
				break;
			pTemp = pTemp->pNext;
		}
		//判断
		if (pTemp->pNext != NULL)
		{
			struct Node* pT = pTemp->pNext; //记录
			pTemp->pNext = pT->pNext;
			free(pT);
			return *pHead;   //return pTemp->pNext  ----- pHead
		}
		else
		{
			printf("查无此节点\n");
			return NULL;
		}
	}
}

下面是一个简单对链表去除重复元素的操作,主要通过两个指针(内指针和外指针),遍历链表,找到重复的直接删除,并连接上下一个节点即可。

(1)去重
void DeleteSome(struct Node* stHead)
{
	if (NULL == stHead || stHead->iData <= 1)
		return;
	//循环遍历
	struct Node* pWai = stHead->pNext;
	if (NULL == pWai)
		return;
	while (pWai != NULL)
	{
		//跟后面的节点进行比较
		struct Node* pNei = NULL;
		if (NULL == pNei)
			return;
		pNei = pWai;
		while (pNei->pNext != NULL)
		{
			if (pWai->iData == pNei->pNext->iData)
			{
				//删除节点
				//1.记录节点
				struct Node* pTemp = pNei->pNext;
				//2.原位置进行新的链接
				pNei->pNext = pTemp->pNext;
				//3.释放节点
				free(pTemp);
				//4.节点数--
				stHead->iData -= 1;
				continue;
			}
			pNei = pNei->pNext;
		}

		pWai = pWai->pNext;
	}
}

此时有空头的单向链表基本操作已经完成咯~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

千北@

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

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

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

打赏作者

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

抵扣说明:

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

余额充值