1、建立单链表:
下面两种方法的时间复杂度都是O(n)
(1)头插法
Linklist CreateFromHead(){
LinkList L;
LNode *s;
int x;
int flag=1;
L=(Linklist)malloc(sizeof(LNode));
L->next=NULL;
scanf("%d",&x);
while(x!=-1){
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
每次都相当于在头结点后面插入新元素
(2)尾插法
Linklist CreateFromTail(){
LinkList L;
LNode *r,*s;
int x;
L=(LNode *)malloc(sizeof(LNode));
L->next=NULL;
r=H;//指向头结点
scanf("%d",&x);
while(x!=-1){
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=r->next;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return L;
}
有一个尾指针r始终指向最后一个节点
2、循环列表
举个例子:有两个带头结点的循环单链表LA、LB,编写一个算法,将两个循环单链表合并为一个循环单链表,其头指针为LA
分析:先找到两个链表的尾,分别用指针p、q指向它们,然后将第一个链表的尾与第二个链表的第一个结点链接起来,并修改第二个链表的尾节点,使它的链域指向第一个链表的头结点,并且释放第二个链表的头结点
LinkList merge_1(LinkList LA,LinkList LB){
LNode *p,*q;
p=LA;
q=LB;
while(p->next!=LA)
p=p->next;
while(q->next!=LB)
q=q->next;
p->next=LB->next;
free(LB);
q->next=LA;
return(LA);
}
时间复杂度为O(n)
第二种情况,当上面的两个循环链表带有尾指针时,又怎么合并呢?
LinkList merge_2(LinkList RA,LinkList RB)
{
LNode *p;
p=RA->next;
RA->next=RB->next->next;
free(RB->next);
RB->next=p;
return(RB);
}
时间复杂度为O(1)
3、双向链表
更方便的获得一个结点的前驱和后继结点,方便插入和删除
在单链表的每个结点里再增加一个指向其前驱的指针域prior