博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

DS-单链表:删除指定元素值x的结点

Posted on 2023-02-16 01:20  乔55  阅读(78)  评论(0编辑  收藏  举报

一、删除单链表中元素值等于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;
}