• 链表之循环链表


    上期文章介绍了单链表的一些基本功能函数,本次主要介绍循环链表的一些基本功能函数。循环链表其实就是将单链表的最后一个结点指向单链表的头结点,从而构成一个循环结构。本次函数功能主要包括链表创建函数(头插法和尾插法)链表打印函数两种链表是否有环的判定函数,以及最后的一个链表清除函数

    函数运行如下图所示:

    cLinkList

    功能函数

    链表创建函数(头插法)

    //定义循环链表生成函数(头插法)
    void cListCreatHead(cLinkList *L, int n)
    {
        int i;
        cLinkList *p, *r;
        p = L;
        p->data = rand() % 100 + 1;
        for(i = 1; i < n; ++i)
        {
            r = (cLinkList *)malloc(sizeof(cLinkList));
            r->data = rand() % 100 + 1;
            r->next = p;
            p = r;
        }
        L->next = p;
    }
    

    这里使用了头插法对链表进行生成操作,L作为cLinkList的一个指针,指向链表的最后一个结点,这里注意最后要将L指向p构建循环。

    链表创建函数(尾插法)

    //定义循环链表生成函数(尾插法)
    void cListCreatTail(cLinkList *L, int n)
    {
        int i;
        cLinkList *head, *p;
        head = L;
        L->data = rand() % 100 + 1;
        for(i = 1; i < n; i++)
        {
            p = (cLinkList *)malloc(sizeof(cLinkList));
            p->data = rand() % 100 + 1;
            L->next = p;
            L = p;
        }
        L->next = head;
    }
    

    这里使用了尾插法对链表进行生成操作,L作为cLinkList的一个指针,在创建过程中不断向后移动,最后指向链表的最后一个结点,这里注意最后要将L指向头结点指针head构建循环。

    链表打印函数

    void cListPrint(cLinkList *L)
    {
        cLinkList *head, *p;
        head = L;
        p = L;
        int count = 1;
        while(p->next != head)
        {
            printf("%d	", p->data);
            p = p->next;
            count++;
        }
        printf("%d
    ", p->data);
        printf("The length of this LinkList is: %d
    ", count);
    }
    

    通过判定p->next != head为条件对链表进行遍历打印,在遍历过程中计算链表的长度并打印输出。

    检测是否有环(方法一)

    //检查是否有环(方法一)
    int cListCheckLoop1(cLinkList *L)
    {
        cLinkList *head, *p, *q;
        head = p = q = L;
        int countp, countq;
        countp = 1;
        while(1)
        {
            p=p->next;
            countp++;
            countq = 1;
            q = head;
            while(q != p)
            {
                q = q->next;
                countq++;
            }
            if(++countq != countp)
            {
                printf("YES!
    There is a loop in the LinkList!
    ");
                return 1;
            }
            if(p->next == NULL)
            {
                printf("NO!
    There is no loop in the LinkLis!
    ");
                return 0;
            }
        }
    }
    

    设置指针变量p对链表进行遍历,同时使用qp之前的结点进行遍历,如果发现到达p所在结点的更短路径,则判定链表存在环。比如,p走了6步到达结点A,而q只需要3步即可到达结点A,则此时链表中必定存在环,换言之,此前p已经经过结点A了。

    检测是否有环(方法二)

    //检测链表是否有环(方法二)
    int cListCheckLoop2(cLinkList *L)
    {
        cLinkList *p, *q;
        p = q = L;
        while(p->next != NULL && p->next->next != NULL)
        {
            p = p->next->next;
            q = q->next;
            if(p == q)
            {
                printf("YES!
    There is a loop in this LinkList
    ");
                return 1;
            }
        }
        printf("NO!
    There is no loop in the LinkList
    ");
        return 0;
    }
    

    设置p的步长为2,q的步长为1,同时对链表进行遍历,如果在某个时刻p == q,则就可以断定链表中存在环。

    链表清除

    //链表清除函数
    void cListClear(cLinkList *L)
    {
        cLinkList *p, *temp;
        p = L->next;
        while(p != L)
        {
           temp = p;
           p = p->next;
           free(temp);
        }
    }
    

    使用free()函数对我们生成的链表空间进行遍历删除。


    总体代码

    #include <stdio.h>
    #include <stdlib.h>
    //定义循环链表结构
    typedef struct node
    {
        int data;
        struct node *next;
    }cLinkList;
    
    //定义循环链表生成函数(头插法)
    void cListCreatHead(cLinkList *L, int n)
    {
        int i;
        cLinkList *p, *r;
        p = L;
        p->data = rand() % 100 + 1;
        for(i = 1; i < n; ++i)
        {
            r = (cLinkList *)malloc(sizeof(cLinkList));
            r->data = rand() % 100 + 1;
            r->next = p;
            p = r;
        }
        L->next = p;
    }
    
    //定义循环链表生成函数(尾插法)
    void cListCreatTail(cLinkList *L, int n)
    {
        int i;
        cLinkList *head, *p;
        head = L;
        L->data = rand() % 100 + 1;
        for(i = 1; i < n; i++)
        {
            p = (cLinkList *)malloc(sizeof(cLinkList));
            p->data = rand() % 100 + 1;
            L->next = p;
            L = p;
        }
        L->next = head;
    }
    
    //打印链表
    void cListPrint(cLinkList *L)
    {
        cLinkList *head, *p;
        head = L;
        p = L;
        int count = 1;
        while(p->next != head)
        {
            printf("%d	", p->data);
            p = p->next;
            count++;
        }
        printf("%d
    ", p->data);
        printf("The length of this LinkList is: %d
    ", count);
    }
    
    //检查是否有环(方法一)
    int cListCheckLoop1(cLinkList *L)
    {
        cLinkList *head, *p, *q;
        head = p = q = L;
        int countp, countq;
        countp = 1;
        while(1)
        {
            p=p->next;
            countp++;
            countq = 1;
            q = head;
            while(q != p)
            {
                q = q->next;
                countq++;
            }
            if(++countq != countp)
            {
                printf("YES!
    There is a loop in the LinkList!
    ");
                return 1;
            }
            if(p->next == NULL)
            {
                printf("NO!
    There is no loop in the LinkLis!
    ");
                return 0;
            }
        }
    }
    
    //检测链表是否有环(方法二)
    int cListCheckLoop2(cLinkList *L)
    {
        cLinkList *p, *q;
        p = q = L;
        while(p->next != NULL && p->next->next != NULL)
        {
            p = p->next->next;
            q = q->next;
            if(p == q)
            {
                printf("YES!
    There is a loop in this LinkList
    ");
                return 1;
            }
        }
        printf("NO!
    There is no loop in the LinkList
    ");
        return 0;
    }
    
    //清除链表
    void cListClear(cLinkList *L)
    {
        cLinkList *p, *temp;
        p = L->next;
        while(p != L)
        {
           temp = p;
           p = p->next;
           free(temp);
        }
    }
    
    //主函数
    int main()
    {
        int length = 10;
        cLinkList *L;
        L = (cLinkList *)malloc(sizeof(cLinkList));
        char operator;
        printf("1.生成链表(头插法)
    ");
        printf("2.生成链表(尾插法)
    ");
        printf("3.打印链表
    ");
        printf("4.判断链表是否有环(方法一)
    ");
        printf("5.判断链表是否有环(方法二)
    ");
        printf("6.清除链表
    ");
        printf("0.退出
    ");
        while(1)
        {
            scanf("%c", &operator);
            switch(operator)
            {
                case '1':
                    cListCreatHead(L, length);
                    printf("**********生成链表(头)!**********
    ");
                    break;
                case '2':
                    cListCreatTail(L, length);
                    printf("**********生成链表(尾)!**********
    ");
                    break;
                case '3':
                    printf("*************打印链表!*************
    ");
                    cListPrint(L);
                    break;
                case '4':
                    printf("***********是否有环(一)***********
    ");
                    cListCheckLoop1(L);
                    break;
                case '5':
                    printf("***********是否有环(二)***********
    ");
                    cListCheckLoop2(L);
                    break;
                case '6':
                    printf("*************清除链表!*************
    ");
                    cListClear(L);
                    break;
                case '0':
                    printf("***************退出*****************
    ");
                    free(L);
                    return 0;
            }
        }
        return 0;
    }
    
    

    github Githubhttps://github.com/haoyuanliu
    个人博客 个人博客http://haoyuanliu.github.io/

    个人站点,欢迎访问,欢迎评论!

  • 相关阅读:
    Struts2框架
    读者写者问题
    哲学家就餐问题
    理解中断
    理解处理机调度
    理解死锁
    理解进程
    Linux CentOS 6.7 挂载U盘
    家庭-养老院模型理解IOC和DI
    Bash基础
  • 原文地址:https://www.cnblogs.com/zuilehongdou/p/5527818.html
Copyright © 2020-2023  润新知