代码改变世界

面试题12:单链表建环

2016-03-31 22:13  Keiven_LY  阅读(254)  评论(0编辑  收藏  举报

昨天研究了关于单链表是否有环的问题,但是我们建的的单链表本身就是没环的。我们能否给一个无环链表建环呢?

当然可以,不过得想想算法。其实貌似也不难,只要找到最后一个结点 tail,让它指向环的入口就行。所以问题分解为:找到环入口点 cur,把最后的指针 tail 指向 cur即可。、

算法思想:

1、首先找到环的入口,也就是参数num。定义工作指针pcur,让它遍历到环入口处;

Node *pcur = head;
for(int i = 1; i < num; i++)
{
    if(pcur == NULL)
        return ERROR;
    pcur = pcur->next;
}

2、这个时候让第二个工作指针ptail接替pcur遍历到表尾

ptail = pcur;
while(ptail->next)
{
    ptail = ptail->next;
}

3、这个时候ptail就是尾结点,而pcur就是环的入口,让ptail指向pcur即可

ptail->next = pcur;

功能函数:

/*     单链表建环    */
void buildLoop(Node *head, int num)
{
    Node *pcur = head;
    Node *ptail = NULL;
    if(num <=0 || head == NULL)
        cout << "链表不存在或链表为空!!" << endl;
    for(int i = 0; i < num; i++)
    {
        if(pcur == NULL)
        {
            cout << "链表为空,无法建环" << endl;
        }

        pcur = pcur->next; 
    }
    ptail = pcur;
    while(ptail->next)
    {
        ptail = ptail->next;
    }
    ptail->next = pcur;
    cout << "建环成功,入口位置是" << num <<endl;
}

完整可执行程序:

#include<iostream>
#include <stack>
#include<stdlib.h> 
#include<time.h>

using namespace std;

typedef struct node
{
    int data;
    struct node *next;
}Node;

/*     创建含有n个结点的单链表    */
Node *CreateListHead(int n) 
{
    Node *head;
    head=(Node *)malloc(sizeof(Node)); /*创建头结点*/
    Node *q = head;

    /* 初始化随机数种子 */
    srand(time(0));  //srand函数在stdlib.h头文件中,time函数在time.h头文件中

    for(int i=0; i < n; i++)
    {
        Node *p = (Node *)malloc(sizeof(Node));
        p->data = rand()%100+1;  //随机生成100以内的数字 
        p->next = q->next;
        q->next = p;
        q = p;
    }
    q->next = NULL;

    return head;
}

/****打印单链表******/
void print(Node *head)
{
    Node *p;
    if(head->next==NULL)
    {
        cout << "The LinkList is Empty !" <<endl;
        return;
    }
    p=head->next;
    while(p!=NULL)
    {
        cout << p->data << " " ;
        p=p->next;
    }
}
/*     判断链表是否有环    */
int hasLoop(Node *head)
{
    Node *p1,*p2;
    if(head == NULL || head->next == NULL) //链表为空,或是单结点链表直接返回头结点
        return 0;
    p1 = p2 = head;
    while(p1->next != NULL && p1->next->next != NULL)
    {
        p1 = p1->next->next;
        p2 = p2->next;
        if(p1 == p2)
            return 1;
    }
    return 0;
}

/*     单链表建环    */
void buildLoop(Node *head, int num)
{
    Node *pcur = head;
    Node *ptail = NULL;
    if(num <=0 || head == NULL)
        cout << "链表不存在或链表为空!!" << endl;
    for(int i = 0; i < num; i++)
    {
        if(pcur == NULL)
        {
            cout << "链表为空,无法建环" << endl;
        }

        pcur = pcur->next; 
    }
    ptail = pcur;
    while(ptail->next)
    {
        ptail = ptail->next;
    }
    ptail->next = pcur;
    cout << "建环成功,入口位置是" << num <<endl;
}
int main()
{
    Node *SingleLinkList = NULL;
    int length;

    cout << "Please input the length of LinkList: ";
    cin >> length;
    SingleLinkList = CreateListHead(length);
    cout << "The new created LinkList as below: " ;
    print(SingleLinkList);
    cout << endl;

    int position_loop;//建环位置
    cout << "请输入你要建环的位置:  ";
    cin >> position_loop;
    buildLoop(SingleLinkList, position_loop);

int flag = hasLoop(SingleLinkList);
    if(flag == 1)
        cout << "该链表存在回环!" << endl;
    else
        cout << "该链表不存在回环!" << endl;
    system("pause");
    return 0;
}

运行结果: