带环链表的几个问题
遇到了一个面试题。
题是这样的:
1、 判断一个单链表是否存在环
2、 如果存在,求环的长度
3、 如果存在,求环的起始节点
4、 如果存在,整个链表的长度
参考了
http://blog.csdn.net/liuxialong/article/details/6555850
http://blog.csdn.net/thefutureisour/article/details/8174313
记录一下:
对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。
对于问题2,记录下问题1的碰撞点p,slow、fast从该点开始,再次碰撞所走过的操作数就是环的长度s。
3、问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
该定理的证明可参考:http://fayaa.com/tiku/view/7/
4、问题3中已经求出连接点距离头指针的长度,加上问题2中求出的环的长度,二者之和就是带环单链表的长度
下面是自己写的测试代码
#include <iostream> using namespace std; struct node{ int data; struct node *next; }; class CNode{ private: struct node *head;//单链表的头 struct node *meet;//记录相遇点 int size; int loop_len; int total_len; public: CNode(int data[],int n,int start); bool isloop(); int get_loop_len()//获取环的长度 { return loop_len; } int get_total_len()//获取整个链表的长度 { return total_len; } int get_start();//获取环开始的地方的元素值 }; CNode::CNode(int data[],int n,int start):meet(NULL),loop_len(0),total_len(0)//构造函数,带排序功能 { size = n; head = NULL; int i = 0; struct node *q = NULL; for(i = 0;i < n;i++) { struct node *p = new struct node; p->data = data[i]; p->next = NULL; if(i == 0) { head = p; head->next = NULL; } else { if(p->data < head->data)//比头数据要小 { p->next = head; head = p; } else { struct node *pre = head; struct node *curr = head->next; while(curr != NULL) { if(p->data < curr->data)//找到合适位置 { break; } pre = curr; curr = curr->next; } p->next = curr; pre->next = p; } } q = p; } //下面是变成环的过程 struct node *current = head; while(current != NULL) { if(current->data == start) { break; } current = current->next; } q->next = current;//形成环 } bool CNode::isloop()//判断是否存在环 { struct node *fast = head; struct node *slow = head; int count = 0;//记录相遇的次数 while(fast->next != NULL && fast->next->next != NULL)//C语言采用的是短路与,所以可以这样 { if(fast == slow) { count++; if(count == 1)//第一次相遇 { loop_len = 0;//开始计数 } if(count == 2) { meet = slow; return true; } } loop_len++; fast = fast->next->next; slow = slow->next; } return false; } int CNode::get_start() { struct node *p = head; struct node *q = meet; int num = 0; while(p != q) { num++; p = p->next; q = q->next; } total_len = num + loop_len; return p->data; } int main() { int data[9] = {7,4,6,5,3,1,2,8,9}; CNode cnode(data,9,4); if(cnode.isloop()) { cout<<"链表存在环!"<<endl; } cout<<"环的开始点为:"<<cnode.get_start()<<endl; cout<<"环的长度为:"<<cnode.get_loop_len()<<endl; cout<<"链表的总长度为:"<<cnode.get_total_len()<<endl; return 0; }
最后附上word和源代码链接
链接:http://pan.baidu.com/s/1mhHdQkg 密码:wtyy
如果你觉得对你有用,请赞一个吧~~