• 带环链表的几个问题


    带环链表的几个问题

    遇到了一个面试题。

    题是这样的:

    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

    如果你觉得对你有用,请赞一个吧~~

  • 相关阅读:
    Ionic3 UI组件之 autocomplete
    Ionic项目中如何使用Native Camera
    AD RMS企业文件版权管理
    利用WSUS部署更新程序
    远程桌面web连接
    文件服务器的管理
    域用户配置文件
    无需转化直接使用ESD映像文件安装系统简明教程
    Windows DHCP备份还原命令
    Bitlocker驱动器加密使用
  • 原文地址:https://www.cnblogs.com/qingergege/p/7624482.html
Copyright © 2020-2023  润新知