数据结构和算法学习笔记:单向链表的插入与删除操作

插入:

//单向链表常用的后插操作
算法思想
第0步:先检查插入节点位置的合法性
第1步:调用按值查找算法p=Getelem(L,i-1)找到前驱节点

s->next=p->next
p->next=s

//以上代码两步不能颠倒,否则会造成原来p->next节点丢失,断链

时间复杂度O(n),花在了查找节点s上
若s节点的地址给定,则时间复杂度显然为O(1)
那么由这一点,若我给定链表中某一个节点p,我希望实现将s插入到p的前面
我可以先将s插入到p的后面,然后将p->data与s->data交换,这样既满足了逻辑关系,又能使得时间复杂度为O(1)

s->next=p->next;
p->next=s;
temp=p->data;
p->data=s->data;
s->data=temp;
(但这样做从哲学上来说,s->data和p->data都不在原来的内存空间了...)

删除:

算法思想:
第0步:先检查插入节点位置的合法性
第1步:调用按值查找算法p=Getelem(L,i-1)找到前驱节点
q = p->next;
p->next = q->next;
free(q);

时间复杂度O(n),花在了查找节点s上
那么由这一点,若我给定链表中某一个节点p,
删除这个节点p的操作可以这样来实现:
p->data=p->next->data;
p->next=p->next->next;
free(q)

这样既满足了逻辑关系,又能使得时间复杂度为O(1)
 

代码实现:

#include <stdbool.h>//注意加上
//按序号查找节点
LNode *Getelem(LinkList L,int i)
{

    LNode *p=L->next;
    if(i==0) return L;
    if(i<1)return NULL;
    for(int j=1;j<i&&p;j++)
    {
        p=p->next;
        j++;
    }
    return p;
}

//单向链表的插入操作(前插,不常用)//就是和尾插法颠倒而已Getelem先找后继节点
bool Insert_from_header(LinkList& L, int i, int elem)//对线性表而言的第i个位置
{
}

//单向链表常用的后插操作
/*算法思想:
第0步:先检查插入节点位置的合法性
第1步:调用按值查找算法p=Getelem(L,i-1)找到前驱节点
s->next=p->next
p->next=s

时间复杂度O(n),花在了查找节点s上
若s节点的地址给定,则时间复杂度显然为O(1)
那么由这一点,若我给定链表中某一个节点p,我希望实现将s插入到p的前面
我可以先将s插入到p的后面,然后将p->data与s->data交换,这样既满足了逻辑关系,又能使得时间复杂度为O(1)
即
s->next=p->next;
p->next=s;
temp=p->data;
p->data=s->data;
s->data=temp;
(但这样做从哲学上来说,s->data和p->data都不在原来的内存空间了...)
*/
//代码实现:
bool Insert_after(LinkList &L,int i,LNode* &s)
{
    if (Getelem(L, i - 1) == NULL)return false;
    LNode* p;
    p=Getelem(L, i - 1);
    s->next = p->next;

    //以下两步不能颠倒,否则会造成原来p->next节点丢失,断链
    p->next = s;
    return true;
}

//单向链表的删除操作
/*算法思想:
第0步:先检查插入节点位置的合法性
第1步:调用按值查找算法p=Getelem(L,i-1)找到前驱节点
q = p->next;
p->next = q->next;
free(q);

时间复杂度O(n),花在了查找节点s上
那么由这一点,若我给定链表中某一个节点p,
删除这个节点p的操作可以这样来实现:
p->data=p->next->data;
p->next=p->next->next;
free(q)

这样既满足了逻辑关系,又能使得时间复杂度为O(1)
*/
//代码实现:
bool Dele_from_header(LinkList& L, int i)
{
    if (Getelem(L, i - 1) == NULL)return false;
    LNode* p,*q;
    p = Getelem(L, i - 1);
    q = p->next;
    p->next = q->next;
    free(q);
    return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值