约瑟夫环问题

约瑟夫环问题

(这是一个比较简单的链表入门小练习,记录一下整个学习和代码进步的过程。)

题目

问题描述为:编号为1,2,3,,,,n的n个人按顺时针方向为坐在一张圆桌周围,每人持有一个密码(整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始报数,报到m时停止报数,报m的那个人出列,将其密码作为新的m值,并从顺时针方向的下一个人开始重新从1报数,数到m的那个人又出列;如此下去,直到圆桌的人全部出列为止。

分析

算法分析实现,在这里采用单项循环链表的数据结构,因为要进行反复的删除操作;令链表的尾指针指向首元素的地址。每个人的信息作为一个节点,此节点中存储着他们的编号和密码。在下面的代码中,编号我用id表示,密码用了secret(其实是密码的英语单词在写的时候没想起来,,,,,就用了个秘密,,,?),每个节点除了指针域以外,还有两个域存储编号和密码。

思路分析
  1. 因为有n个人,所以第一步建立n个节点的单项循环链表。因此我们要写一个创建单链表的函数,输入编号和与之对应的密码,[然后打印出链表(整个的信息),可以选作,为了观察方便,思路更清晰还是写一下比较好~]
  2. 从链表的第一个节点开始循环找寻下一个节点,即循环到m的那个人。
  3. 输出该节点的id(对应编号),将该节点的secret(密码)作为新的m值循环下去,并删除该节点。所以此处我们需要写一个根据m值循环获取新节点的函数。
  4. 根据m值不断从链表中删除节点,直到链表为空。所以我们要有对应的判空操作。

自定义的结构体类型
typedef struct Node
{
int id; //编号
int secret; //对应密码
struct Node *next;
}Node;

函数
void Creatlist(Node **,int);
void Printlist(Node *);
Node *GetNode(int ,int);
void Runninglist(Node **,int);

完整代码块
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 50
typedef struct Node
{
    int id;                 //编号
 int secret;        //对应密码
 struct Node *next;
}Node;
void Creatlist(Node **,int); 
void Printlist(Node *);
Node *GetNode(int ,int);
void Runninglist(Node **,int);
int main(void)
{
  	int m,n;      //m是初始密码,n为人个数
  	m=n=0;
  	Node *pHead =NULL;
  	do
      {
   	if (n<MAXSIZE)
   	{
     		//输入人数 
     		//printf("输入人数");
     		scanf("%d",&n);
      	}
      }while(n>MAXSIZE);
    
    //printf("输入初始密码");
 	 scanf("%d",&m); 
 
   Creatlist(&pHead,n); 
   Printlist(pHead);
   Runninglist(&pHead,m);
   
  		return 1;
  }
     void Creatlist(Node **Head,int n)
{
 Node *pNew=NULL;        //创建循环链表Head
 Node *p=NULL;
 int i,Secret;
 for (i=1;i<=n;i++)
 {
  	scanf("%d ",&Secret);
  	pNew=GetNode(i,Secret);
  	if(*Head==NULL)
  	{
   		*Head=p=pNew;
   		p->next=*Head;
  	}
  	else
  	{
     	pNew->next=p->next;       
     	p->next=pNew;
     	p=pNew;
     	}
  }
}
Node *GetNode(int Id,int Secret)
{
 	Node *pNew=NULL;
 	pNew=(Node *)malloc(sizeof(Node));
 	if(!pNew)
 	{
  		exit(-1);
 	}
  	pNew->id=Id;                  //传送编号
  	pNew->secret=Secret;//传密码
  	pNew->next=NULL;
		return pNew;
}	
void Printlist(Node *pHead)//打印创建好的链表
{
 	Node *p;
 	p=pHead;
 	if(pHead==NULL)   //判读链表是否为空
 	{ 
 		printf("NULL");
 	}
 	else
 	{
  	do
  	{
   		printf("%d",p->secret);
   		//printf("%d %5d",p->id,p->secret);
   		p=p->next;
  	}  while(p!=pHead);
    }
  }
  void Runninglist(Node **Head,int Secret)      //运行
 {
  	int temp=0,x=1;
  	Node *pre,*pcur,*pdel;   //头尾删除
  	pre=pcur=pdel=NULL;
  	pre=pcur=*Head;

	while(pre->next!=*Head)
  	pre=pre->next;
  	while(x)
  	{
  		for(temp=1;temp<Secret;temp++)
    	{
     		pre=pcur;
     		pcur=pcur->next;
    	}
    		if(pre==pcur)  x=0;
     		pdel=pcur;
     		pre->next=pcur->next;
     		pcur=pcur->next;
     		Secret=pdel->secret;
  		//printf("出列");
		printf("%d",pdel->id);
     		//printf("No.%d个人出列,密码是%d\n",pdel->id,pdel->secret);
     		
		free(pdel);
	}
		*Head=NULL;
    		getchar();
   }

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值