资料来源:
http://student.zjzk.cn/course_ware/data_structure/web/xianxingbiao/xianxingbiao2.3.2.htm点击打开链接
循环链表(Circular Linked List)
循环链表是一种首尾相接的链表。
1、循环链表
(1)单循环链表——在单链表中,将终端结点的指针域NULL改为指向表头结点或开始结点即可。
(2)多重链的循环链表——将表中结点链在多个环上。
2、带头结点的单循环链表
注意:
判断空链表的条件是head==head->next;
3、仅设尾指针的单循环链表
用尾指针rear表示的单循环链表对开始结点a1和终端结点an查找时间都是O(1)。而表的操作常常是在表的首尾位置上进行,因此,实用中多采用尾指针表示单循环链表。带尾指针的单循环链表可见下图。
注意:
判断空链表的条件为rear==rear->next;
4、循环链表的特点
循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活。
【例】在链表上实现将两个线性表(a1,a2,…,an)和(b1,b2,…,bm)连接成一个线性表(a1,…,an,b1,…bm)的运算。
分析:若在单链表或头指针表示的单循环表上做这种链接操作,都需要遍历第一个链表,找到结点an,然后将结点b1链到an的后面,其执行时间是O(n)。若在尾指针表示的单循环链表上实现,则只需修改指针,无须遍历,其执行时间是O(1)。
相应的算法如下:
LinkList Connect(LinkList A,LinkList B)
{//假设A,B为非空循环链表的尾指针
LinkList p=A->next;//①保存A表的头结点位置
A->next=B->next->next;//②B表的开始结点链接到A表尾
free(B->next);//③释放B表的头结点
B->next=p;//④
return B;//返回新循环链表的尾指针
}
注意:
①循环链表中没有NULL指针。涉及遍历操作时,其终止条件就不再是像非循环链表那样判别p或p->next是否为空,而是判别它们是否等于某一指定指针,如头指针或尾指针等。
②在单链表中,从一已知结点出发,只能访问到该结点及其后续结点,无法找到该结点之前的其它结点。而在单循环链表中,从任一结点出发都可访问到表中所有结点,这一优点使某些运算在单循环链表上易于实现。
5、循环链表的其它几个操作
循环链表的插入、删除和获取元素的操作基本和单链表类似。
具体实践代码:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node* next;
}Node,*CirculateList;
//create circulate list with n elements.
CirculateList CreateList(CirculateList list, int n)
{
CirculateList temp,head;
list = (Node*)malloc(sizeof(Node*));
if(list == NULL)
{
printf("fails to create list.\n ");
return NULL;
}
head = list;
head ->next = head; //empty list
int i = 1;
while(i <= n)
{
temp = (Node*)malloc(sizeof(Node*));
if (1==i){
temp->next=head;
}
else{
temp->next = list->next;
}
temp->data = i;
list->next = temp;
++i;
}
return head;
}
//1 ture;0error
int ListInsert(CirculateList list, int pos, int num)
{
CirculateList temp,node;
temp = list;
int i=1;
while(temp->next!=list)
{
if (i==pos)
{
break;
}
temp = temp->next;
i++;
}
if((list==temp->next)&&(i<pos))
{
printf("fails to insert %d into list.\n ",num);
return 0;
}
else if((list==temp->next)&&(i==pos))
{
node = (Node*)malloc(sizeof(Node*));
temp->next = node;
node->data = num;
node->next = list;
}
else{
node = (Node*)malloc(sizeof(Node*));
node->next = temp->next;
temp->next = node;
node->data = num;
}
return 1;
}
//1 ture;0error
int ListDelete(CirculateList list, int pos)
{
CirculateList temp,node;
node = (Node*)malloc(sizeof(Node*));
temp = list;
int i=1;
while(temp->next!=list)
{
temp = temp->next;
if (i==pos)
{
break;
}
i++;
}
if((list==temp->next) && (i<pos))
{
printf("fails to delete a element from list at pos %d.\n ",pos);
return 0;
}else
{
node= temp->next;
temp->data = node->data;
temp->next = node->next;
// free(node);
}
return 1;
}
//return the pos of element. 0 instands None exist.
int LocateElem(CirculateList list, int element)
{
CirculateList p = list->next->next;
int j = 1;
while (p != list->next)
{
++j;
if (p->data == element)
return j;
p = p->next;
}
return 0;
}
void ListShow(CirculateList list)
{
if(list->next == list)
{
printf("No elements in the list.\n");
}
else
{
CirculateList temp;
temp = (Node*)malloc(sizeof(Node*));
temp=list->next;
while(temp!=list)
{
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
}
int main()
{
CirculateList mylist;
mylist = CreateList(mylist, 16);
ListShow(mylist);
printf("---------------------------------------------\n");
int ret = ListInsert(mylist, 16,18);
if (!ret)
{
printf("fail to insert list.\n");
}
ListShow(mylist);
printf("---------------------------------------------\n");
int n=18;
printf("the pos of %d is %d\n",n, LocateElem(mylist, n));
printf("---------------------------------------------\n");
ret = ListDelete(mylist, 1);
if (!ret)
{
printf("fail to insert list.\n");
}
ListShow(mylist);
return 0;
}