单向循环链表求解约瑟夫问题

本文介绍了约瑟夫问题的解决方案,使用循环链表模拟过程,包括创建单向循环链表、删除指定位置的结点以及遍历链表。通过算法实现展示了如何处理编号的人从1开始计数,达到一定数值时出列的问题。
摘要由CSDN通过智能技术生成

一、约瑟夫问题

        设编号分别为:1,2,...,n的n个人围坐一圈。约定序号为k(1<=k<=n)的人从1开始计数,数到m的那个人出列,他的下一位又从1开始计数,数到m的那个人又出列,依次类推,直到所有人出列为止。

二、算法思路

        用一个不带头结点的循环链表来处理约瑟夫问题:先构成一个有n个结点的单循环链表,然后从第k结点起从1计数,记到m时。对应结点从链表中删除;然后再从被删除节点的下一个节点起又从1开始计数.....,直到所有节点都出列。

三、算法实现

1,创建单向循环链表

linklist create_list(void ){
    int a=0;
    linklist H,r,p;
    loop:
    printf("please input a\n");
    scanf("%d",&a);//输入单向循环链表的结点数量a,a的值需要大于0,如果a小于等于0,则重新输入
    if(a<=0)  {
        printf("a>0");
        goto loop;
    }


    H= malloc(sizeof(listnode));//根据约瑟夫问题,创建第一个结点,并让其数据域为1
    if(!H){
        printf("malloc failed\n");
        return NULL;
    }
    r=H;
    H->data=1;
    H->next=H;//只有一个结点的单向循环链表



    //循环插入其他结点并给数据域赋值
    for (int i = 2; i<=a ; i++) {
        p= malloc(sizeof(listnode));//为新结点开辟空间
        if(!p){//判断是否开辟成功
            printf("malloc failed\n");
            return NULL;
        }
        p->data=i;//赋值
        r->next=p;//插入
        r=p;
    }
    p->next=H;//最后一个节点的next域指向第一个结点,形成闭环
    return H;
}

2、删除结点

void operate_list(linklist H,int k,int m){
    linklist p,r;
    p=H;
    while (p->next->data!=k){//寻找起始节点的前一个节点,方便进行删除操作
        p=p->next;
    }
    while(p->next!=p){//代跑指针指向自己时,则链表只剩最后一个元素,结束循环
        int a=0;
        while (a<m-1){//寻找出列节点的前驱
            a++;
            p=p->next;
        }
        r=p->next;//删除出列结点
        p->next=r->next;
        printf("%d\n",r->data);
        free(r);
    }
    printf("%d\n",p->data);//打印仅存的一个结点
    free(p);
    p=NULL;
}

3,遍历并打印单向循环链表(此操作与解题无关,只为检查单向循环链表的创建)

void show_list(linklist H){
    linklist p;//创建一个指针代跑,遍历链表
    p=H;
    while (p->next!=H){//循环链表,结束条件为p->next==H
        printf("%d\n",p->data);
        p=p->next;
        //遍历,指针后移!!!!!!!
    }
    printf("%d",p->data);//打印最后一个元素
}

结束,感谢观看!!!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值