插入:
//单向链表常用的后插操作
算法思想:
第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;
}