循环链表

资料来源:

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值