typedef struct LNode
{
int data;
struct LNode *next;
}LNode;
带头结点单链表逆置
void reverse(LNode *L)//头插法颠倒
{
LNode *p,*q;//p是用来接收新链表的结点,q负责给p看家
p=L->next;
L->next=NULL;
while(p!=NULL)
{
q=p->next;//标记p的后继节点为q
p->next=L->next;//将p加入新的L链表,将其连接在L之后之后
L->next=p;
p=q;//p返回未处理链表
}
}
不带头结点单链表逆置
void reverse(LNode *L)
{
LNode *p,*q,*r;//p用来遍历 q指向新链表的队头元素,r指向当前结点的后继节点,
//给p看家
p=L;
q=NULL;
while(p!=NULL)
{
r=p->next;//r指向下一个待处理数据即当前正在处理的元素的后继节点
p->next=q;//q标记已排链表的第一个元素,将p连接到队首
q=p;//队首指针前移
p=r;//p返回未处理链表的队首,循环处理
}
}
实现升序C=A+B
LNode merge(LNode *La,LNode *Lb)
{
LNode *Lc;
LNode *p,*q,*r;
Lc=La;
p=La->next;
q=Lb->next;
r=Lc;
while(p!=NULL&&q!=NULL)
{
if(p->data<=q->data)
{
r->next=p;
p=p->next;
r=r->next;
}
else
{
r->next=q;
q=q->next;
r=r->next;
}
}
if(p!=NULL)
{
r->next=p;
}
else if(q!=NULL)
{
r->next=q;
}
else//p q都空
r->next=NULL;
return Lc;
}
实现C=A-B
LNode different(LNode La,LNode Lb)
{
LNode *p,*q,*r;
q=Lb->next;
while(q)
{
p=La;
while(p->next)
{
if(q->data==p->next->data)
{
r=p->next;
p->next=r->next;
free(r);
}
p=p->next;
}
q=q->next;
}
return La;
}
长度为n的顺序表的移动次数
插入
在第i个位置前插入新元素需要移动n-i+1个元素;
等概率下平均移动次数为n/2,不等概率下平均移动个数为(2n+1)/3
时间复杂度为O(n)
删除
删除第i个元素需移动n-i个元素,平均移动次数(n-1)/2
长度为n的链表
访问第i个位置的元素时间复杂度是O(n)
带头结点的单循环链表只有一个元素的条件:L->next->nextL&&L->next!=L;
带头结点的双循环链表为空的条件:L->priorL->next&&L->next==L
若一个线性表最常操作是
(1) 在末尾插入节点和删除尾节点,则选用带头结点的双循环链表或给出表尾指针的双向循环链表;
(2) 存取第一个元素及其前驱后继节点的值,则选用顺序表
在单链表中设置头结点的作用:
头节点是为了操作的统一,放在第一元素结点之前,头指针的值是确定的,无论链表是否为空,头指针均不为空;设置头结点后,可以统一插入结点和删除结点是第一元素结点的算法,不需要判断是否是在第一个元素之前插入元素和删除第一个元素。
顺序存储结构通过结点物理位置上相邻表示元素之间的关系,链式存储结构通过指针表示元素之间的关系。
循环单链表的优点:从链表中任何一个结点出发都可以访问到链表中的每一个元素
实现A交B
void jiao(LNode *LA,LNode *LB)
{
LNode *LC;
LC=LA;
LNode *p,*q,*r;
p=LA;
q=LB;
r=LC;
while(p!=NULL)
{
while(q!=NULL)
{
if(p->data==q->data)
{
r->next=p;
r=r->next;
break;
}
q=q->next;
}
p=p->next;
}
r->next=NULL;
}