栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

约瑟夫环C语言链表实现

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

约瑟夫环C语言链表实现

        约瑟夫环:设编号分别为1、2、3....、n的n个人围坐一圈,提前约定编号为k(1≤k≤n)的人从1开始计数,数到m的那个人淘汰出局,他的下一个人又从1开始计数,数到m的人再淘汰出局,依次类推,直到最后只剩一个人,他将获得胜利。
设n=8,k=3,m=4时,如下图

 则淘汰序列为:6、2、7、4、3、5、1、8
最终存活者编号为8


算法思路:用头插法构建一张单向循环链表,结点内保存的数据即为编号。首先找到第k个结点,然后开始从1计数,计到m时删除该结点;然后从被删除结点的下一结点起又从1计数,直到最终只剩一个结点时循环结束,输出最终存活者编号。

以下为源代码,另外包含单向循环链表的一些基本操作和链表合并等

#ifndef _LIST_
#define _LIST_
#include 
#include 

typedef int data_t;
typedef struct linklist
{
    data_t data;//数据域
    struct linklist *next;//指针域
}LinkList;

//创建头节点
LinkList *Creat_Linklist();
//判空
int Linklist_Is_Empty(LinkList *h_node);
//求表长
int Linklist_length(LinkList *h_node);
//从表头插入数据
void Linklist_Insert_head(LinkList *h_node,data_t data);
//打印
void Linklist_Show(LinkList *h_node);
//两表合并
void lianjie(LinkList *linka,LinkList *linkb);
//约瑟夫环
void yuesefu(LinkList *head,int,int,int);
#endif
#include "list.h"
//创建头节点
LinkList *Creat_Linklist()
{
    LinkList *head=(LinkList*)malloc(sizeof(LinkList));
    if(NULL==head)
    {
        printf("malloc error!n");
        return NULL;
    }
    head->data=-1;
    head->next=head;
    return head;
}
//判空
int Linklist_Is_Empty(LinkList *h_node)
{
    if(h_node->next==h_node)return 0;//表空返回0
    else return 1;
}
//求表长,为有效数据节点个数(即除去头节点)
int Linklist_length(LinkList *h_node)
{
    int len=0;
    LinkList *p=h_node->next;//p指向头节点后的第一个节点
    while(p!=h_node)
    {
        len++;
        p=p->next;

    }
    return len;
}
//打印
void Linklist_Show(LinkList *h_node)
{
    if(Linklist_Is_Empty(h_node)==0)
    {
        printf("表为空,无法打印n");
        return ;
    }
    LinkList *p=h_node->next;//p指向头节点后的第一个节点
    while(p!=h_node)
    {
        printf("%d,",p->data);//打印数据
        p=p->next;

    }
    puts("");
}
//头插法
void Linklist_Insert_head(LinkList *h_node,data_t data)
{
    LinkList *p=(LinkList *)malloc(sizeof(LinkList));
    if(NULL==p)
    {
        printf("malloc new node error!n");
        return ;
    }
    p->data=data;//存数据

    p->next=h_node->next;//新节点拿到下一节点的地址
    h_node->next=p; //上一节点刷新得到新节点的地址
}
//两链表的合并
void lianjie(LinkList *linka,LinkList *linkb)
{
    LinkList *p,*q;
    p=linka->next;
    q=linkb->next;
    while(p->next!=linka)
    {
        p=p->next;
    }
    while(q->next!=linkb)
    {
        q=q->next;
    }
    p->next=linkb->next;
    q->next=linka;

    linkb->next=linkb;
}
//约瑟夫环
void yuesefu(LinkList *head,int n,int k,int m)
{
    LinkList *q=NULL;
    Linklist_Insert_head(head,n);//先头插一个结点,即尾结点
    q=head->next;//保存尾结点地址,用于后面头尾连接
    while(--n)
    {
        Linklist_Insert_head(head,n);
    }
    Linklist_Show(head);//打印编号
    q->next=head->next;//最后一个节点连上第一个节点
    q=head->next;//重置q,用于后面指向起始结点
    free(head);//释放头结点
    while(--k)
    {
        q=q->next;
    }
    printf("起始结点编号=%dn",q->data);
    LinkList *temp=NULL;//用于删除目标结点
    int count;//用于每轮计数
    while(q->next!=q)
    {
                
        count=m-1;
        while(--count)
        {
            q=q->next;
        }
        temp=q->next;//指向目标结点
        printf("%d,",temp->data);//打印淘汰者编号
        q->next=temp->next;//删除目标节点
        free(temp);//释放目标节点

        q=q->next;//指向新起始节点
    }
    printf("n最后存活者编号%dn",q->data);
}




#include "list.h"
int main(int argc, char *argv[])
{     
    //约瑟夫环 
    int n,k,m;
    printf("请输入人数 起始序号 次数n");
    scanf("%d%d%d",&n,&k,&m);
    printf("n=%d,k=%d,m=%dn",n,k,m);

    LinkList *head=Creat_Linklist();
    yuesefu(head,n,k,m);
    return 0;
} 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1029160.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号