数据结构——修改单向链表有空头(八)
这里将前节点放在 pWai,后节点放在pNei,设置两个循环,pNei放在内循环,先将第一个节点放在pWai,然后在内循环中判断前节点与后面的节点数据是否重复,有重复的就删除,没有了就进入下一个外循环pWai向后移一位。下标的范围0~stHead.iData,循环定位指定下标前一个节点-->记录,将指定节点扣下来,让前一个节点指向指定节点的下一个节点,然后就可以删除指定节点。void Delete
一、修改指定节点
1、修改指定下标节点
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;
}
下标的范围0~stHead.iData - 1,这里跟下标插入不同,插入可以插在尾部。找到相应下标的节点,修改节点数据。
调用ChangeByIndex(stHead,1, 22):

2、修改指定节点数据
void ChangeByData(struct Node stHead, int iData, int iValue)//修改指定节点数据
{
if (stHead.iData <= 0)
return;
//遍历
struct Node* pTemp = stHead.pNext;
while (pTemp != NULL)
{
if (pTemp->iData == iData)
pTemp->iData = iValue;
pTemp = pTemp->pNext;
}
}
遍历链表,找到了直接在循环中修改。
调用ChangeByData(stHead, 3, 33):

二、删除指定节点
1、删除指定下标节点
void DeleteByIndex(struct Node* stHead, int iIndex)//删除指定下标节点
{
//参数合法性检测
if (NULL == stHead || iIndex < 0 || iIndex > stHead->iData)
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);
//节点数减一
stHead->iData--;
}
下标的范围0~stHead.iData,循环定位指定下标前一个节点-->记录,将指定节点扣下来,让前一个节点指向指定节点的下一个节点,然后就可以删除指定节点。
调用DeleteByIndex(&stHead,1):

2、删除全部指定数据节点
void DeleteByData(struct Node* stHead, int iValue)//删除全部指定数据节点
{
//参数合法性检测
if (NULL == stHead || stHead->iData < 0)
return;
//循环链表
struct Node* pTemp = stHead;
while (pTemp->pNext != NULL)
{
if (pTemp->pNext->iData == iValue)
{
//指定节点扣下来
struct Node* pT = pTemp->pNext;
//链表重新链接
pTemp->pNext = pT->pNext;
//删除原节点
free(pT);
pT = NULL;
//节点数减一
stHead->iData--;
continue;//直接跳到判断
}
pTemp = pTemp->pNext;
}
}
在C语言中,continue是一种流程控制语句,用于跳过当前循环体中剩余的代码,直接进入下一次循环的条件判断部分。它仅适用于for、while和do-while循环结构。在这个函数块中 continue让程序直接跳到if。这个函数的逻辑是,遍历链表-->判断节点是否为指定的数据节点,如果是就删除并直接判断被删除节点的下一个节点,如果不是就进行下一个循环,这样重复直到链表被遍历完。
调用DeleteByData(&stHead,1):

3、去除重复的节点
void DeleteSame(struct Node* stHead)//去重
{
//参数合法性检测
if (NULL == stHead)
return;
//循环遍历
struct Node* pWai = stHead->pNext;
while (pWai != NULL)
{
//跟后面的节点进行比较
struct Node* pNei = pWai;
while (pNei->pNext != NULL)
{
if (pWai->iData == pNei->pNext->iData)
{
//记录原节点
struct Node* pTemp = pNei->pNext;
//原位置进行新的链接
pNei->pNext = pTemp->pNext;
//释放节点
free(pTemp);
//节点数--
stHead->iData--;
continue;
}
pNei = pNei->pNext;
}
pWai = pWai->pNext;
}
}
这里将前节点放在 pWai,后节点放在pNei,设置两个循环,pNei放在内循环,先将第一个节点放在pWai,然后在内循环中判断前节点与后面的节点数据是否重复,有重复的就删除,没有了就进入下一个外循环pWai向后移一位。
调用DeleteSame(stHead):

三、释放链表
释放链表是指将链表占用的内存空间全部归还给系统,防止内存泄漏。
void FreeList(struct Node* stHead)//释放链表
{
if (NULL == stHead || stHead->iData <= 0)
return;
struct Node* pTemp = stHead->pNext;
while (pTemp != NULL)
{
//记录当前节点
struct Node* pT = pTemp;
//节点下移
pTemp = pTemp->pNext;
//释放记录
free(pT);
}
//对应数据置NULL
stHead->pNext = NULL;
stHead->iData = 0;
}
用pT记录当前节点,以方便节点下移,所有节点释放完毕后,需要将空头重置为初始状态。空头作为链表的哨兵节点,本身不存储实际数据,因此不需要进行内存释放操作。
更多推荐
所有评论(0)