删除 / 插入无头单链表的非尾节点(不能遍历链表)


单链表的结构
typedef int DataType;
typedef struct Node
{
    DataType _data;
    struct Node* _next;
}Node, *PNode;
单链表的尾插操作
void SListPushBack(PNode* pHead, DataType data)
{
    PNode _new = NULL;
    // 参数检验
    assert(pHead);

    _new = BuyNewNode(data);
    if (NULL == _new)
    {
        return;
    }
    else
    {
        if (NULL == (*pHead))
        {
            *pHead = _new;
        }
        else
        {
            PNode pCur = NULL;
            pCur = (*pHead);

            while (!(pCur->_next == NULL))
            {
                pCur = pCur->_next;
            }

            pCur->_next = _new;
        }
    }
}
查找单链表中值为data元素的位置
// 在链表中查找值为data的元素,找到后返回指向该结点的指针 
PNode SListFind(PNode pHead, DataType data)
{
    PNode pCur = NULL;

    // 参数检验
    assert(pHead);

    pCur = pHead;
    while (pCur != NULL)
    {
        if (pCur->_data == data)
        {
            return pCur;
        }
        pCur = pCur->_next;
    }

    return NULL;
}

删除无头单链表的一个非尾节点

思想:
这里写图片描述
首先明确题意,不能遍历单链表,也就是说,即使你拿到了要删除节点的指针,由单链表性质,你也没法拿到该节点的直接前驱节点,但是,虽然我没法拿到前面节点的指针,我知道链表后面的内容,于是我们巧妙的把当前要删除节点的后一个节点删除掉就可以了,在删除之前,我们要保存后一个节点的data,那很明显了,当然是用后一个节点的data覆盖要删除节点的data,然后先把链表链接起来,再把后一个节点摘下并且释放掉。
这里写图片描述
代码实现:

// 删除链表的非尾结点 要求:不能遍历链表 
void DeleteListNotTailNode(PNode pos)
{
    PNode pCur_next = pos->_next; // 记录要删除节点的下一个节点的位置
    pos->_data = pCur_next->_data; // 修改data
    pos->_next = pCur_next->_next; // 链接单链表

    free(pCur_next); // 释放空间
    pCur_next = NULL; // 养成一个好习惯 杜绝野指针
}

测试:

void TestDeleteListNotTailNode()
{
    PNode pHead = NULL;
    PNode ret_Find = NULL;
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 2);
    SListPushBack(&pHead, 3);
    SListPushBack(&pHead, 4);

    printf("postive seq:");
    PrintNode(pHead);

    ret_Find = SListFind(pHead, 2);
    DeleteListNotTailNode(ret_Find);

    printf("after delete:\n");
    printf("postive seq:");
    PrintNode(pHead);
}

int main()
{
    TestDeleteListNotTailNode();
    system("pause");
    return 0;
}

测试结果:
这里写图片描述


在无头单链表的一个节点前插入一个节点(不能遍历链表)

思想:
明白上一道题的想法,这道题就不难了
这里写图片描述
首先,我们先申请一个新节点,但是新节点里放的值是pos->data,然后我们就可以用data修改pos->_data,然后将_new这个节点链接进去,就达到我们的目的了!
这里写图片描述
实际上是在pos位置之后插入的新节点,但是值已经被交换,并不影响单链表,而且符合题意
代码实现:

// 在链表pos位置前插入值为data的结点 
void InesrtPosFront(PNode pos, DataType data)
{
    PNode _new = BuyNewNode(pos->_data);

    pos->_data = data;
    _new->_next = pos->_next;
    pos->_next = _new;
}

测试:
我们刚刚把2这个节点给删了,现在我们再插入2这个节点

void TestDeleteListNotTailNode()
{
    PNode pHead = NULL;
    PNode ret_Find = NULL;
    SListPushBack(&pHead, 1);
    SListPushBack(&pHead, 2);
    SListPushBack(&pHead, 3);
    SListPushBack(&pHead, 4);

    printf("postive seq:");
    PrintNode(pHead);

    ret_Find = SListFind(pHead, 2);
    DeleteListNotTailNode(ret_Find);

    printf("after delete:\n");
    printf("postive seq:");
    PrintNode(pHead);

    ret_Find = SListFind(pHead, 3);
    InesrtPosFront(ret_Find, 2);

    printf("after Insert:\n");
    printf("postive seq:");
    PrintNode(pHead);

}

int main()
{
    TestDeleteListNotTailNode();
    system("pause");
    return 0;
}

测试结果:
这里写图片描述


如有不正,还请指出,有劳~
如有更好的方法,欢迎指点,感谢你的浏览~

猜你喜欢

转载自blog.csdn.net/Eric_qiushui/article/details/80568184
今日推荐