一.循环链表
1)循环单链表
typedef struct LNode
{
    int data;
    LNode * next;
}LNode,*LinkList;
bool InitList(LinkList L)
{
    L=(LNode *)malloc(sizeof(LNode));
    if(L=NULL) return false;
    L->next=L;
    return true;
}
bool Empty(LinkList L)
{
    if(L->next=L) return true;
    return false;
}
bool isTail(LinkList L,LNode * p) //判断一个结点是否为尾节点
{
    return(p->next==L);
}使用循环单链表时,如果经常需要对表头、表尾操作,可以使L指向表尾,这样找到表头、表尾的时间复杂度都是O(1)。
2)循环双链表
typedef struct LNode
{
    int data;
    LNode * next;
    LNode * prior;
}LNode,*LinkList;
bool InitList(LinkList L)
{
    L=(LNode *)malloc(sizeof(LNode));
    if(L=NULL) return false;
    L->next=L;
    L->prior=L;
    return true;
}
bool Empty(LinkList L)
{
    if(L->next=L) return true;
    return false;
}
bool isTail(LinkList L,LNode * p) //判断一个结点是否为尾节点
{
    return(p->next==L);
}
bool ListInsert(DNode * p,DNode * s) 
{
    if(p==NULL||s==NULL) return false;
    s->next=p->next; //1
    p->next->prior=s; //2 尾节点会指向头结点,不会置空,因此不需要条件判断
    s->prior=p; //3
    p->next=s;  //4  1,2必须在4前
    return true;
}
bool ListDelete(DNode * p) //删除指定结点的后继节点
{
    if(p==NULL) return false;
    DNode * q=p->next; 
    p->next=q->next;
    q->next->prior=p;
    free(q);
    return true;
}指针类链表小结
链表类代码在编写时需要考虑三个问题:
1.如何判空,知道空的状态如何判断就知道如何初始化
2.如何判断表头,表尾,知道怎么判断表头表尾就知道怎么遍历,就知道了怎么去查找、删除、增加
3.表尾、表头是否需要特殊处理
二.静态链表
1)静态链表的定义
#define MaxSize 10
typedef struct Node
{
    int data;
    int next;
}SLinkList[MaxSize];
void InitList()
{
    SLinkList a;
}2)静态链表的基本操作
初始化:要将a[0]置为-1;将其他空的结点游标置为-2(方便后续计算机判断哪些结点是空结点);
查找:通过游标依次遍历元素,时间复杂度为O(n)
插入:
1.找到一个空的结点用来存放元素
2.找到位序为i-1的结点
3.修改新的结点的next游标
4.修改i-1结点的next
删除:
1.找到其前驱结点
2.修改前驱结点游标
3.被删除结点的游标置为-2;
3)静态链表的优缺点
优点:增删容易,不需要大量的移动数据
缺点:查找需要遍历,容量固定

京公网安备 11010502036488号