链表——删除非尾结点、某个结点位置插入值为data的结点(不能遍历链表)

最近遇到这样一个题: 删除一个非尾结点pos;在pos位置插入一个值为data的新结点,要求都是不能遍历链表

对于这种类型的题,首先:找到pos这个结点,然后才是调用函数删除或者插入。

于是,首先我们应该写一个能找到pos结点的函数 PNode FindDataNode(PNode pHead, DataType data)

函数代码如下:

PNode FindDataNode(PNode pHead, DataType data)
{
    assert(pHead);             //参数检测

    PNode pCur;

    pCur = pHead;

    while (pCur)                              //遍历链表,找到值为data的结点 并且返回
    {
        if (data == pCur->_data)
            return pCur;
        pCur = pCur->_pNext;
    }

    printf("该结点不存在!!\n");                     //没找到值为data的结点  返回空
    return NULL;

}

那么如何只遍历一次就能删除pos结点呢??

思路:已知,假设找到data为2的pos结点,先将pos结点的data与其next的data交换,然后再将pos的next结点指向其next的next结点,最后再free pos结点的next结点,最终间接达到删除pos结点的效果!

已知,假设找到data为2的pos结点,先将pos结点的data与其next的data交换,然后再将pos的next结点指向其next的next结点,最后再free pos结点的next结点

代码:

    void DeleteListNotTailNode(PNode pos)
{
    assert(pos);                                           //参数检测

    if (NULL == pos)                                       //该结点为空,即没找到值为data的结点
    {
        printf("该结点不存在!\n");
        return;
    }
    if (NULL == pos->_pNext)                             //该结点为尾结点
    {
        printf("待删除结点为尾结点,不予删除!!\n");
        return;
    }

    PNode pDelet = pos->_pNext;

    pos->_data = pDelet->_data;                               //将pos位置的data 改为 其下一个结点的data
    pos->_pNext = pDelet->_pNext;                             //将pos位置的下一个结点 改为 下一个结点的下一个结点

    free(pDelet);                                             //释放pos位置的下一个结点
    pDelet = NULL;                                            //将释放的空间赋空

}

同样的,对于pos位置的插入也可以这样做

思路:稍稍做一些改变,首先将pos结点与new结点的data交换,然后再将new结点的next链接到pos的next结点,最后再更新pos的next结点,使其的next结点改为new结点,最后达到插入的效果!
这里写图片描述

代码:

void InesrtPosFront(PNode pos, DataType data)
{
assert(pos);                              //参数检测

if (NULL == pos)
{
    printf("该结点不存在!!\n");
    return;
}

PNode pNew = BuyNewNode(data);                              //申请待插入新结点 

pNew->_pNext = pos->_pNext;                                    //将pNew 链接到pos位置的next
pos->_pNext = pNew;

Swap(&pos->_data, &pNew->_data);                                 //交换pos 与 pNew 的data
}

其中调用了Swap这个交换data的函数,如下:

    void Swap(DataType* left, DataType* right)
{
    DataType temp;
    temp = *left;
    *left = *right;
    *right = temp;
}

最后:奉上我的测试函数以及测试结果!

测试函数:

void testListPushAndPop()
{
    PNode pHead;
    PNode pos;

SListInit(&pHead);

PNodePushBack(&pHead, 1);
PNodePushBack(&pHead, 2);
PNodePushBack(&pHead, 3);
PNodePushBack(&pHead, 4);
PNodePushBack(&pHead, 5);
PNodePushBack(&pHead, 6);
printSList(pHead);

pos = FindDataNode(pHead, 3);

DeleteListNotTailNode(pos);
printSList(pHead);

pos = FindDataNode(pHead, 4);

InesrtPosFront(pos, 3);
printSList(pHead);

}

测试结果:首先一次尾插 1, 2, 3, 4, 5, 6;然后找到data为3的结点,再将其删除得到:1, 2, 4, 5, 6;最后找到data为4的结点,将data为3的结点插入得到: 1, 2, 3, 4, 5, 6 。

这里写图片描述

其他的一些小问题,可以关注我哦!谢谢大家的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值