鱼C论坛

 找回密码
 立即注册
查看: 3233|回复: 2

[技术交流] 有环链表的判断

[复制链接]
发表于 2015-3-27 17:22:52 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 spy 于 2015-3-27 17:30 编辑

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

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

struct Node *CreateList();
void ListTraverse(struct Node *);
int IsEmpty(struct Node *);
int ListLength(struct Node *);
void GenerateLoopListTail(struct Node *, int);
//int HaveLoop(struct Node *, int);
int HaveLoop2(struct Node *);
void DestroyList(struct Node *, int);

void main()
{
        struct Node *head = NULL;
        int n, i, len=0, j=0;
        char ch;
        printf("\n");
        printf("------------------------\n\n");
        printf(" 1.初始化链表\n 2.创建有环链表(尾插法)\n 3.判断链表是否有环\n 0.退出\n\n 请选择您的操作: ");
        scanf("%d", &n);
        putchar('\n');

        while(n)
        {
                switch(n)
                {
                case 1:
                        {
                                head = CreateList();
                                len = ListLength(head);
                                if(IsEmpty(head))
                                {
                                        printf("链表为空,请初始化链表!\n\n");
                                        break;
                                }
                                else
                                {
                                        ListTraverse(head);
                                        break;
                                }
                        }

                case 2:
                        {
                                if(IsEmpty(head))
                                {
                                        printf("链表为空,请初始化链表!\n\n");
                                        break;
                                }
                                else
                                {
                                        if(j)  //j=0,则创建有环链表, 否则重新输入
                                        {
                                while(1)
                                                {
                                                        printf("当前已经是有环链表, 是重新建立链表还是放弃当前操作?(Y/N)\n");
                                                        fflush(stdin);
                                                        ch = getchar();
                                                        putchar('\n');
                                                        if('Y'==toupper(ch))
                                                        {
                                                                j = 0;
                                                                DestroyList(&head, len);
                                                                head = CreateList();
                                                                if(IsEmpty(head))
                                                                {
                                                                        printf("链表为空,请初始化链表!\n\n");
                                                                        goto SELECT;
                                                                }
                                                                else
                                                                {
                                                                        ListTraverse(head);
                                                                        goto SELECT;
                                                                }
                                                        }
                                                        else
                                                                if('N'==toupper(ch))
                                                                {
                                                                        goto SELECT;
                                                                }
                                                                else
                                                                {
                                                                        printf("error!\n");
                                                                }
                                                }
                                        }
                                        printf("输入要形成环的结点位置\n");
                                        scanf("%d", &i);
                                        len = ListLength(head);
                                        while(i<1 || i>len-1)
                                        {
                                                printf("无法形成环, 是重新输入还是放弃当前操作?(Y/N)\n");
                                                fflush(stdin);             //之前输入的回车符还存在缓冲区,需要清除后缓冲区才能正确接受当前的输入
                                                ch = getchar();
                                                if('N'==toupper(ch))
                                                {
                                                        putchar('\n');
                                                        goto SELECT;
                                                }
                                                else
                                                        if('Y'==toupper(ch))
                                                        {
                                                                printf("输入要形成环的结点位置\n");
                                                                scanf("%d", &i);
                                                        }
                                                        else
                                                        {
                                                                printf("error!\n");
                                                        }
                                        }
                                        GenerateLoopListTail(head, i);
                                        j++;
                                        printf("有环链表已形成!\n\n");
                                }
                                break;
                        }
                case 3:
                        {
                                if(IsEmpty(head))
                                {
                                        printf("链表为空,请初始化链表!\n\n");
                                        break;
                                }
                                else
                                {
                                        //if(HaveLoop(head, len))
                                        if(HaveLoop2(head))
                                        {
                                                printf("有环, 环的位置在第%d个结点\n\n", i);
                                        }
                                        else
                                        {
                                        printf("无环\n\n");
                                        }
                                }
                                break;
                        }

                default:
                        {
                                printf("您的输入有误, 请重新输入选择菜单!\n\n");
                        }
                }

SELECT: printf("请选择您的操作: ");
                scanf("%d", &n);
                if(1==n && len!=0)
                {
                        DestroyList(&head, len);
                }
                putchar('\n');
        }
}

struct Node *CreateList()
{
        int n=1, value;
        struct Node * head=NULL;
        struct Node * p, *q;
        printf("输入结点的值, 输入0完成初始化\n");
        scanf("%d", &value);
        while(!value)
        {
                printf("至少需要输入一个元素, 重新输入还是放弃当前操作? (Y/N)\n");
                fflush(stdin);
                if('N'==toupper(getchar()))
                {
                        putchar('\n');
                        return head;
                }
                else
                {
                        printf("输入结点的值, 输入0完成初始化\n");
                        scanf("%d", &value);
                }
        }
        head = (struct Node *)malloc(sizeof(struct Node));
        p = head;
        while(value)
        {
                q = (struct Node *)malloc(sizeof(struct Node));
                q->data = value;
                p->next = q;
                p= q;
                scanf("%d", &value);
        }
        q->next = NULL;
        return head;
}

void ListTraverse(struct Node *head)
{
        struct Node *p = head;
        p = p->next;
        printf("**********链表中的元素**********\n");
        while(p)
        {
                printf("%5d", p->data);
                p = p->next;
        }
        printf("\n\n");
}

int IsEmpty(struct Node *head)
{
        if(NULL == head)
                return 1;
        else
                return 0;
}

void GenerateLoopListTail(struct Node *head, int i)
{
        struct Node *p = head, *q = NULL;
        int j = 0;
        while(p->next!=NULL)
        {
                while(++j<i)
                {
                        p = p->next;
                }
                if(j==i)
                {
                        q = p->next;
                }
                p = p->next;
        }
        p->next = q;

}

int ListLength(struct Node *head)
{
        struct Node *p = head;
        int i=0;
        if(IsEmpty(head))
        {
                return 0;
        }
        while(p->next)
        {
                p = p->next;
                i++;
        }
        return i;
}

/*int HaveLoop(struct Node *head, int len)
{
        struct Node *p=head, *q;
        int cur1=0, cur2;
        while(cur1<=len+1)
        {
                cur2 = 0;
                q = head;
                while(cur2<cur1 && p!=q)
                {
                        q = q->next;
                        cur2++;
                }
                if(p == q)
                {
                        if(cur2!=cur1)
                        {
                                return 1;
                        }
                        else
                        {
                                if(cur2==len+1)
                                {
                                        return 0;
                                }
                        }
                }
                p = p->next;
                cur1++;
        }
}
*/


//使用快慢指针, 效率较高
int HaveLoop2(struct Node *head)
{
        struct Node *p, *q;
        p = q = head;
        do
        {
                p = p->next;
                q = q->next->next;
        }while( p!=q && !(q->next==NULL || q->next->next==NULL) );
        if(p==q)
        {        
                return 1;
        }
        else
        {
                return 0;
        }
}

void DestroyList(struct Node **head, int len)
{
        struct Node *p, *q;
        int i=0;
        p = q = (*head)->next;
        while(++i<len)
        {
                q = p->next;
                free(p);
                p = q;
        }
        free(p);
        free(*head);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-5-19 18:33:25 | 显示全部楼层
谢谢分享!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-5-21 20:03:55 | 显示全部楼层
看看。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-25 05:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表