循环链表
循环链表是链式存储结构的另一种形式,特点是单链表的最后一个结点(终端结点)的指针域不为空,而是指向链表的头结点,使整个链表形成一个环。
例子:
/*
将值为x的新结点插入到从大到小有序循环链表的适当位置
*/
int InsertData(LinkList head,int x){
ListNode *s,*p,*q; //s新结点 q当前结点(即插入新节点s的后继结点) p插入位置的前趋节点
s = (ListNode *)malloc(sizeof(ListNode)); //申请结点存储空间
s->data = x; p = head;
q = p->next; //q指向开始结点
while (q->data > x && q != head) //查找插入位置
{
p = p->next; //p指向q的前趋结点
q = p->next; //q指向当前结点
}
p->next = s; //插入s结点
s->next = q;
}
双向链表
在单链表的结点类型中增加一个指向其直接前驱的指针域prior,这样形成的链表中有两条不同方向的链,称为双向链表。
上图终端结点又指向头结点,因此称作双向循环链表
双向链表结构如下:
typedef int DataType;
typedef struct dlnote
{
DataType data;
struct dlnote *prior, *next;
}DLNote;
typedef DLNote * DLinkList;
DLinkList head;
双向链表的插入与删除
/*
将值得x的新结点插入到带头结点的双向链表中指定结点*p之前
*/
void DLInsert(DLNote *p,DataType x){
DLNote *s = (DLNote *)malloc(sizeof(DLNote)); //申请新结点
s->data = x;
s->prior = p->prior;s->next = p;
p->prior->next = s; //p的直接前驱结点指向s
p->prior=s;
}
/*
删除带头结点的双向链表中指定结点P
*/
DataType DLDelete(DLNote *p){
p->prior->next = p->next;
p->next->prior = p->prior;
DataType x = p->data;
free(p);
return x;
}
例子
假设有一个头结点指针为head的循环双向链表,其结点类型包括三个域:prior、data、next。但是其指向前趋结点的指针域prior为空,因此该双向链表其实是一个单循环链表。试写一算法,将其修改为真正的双循环链表。
void trans(DLinkList head){
DLNode *p;
p = head;
while(p->next != head){
p->next->prior=p;
p=p->next;
}
head -> prior = p;
}