一、删除单链表中元素值等于x的第一个结点
1、思路
2、代码:
/// @brief 删除链表中元素值为x的第一个结点
/// @param plist 链表指针
/// @param x 待删元素
/// @return 返回是否删除成功的标志
/// @retval ERROR(0):链表不存在,不可操作
/// @retval FALSE(0):找不到x元素结点,删除操作失败
status xxx_removeX(myLinkList* plist, linkType x)
{
if (plist == NULL)
{
return ERROR;
}
return xxx_removeX_(plist->phead, x);
}
status xxx_removeX_(myLNode* phead, linkType x)
{
if (phead == NULL || phead->pnext == NULL)
{
return ERROR;
}
myLNode* p = phead->pnext;
myLNode* pre = phead;
while (p != NULL && x != p->data)
{
pre = p;
p = p->pnext;
}
/// 若p==NULL,说明遍历完链表仍未找到x结点,跳出循环
if (p == NULL)
{
return FALSE;
}
pre->pnext = p->pnext;
p->pnext = NULL;
free(p);
p = NULL;
return OK;
}
二、删除元素值等于x的所有结点,方法一
1、思路
- 用指针p遍历链表,pre记录p结点前驱,用计数器i记录被结点个数
- 当
p->data==x
时,执行删除p结点操作,每删除一个结点i自增1
- 遍历完链表,删除操作也就完成了
2、代码
/// @brief 方法1:删除链表中所有元素值为x的结点
/// @return 返回被删元素个数
/// @retval 0:删除失败
/// @retval 正整数:成功删除的结点个数
status xxx_remove_allX(myLinkList* plist, linkType x)
{
if (plist == NULL)
{
return ERROR;
}
return xxx_remove_allX_2_(plist->phead, x);
}
status xxx_remove_allX_(myLNode* phead, linkType x)
{
if (phead == NULL || phead->pnext == NULL)
{
return ERROR;
}
int i = 0;
myLNode* p = phead->pnext;
myLNode* pre = phead;
while (p != NULL)
{
/// x!=p->data,则继续遍历链表
if (x != p->data)
{
pre = p;
p = p->pnext;
continue;
}
/// 若x==p->data,则删除该结点p
pre->pnext = p->pnext;
p->pnext = NULL;
free(p);
p = pre->pnext;
++i; ///< 记录被删结点个数
}
return i;
}
三、删除元素值为x的所有结点,方法二
1、思路
- 用指针p遍历链表,找到链表中第一个x结点,令px指向该结点,pre指向px前驱
- 遍历px之后的结点,只要遇到非x结点,就将非x结点元素值与当前px结点交换值,pre,px,p均向后移动一个位置。若遇到x结点则忽略它,p向后移动 一个位置。
- 当p遍历完链表,px结点之前的结点即为所求,将pre与px断开链接,释放px及之后结点即可
2、代码
status xxx_remove_allX_1_(myLNode* phead, linkType x)
{
if (phead == NULL || phead->pnext == NULL)
{
return ERROR;
}
myLNode* px = NULL; ///< 记录链表中第一个值为x的结点
myLNode* pre = phead; ///< 记录px前驱
myLNode* p = phead->pnext; ///< 遍历指针
/// 遍历链表,直接找到第一个值为x的结点,令px指向该结点,px指向其前驱
while (p!= NULL)
{
if (p->data == x)
{
px = p;
p = p->pnext;
break;
}
pre = p;
p = p->pnext;
}
/// 若px为空,说明整个链表没有值等于x的结点,函数退出
if (px == NULL)
{
return FALSE;
}
/// 遍历px结点的后继链表,将不等于x的元素值逐个拷贝至最前边的px所指的结点
/// 循环结束后,px指向结点及所有后继结点均可被free
while (p != NULL)
{
if (p->data != x)
{
px->data = p->data; ///< 非x元素值拷贝至px结点
pre = px;
p = p->pnext;
px = px->pnext;
continue;
}
p = p->pnext;
}
/// pre为px前驱,同时也为新的结果链表的尾结点。将尾结点pnext域置空
pre->pnext = NULL;
/// 释放px及其后继结点
while (px != NULL)
{
p = px->pnext;
free(px);
px = p;
}
return OK;
}
四、删除元素值为x的所有结点
1、思路
- 设指针px恒指向链表中从头结点开始连续若干非x值结点的尾结点,px初始值指向phead
- 用px遍历链表,只要遇到x值结点只忽掉不处理,p向后移动一个位置。
- 只要遇到x值结点,则将该结点与px的后继结点交换值,px与p均向后移动一个位置
2、代码
status xxx_remove_allX_2_(myLNode* phead, linkType x)
{
if (phead == NULL || phead->pnext == NULL)
{
return ERROR;
}
myLNode* px = phead; ///< px假定指向值为x的结点
myLNode* p = phead->pnext; ///< 遍历指针
while (p != NULL)
{
/// 只要值为x,该结点不用处理,继续遍历后续结点即可
if (p->data == x)
{
p = p->pnext;
}
/// 若值不为x,将其与px所指结点交换元素值
else
{
px = px->pnext;
px->data = p->data;
p = p->pnext;
}
}
/// 将前部分值不为x的结点与后部分值为x的结点断开链接
p = px->pnext;
px->pnext = NULL;
px = p; ///< 令px指向待free结点
while (p != NULL)
{
p = p->pnext;
free(px);
px = p;
}
return OK;
}