约瑟夫环的问题

偶然想到约瑟夫环的问题,就试着编写代码实现一下。

首先介绍一下约瑟夫环的问题。

 

这个就是约瑟夫环问题的实际场景,有一种是要通过输入n,m,k三个正整数,来求出列的序列。这个问题采用的是典型的循环链表的数据结构,就是将一个链表的尾元素指针指向队首元素。pL->pTail->next=pL->head
解决问题的核心步骤:(程序的基本算法)
⒈建立一个具有n个链结点,无头结点的循环链表;
⒉确定第1个报数人的位置;
⒊不断地从链表中删除链结点,直到链表为空。
约瑟夫环链表方法的C语言实现:
 
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
	int data;
	struct Node* next;

}node;
typedef struct LinkList
{
	struct Node* pHead;
	struct Node* pTail;
}Linklist;

//初始化一个循环链表

struct LinkList* init_linklist()
{
	struct LinkList* p = (struct LinkList*)malloc(sizeof(struct LinkList));
	p->pTail = p->pHead =NULL;
    	return p;
}
void insert_linklist(struct LinkList** pL,int data )
{	
	struct LinkList* pl = *pL;
	struct Node* pN;
	pN = (struct Node*)malloc(sizeof(struct Node));
	if(!pN)
	{
		printf("申请空间失败!\n");
		return;
	}
	if(pl->pHead ==NULL&& pl->pTail ==NULL)
	{
		pl->pHead = pN;
		pl->pTail =pN;
		pl->pHead->next = pl->pTail;
		pl->pHead->data =data;
	
	}
	else 
	{
	pN->data =data;
	pN->next =pl->pHead;
	pl->pTail->next = pN;
	pl->pTail = pN;
	}

}
void delete_node(struct LinkList** pL,struct Node** pN)
{
	struct LinkList* pl = *pL;
	struct Node* pn;
	pn =pl->pHead;
	if(pl->pHead!=pl->pTail)
	{	
		while(pn->next!=(*pN))
			pn = pn->next;
		
		
		printf("pN->data = %d\n",(*pN)->data );//输出删除的结点数据	
		pn->next = (*pN)->next;
		if(*pN ==pl->pTail) //如果是循环的尾
			pl->pTail = pn;
		else if(*pN == pl->pHead)//如果是循环的头
			pl->pHead = pn->next;
		free(*pN);	
		*pN =pn->next;//指向下一个结点;
	}
	else 
	{
		printf("pN->data = %d\n",(*pN)->data);
		free(*pN);
		pl->pHead =NULL;
		pl->pTail =NULL;
		*pN =NULL;
	
	}

}
void show_linklist(struct LinkList** pL)
{
	struct LinkList* pl = *pL;
	struct Node* pn;
	pn = pl->pHead;
	if(pn!=NULL)
	{
		printf("所有的数据如下:");
		printf("\n%d\t",pn->data );

		pn = pn->next;
		while(pn!=pl->pHead)//输出剩余的数据
		{
			printf("%d\t",pn->data );
			pn= pn->next;
		}
		printf("\n");
	}
	else 
	{
			printf("\n约瑟夫环中没有数据了\n");
			return;
	}
	

}
int main()
{
	struct LinkList* pl =init_linklist();//初始化循环链表
	int n,k,m;//nums表示数据个数,k表示从当前位置开始

	struct Node* pn;
	printf("请依次输入n、m和k的值,n代表元素的个数,m表示从第几个元素开始报数,k代表每次前进的步数! \n");
	scanf("%d%d%d",&n,&m,&k);

	for(int i =1;i <= n; i ++ )
		insert_linklist(&pl,i);//插入数据
    //显示循环链表中的数据
	show_linklist(&pl);
	pn = pl->pHead;

	//从第m个开始报数
	for(i = 1; i< m;i++)
		pn= pn->next;
	while(pn!=NULL)
	{
		for(i =1;i< k; i++)
			pn = pn->next;
		delete_node(&pl,&pn);
		
	}
	show_linklist(&pl);	

	free(pl);//释放申请的内存空间
  
	return 0;		
}
vc++6.0上面编译运行,输入一个实例,结果如下:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值