链表

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

原文地址:https://www.cnblogs.com/zw1sh/p/12422804.html