检测单链表是否有环新解

检测单链表是否有环有好几种方法。

  • 可以设置两个指针前后步遍历链表,但是这个不好确定环的T型交叉点。
  • 如果数据结构可以改就直接加个flag变量表示是否已经被遍历就可以,这个是最简单,但是一般要在不能改数据结构的情况下检测出环。
  • 我自己还能想到就是初步估计链表的长度,利用链表节点的地址构建一个散列表,访问一个节点就把这个节点的地址放到散列表里面,这个要额外的数据结构来支持算法,在链表节点比较少的情况下额外的内存消耗不会太大。
昨天真正把这个问题想了一下,琢磨小问题有时候还是挺有意思的,从上面的方法来看最简单最好用的当然就是第二个增加变量,这个可以很好的检测出环和节点。又好好想想此时的flag只是当作一个标志,只需要一个bool变量或者一位就可以,想到只要一位就很好办,难道就没有一位是永远空出来的吗。下面先看看单链表结构体的定义。

struct test{
	char c;
	struct test* next;
};
其中的c只是测试用的,没什么含义。从结构体的定义可以看出点问题了。结构体分配内存的时候地址会对齐结构体里面成员字节数最大的那一个,也就是说,单链表节点的地址会四字节对齐,因此单链表节点地址的最后两位永远是0,也就是说next指针的最后两位肯定是0了, 这就给我们提供一个flag,只要遍历一个节点将next的最后一位设为1就ok啦。

下面看看程序吧

struct test* test_cycle(struct test* head){
	unsigned long addr = 0;
	struct test* prev;
	while(head->next){
		prev = head;
		addr = (unsigned long)head->next;
		if(addr & 0x01) //检测最后一位是否为1
			return head;
		head = head->next;
		prev->next = (struct test*)(addr | 0x01);  //最后一位设1
	}
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	struct test t1 = {'a', 0};
	struct test t2 = {'b', 0};
	struct test t3 = {'c', 0};
	struct test t4 = {'d', 0};
	struct test t5 = {'e', 0};
	t1.next = &t2;
	t2.next = &t3;
	t3.next = &t4;
	t4.next = &t5;
	t5.next = &t3;
	struct test* t_joint = test_cycle(&t1);
	if(t_joint)
		printf("%c", t_joint->c);
	return 0;
}
这个程序最后没有将所有next指针还原了,只要遍历一下将所有的next的最后一位重置为0就行了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值