约瑟夫循环问题的解答

约瑟夫环问题(Josephus)  

原题:  

  

 用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。(约瑟夫环问题 Josephus)  

  

提示:  

  

    由于当某个人退出圆圈后,报数的工作要从下一个人开始继续,剩下的人仍然是围成一个圆圈的,可以使用循环表,由于退出圆圈的工作对应着表中结点的删除操作,对于这种删除操作频繁的情况,选用效率较高的链表结构,为了程序指针每一次都指向一个具体的代表一个人的结点而不需要判断,链表不带头结点。所以,对于所有人围成的圆圈所对应的数据结构采用一个不带头结点的循环链表来描述。设头指针为p,并根据具体情况移动。  

下面是我写的一种答案,对内存有两种申请方式,一种是懒汉方式,一种是饱汉方式,大家可以自行确定,只是要注意其释放内存的差别。

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

#define DATALEN 20
typedef enum eret
{
	SUCCESS,
	ERROR_MEMORY
}eret;

typedef struct list_node
{
	int data;
	list_node* next;
}list_node;

/*
 *懒汉方式,需要时才申请内存
*/
eret init_list_node_one(list_node* &pListIn,int len)
{
	int tmp = 0;
	list_node* iterator = NULL;
	
	pListIn = (list_node*)malloc(sizeof(list_node));
	iterator = pListIn;
	tmp = rand();
	iterator->data = tmp;
	iterator->next = iterator;
 
	for (int i = 0;i < len -1;i++)
	{
	 	tmp = rand();
	 	list_node* p = (list_node*)malloc(sizeof(list_node));
	 	if (!p)
	 	{
	 		printf("error memory\n");
	 		return ERROR_MEMORY;
	 	}
	 	p->data = tmp;
	 	iterator->next = p;
	 	p->next = pListIn; 
	 	iterator = p;
	}
	
	return SUCCESS;
}

/*
 *饱汉方式,一次申请足够的内存
*/
eret init_list_node_two(list_node* &pListIn,int len)
{
	int tmp = 0;
	list_node* iterator = NULL;

	pListIn = (list_node*)malloc(len * sizeof(list_node));
	iterator = pListIn;
	for (int i = 0; i < len; i++)
	{
		tmp = rand();
		iterator->data = tmp;
		if (i < len - 1)
		{
			iterator->next = iterator + 1;
			iterator = iterator->next;
		}
		iterator->next = pListIn;
	}

	return SUCCESS;
}

/*
 *懒汉方式时的约瑟夫循环查找,找到一个就释放其内存,
 *注意还有最后一个在循环结束后打印
*/
eret josephos_one(list_node* node,int m,int n)
{
	m %= n;
	list_node* m_pList = node;
	while (m_pList != m_pList->next)
	{
		for (int i = 0; i < m-1;i++)
		{
			m_pList = m_pList->next;
		}
		printf("data:%d\n",m_pList->next->data);
		list_node* tmp = m_pList->next;
		m_pList->next = tmp->next;
		m_pList = m_pList->next;
		free(tmp);
	}
	
	printf("data:%d\n",m_pList->data);
	free(m_pList);

	return SUCCESS;
}
/*
 *饱汉方式时的约瑟夫循环查找,先不释放其内存,
 *注意还有最后一个在循环结束后打印
*/
eret josephos_two(list_node* node,int m,int n)
{
	m %= n;
	list_node* m_pList = node;
	while (m_pList != m_pList->next)
	{
		for (int i = 0; i < m-1;i++)
		{
			m_pList = m_pList->next;
		}
		printf("data:%d\n",m_pList->next->data);
		list_node* tmp = m_pList->next;
		m_pList->next = tmp->next;
		m_pList = m_pList->next;
		//free(tmp);
	}
	
	printf("data:%d\n",m_pList->data);
	//free(m_pList);
	
	return SUCCESS;
}

eret display(list_node* node)
{
	list_node* m_pList = node;
	printf("data:%d\n",m_pList->data);
	m_pList = m_pList->next;
	while (m_pList != node)
	{
		printf("data:%d\n",m_pList->data);
		m_pList = m_pList->next;
	}

	return SUCCESS;
}

int main(int argc, char* argv[])
{
	list_node *node;
	int m = 0,n = 0;

	eret ret = init_list_node_two(node,DATALEN);
	if (ret != SUCCESS)
	{
		printf("init_list_node error,%d\n",__LINE__);
		return -1;
	}

	display(node);

	printf("input m and n:\n");
	scanf("%d%d",&m,&n);

	ret = josephos_two(node,m,n);
	if (ret != SUCCESS)
	{
		printf("josephos error,%d\n",__LINE__);
		return -2;
	}

	//这里的free是针对第二种内存申请的释放,貌似对于内存的申请是整取就需要整放
	free(node);
	system("pause");
	return 0;
}

data:41

data:18467

data:6334

data:26500

data:19169

data:15724

data:11478

data:29358

data:26962

data:24464

data:5705

data:28145

data:23281

data:16827

data:9961

data:491

data:2995

data:11942

data:4827

data:5436

input m and n:

3 4

data:26500

data:29358

data:28145

data:491

data:5436

data:19169

data:24464

data:9961

data:41

data:11478

data:16827

data:18467

data:5705

data:4827

data:23281

data:15724

data:6334

data:26962

data:11942

data:2995

    原文作者:约瑟夫环问题
    原文地址: https://blog.csdn.net/wenchao126/article/details/7934762
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞