一、修改指定节点

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是一种流程控制语句,用于跳过当前循环体中剩余的代码,直接进入下一次循环的条件判断部分。它仅适用于forwhiledo-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记录当前节点,以方便节点下移,所有节点释放完毕后,需要将空头重置为初始状态。空头作为链表的哨兵节点,本身不存储实际数据,因此不需要进行内存释放操作。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐