数据结构 -线性表 -循环表

不用头指针,而是用指向终端结点的尾指针来表示循环链表,这个就是循环列表。如图:



那么要判断单链表中是否有环,主要有以下两种方法:

 

方法一:使用p、q两个指针,p总是向前走,但q每次都从头开始走,对于每个节点,看p走的步数是否和q一样。如图,当p从6走到3时,用了6步,此时若q从head出发,则只需两步就到3,因而步数不等,出现矛盾,存在环。

 

方法二:使用p、q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p == q,则存在环。

用随机的方法来生成一个链表,用两种方法判断是否有环。代码如下。


#include<stdio.h>
#include "malloc.h"
#include <stdlib.h>
#include <time.h>

#define OK 1
#define ERROR 0
#define TRUE 1
# define PALSE 0

typedef int Status;//Status是函数的类型其值是函数的状态码,如ok
typedef int ElemType;//ElemType类型是根据实际情况而定这里设定为int

typedef struct Node
{
	ElemType data;
	struct Node *next;
}Node,*LinkList;

//初始化带头结点的空链表
Status InitList(LinkList *L)
{
	*L = (LinkList)malloc(sizeof(Node));//产生头结点,便是l指向此节点

	if (!(*L))//储存分配失败
		return ERROR;
	(*L)->next=NULL;// 指针为空

	return OK;
}
int ListLength(LinkList L)
{
	int i=0;
	LinkList p=L->next;//p指向第一个节点
	while (p)
	{	
		i++;
		p=p->next;
	}
	return i;
}

//随机产生n个元素的值,建立表头节点的单链表l
void CreateListHead(LinkList *L,int n)
{
	LinkList p;
	int i;
	
	srand(time(0));//初始化随机种子

	*L = (LinkList)malloc(sizeof(Node));//l为整个线性表
	(*L)->next=NULL;

	for (i=0;i<n;i++)
	{
		p=(LinkList)malloc(sizeof(Node));//生成新的节点
		(*L)->data=rand()%100+1;//随机生成100一类的数字
		p->next=p;//将表尾的终端节点的指针指向新节点
		(*L)->next=p;//将当前的新节点定义为表尾的终端节点
	}
}
void CreateListTail(LinkList *L,int n)
{
	LinkList p,r;
	int i;
	
	srand(time(0));//初始化随机种子

	*L = (LinkList)malloc(sizeof(Node));//l为整个线性表
	(*L)->next=NULL;
	r=*L;

	for (i=0;i<n;i++)
	{
		p=(Node *)malloc(sizeof(Node));//生成新的节点
		p->data=rand()%100+1;
		r->next=p;
		r=p;
	}
	r->next=(*L)->next->next;
}
int HasLoop1(LinkList L)
{
	LinkList cur1=L;//定义重点
	int pos1=0;//重点的参数

	while(cur1)//cur1存在
	{
		LinkList cur2=L;//定义cur2
		int pos2 =0;
		while(cur2)
		{
			if (cur1==cur2)
			{
				if(pos1==pos2)
					break;
				else 
				{
					printf("环的位置在%d个节点处\n\n",pos2);
					return 1;
				}
			}
			cur2=cur2->next;
			pos2++;
		}
		cur1=cur1->next;//如果发现没环,继续下一个节点
		pos1++;
	}
	return 0;
}
int HasLoop2(LinkList L)
{
	int step1=1;
	int step2=2;
	LinkList p=L;
	LinkList q=L;

	while (p!= NULL && q!=NULL && q->next!=NULL)
	{
		p= p->next;
		if(q->next!=NULL)
			q=q->next->next;
		printf("p:%d,q:%d\n",p->data,q->data);

		if (p==q)
			return 1;
	}
	return 0;
}
	int main()
	{

		LinkList L;
		Status i;
		char opp='a';
		ElemType e;
		int find;
		int tmp;

		i =  InitList(&L);
		printf("初始化L后:ListLength=%d\n",ListLength);
		printf("\n1.创建有环链表L(尾插法)\n2.创建的无环列表L(头插法)\n3.判断是都有环\n0.退出");
		while (opp!='0')
		{
			scanf("%c",&opp);
			if(opp=='0')
				return
			printf("\n");
			switch(opp)
			{
				case '1':
					CreateListTail(&L,10);
					printf("成功创建有环列表L(尾插法)\n");
					break;

				case '2':
					CreateListHead(&L,10);
					printf("成功创建无环列表L(尾插法)\n");
					break;

				case '3':


					printf("方法一:\n\n");
					if (HasLoop1(L))
					{
						printf("结论:链表有环\n\n\n");
					}
					else
					{
						printf("结论:链表无环\n\n");
					}

					printf("方法二:\n\n");
					if (HasLoop2(L))
					{
						printf("结论:链表有环\n\n\n");
					}
					else
					{
						printf("结论:链表无环\n\n");
					}
					printf("*************************************************************************\n");
					break;

				case '0':
					exit(0);
			}
		}
	}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值