单向循环链表
循环链表(Circular Linked List)是另一种形式的链式存储结构。其特点是表中最后一个节点的指针域指向头节点,整个链表形成一个环。
当链表遍历时,判别当前指针 p是否指向表尾结点的终止条件不同。在单链表中,判别条件为 p!=NULL或 p->next!=NULL,而循环单链表的判别条件为p!=L 或 p->next!=L(L为头节点)。

双向链表
链式存储结构的节点中只有一个指示直接后继的指针域,由此,从某个结点出发只能顺指针向后寻查其他节点。若要寻查结点的直接前驱、则必须从表头指针出发。换句话说,在单链表中,查找直接后继的执行时间为 〇(1),而查找直接前驱的执行时间为 O(n)为克服单链表这种单向性的缺点,可利用双向链表(Double Linked List)。在双向链表的节点中有两个指针域,一个指向直接后继,另一个指向直接前驱。

typedef int ElemType;
typedef struct node
{
ElemType data;
struct node* prev,*next;
}Node;
插入双链表(头插法):

typedef struct node
{
ElemType data;
struct node* prev,*next;
}Node;
int insertHead(Node* L,ElemType e)//L为头链表
{
Node* p = (Node*)malloc(sizeof(Node));
p->data = e;
p->next = L->next;
p->prev = L;
if(L->next != NULL)
{
L->next->prev = p;
}
L->next = p;
return 1;
}
插入双链表(尾插法):

typedef struct node
{
ElemType data;
struct node* prev,*next;
}Node;
Node* Returntail(Node* L)
{
while(L->next !=NULL)
{
L = L->next;
}
return L;
}
Node* insertTail(Node* tail,ElemType e)
{
Node* p = (Node*)malloc(sizeof(Node));
p->data = e;
p->prev = tail;
p->next = NULL;
tail->next = p;
return p;
}
插入双链表(指定位置插入):
typedef struct node
{
ElemType data;
struct node* prev,*next;
}Node;
int insertNode(Node* L,int pos,ElemType e)
{
Node* p = L;
int i = 0;
//找到要插入结点的上一个结点
while(i < pos-1)
{
p = p->next;
i++;
if(p == NULL)
{
return 0;
}
}
Node* q = (Node*)malloc(sizeof(Node));
q->data = e;
q->next = p->next;
q->prev = p;
p->next = q;
if(q->next != NULL)
{
q->next->prev = q;
}
return 1;
}
双向链表删除结点:
typedef struct node
{
ElemType data;
struct node* prev,*next;
}Node;
int DeleteNode(Node* L,int pos)
{
Node* p;
int i = 0;
//找到要删除结点的上一个节点
while(i < pos-1)
{
L = L->next;
i++;
if(L == NULL)
{
return 0;
}
}
//开始删除节点,L目前是删除节点的前置结点
p = L->next;
if(p == NULL)
{
return 1;
}
else
{
L->next = p->next;
if(p->next != NULL)
{
p->next->prev = L;
}
free(p);
return 1;
}
}