判断单链表是否有环
来源:互联网 发布:指南针炒股软件诈骗 编辑:程序博客网 时间:2024/05/22 06:41
前言:
其实这个题目是面试官给提的,由于当时在学习数据结构与算法的时候没有接触过这类问题,因此通过在网上查阅资料和自己的理解产生这篇博客,希望能帮得到大家。
如下面的单链表:
如何判断该链表中是否存在环。
方法一:
使用 p、q 两个指针,p 总是向前走,但 q 每次都从头开始走,对于每个节点,看 p 走的步数是否和 q 一样。如果对于每个节点,p、q 走过的步数都是一样的,则证明不存在环,反之,存在环。
代码(C语言实现):
// param 单链表头结点指针bool has_loop1(struct node * head){ //p、q 指针 node_t p = head,q = head; //typedet struct node * node_t //步数 int p_count = 0,q_count = 0; while(q != NULL && p_count == q_count){ //重置p指针和步数 p = head; p_count = 0; //q继续遍历链表 q = q -> next; q_count ++; while(p != q){ p = p -> next; p_count ++; } //当 p == q 时,判断各自走过的步数 if(p_count != q_count){ return true; } } return false;}
网上也有不同的类似的解决方法:
首先从头节点开始,依次遍历单链表的每一个节点。每遍历到一个新节点,就从头节点重新遍历新节点之前的所有节点,用新节点ID和此节点之前所有节点ID依次作比较(这个节点ID直接用地址就行)。如果发现新节点之前的所有节点当中存在相同节点ID,则说明该节点被遍历过两次,链表有环;如果之前的所有节点当中不存在相同的节点,就继续遍历下一个新节点,继续重复刚才的操作。或者是将遍历过的节点放到 hash 表(数组)中,每遍历一个新节点,将新节点和 hash 表(数组)中的旧节点作比较,如果存在,则证明该链表有环。
这些方法的核心思想无非就是将新节点与遍历过的旧节点做比较,因此我就不在展开分析。
方法二:
使用 p、q 两个指针,p 每次向前走一步,q 每次向前走两步,若在某个时候 p == q,则存在环。
该方法应该算是业界中效率最高的吧,网上的博客中都会说到这个方法。
其实理解这个方法不是很难,这个方法就好比有两个人甲、乙在跑道上(环状)跑步(同时同起点出发),乙的速度是甲的两倍,总有某一个时刻乙会追上甲,此时乙跑的路程比甲多一圈。回归到我们的问题,q 的速度是 p 的两倍,那么如果存在环的话,q 和 p 在某个时刻总会相遇的(即 p == q)。
代码:
//param 单链表头结点指针bool has_loop2(struct node * head){ //同起点 node_t p = head,q = head; while(p != NULL && q != NULL){ p = p->next; q = q->next; if(q != NULL){ q = q->next; } //这里 q=q->next->next 分开是为了防止段错误 //p 和 q 相遇 if(p != NULL && q != NULL && p == q){ return true; } } return false;}
结尾:
现在我们来看看客户端代码:
#include <stdio.h>#include <stdlib.h>#include <stdbool.h>//链表长度#define LEN 8//节点结构struct node{ char var; struct node * next;};typedef struct node * node_t;//方法一:计算步长bool has_loop1(struct node * head);//方法二:判断两个指针是否相遇bool has_loop2(struct node * head);int main(void){ node_t head = (node_t)malloc(sizeof(struct node)); node_t pre = head; node_t link = NULL; int i; for(i = 0;i < LEN;i ++){ node_t new_node = (node_t)malloc(sizeof(struct node)); pre->next = new_node; pre = pre->next; if(i == 2){ link = pre; } } pre->next = pre; if(has_loop1(head)){ printf("存在环\n"); }else{ printf("不存在环\n"); } if(has_loop2(head)){ printf("存在环\n"); }else{ printf("不存在环\n"); } return 0;}
本博客参考自 http://www.cnblogs.com/shuaiwhu/archive/2012/05/03/2480509.html,加上自己的理解,如果上面代码有错的地方,欢迎指正。
0 0
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环?
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- 判断单链表是否有环
- J2EE Servlet随手记
- Rabbit MQ持久化
- Android中实现定时器的四种方式
- 真的要加相机权限吗?!
- 创建对象及原型模式
- 判断单链表是否有环
- Java微信公众平台开发之生成带参二维码
- 7. JPA - Hibernate【从零开始学Spring Boot】
- 复杂表单转换JS对象 form2js插件介绍
- GOF23的一些总结(三)
- Eclipse设置或更换jdk版本
- 求N以内的所有完数
- 更新libva及V4l2 Buffer Sharing
- 协议栈的编码、解码