约瑟夫环问题

约瑟夫环问题就是从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开

始报数,数到m的那个人又出列;计算出最后留下来的那个人的编号。

下边给出两种方法,顺序表实现和链表实现

链表的代码:

typedef struct LinkNode
{
	DataType data;
	struct LinkNode *next;
}LinkNode,*pLinkNode;
typedef struct LinkList
{
	LinkNode *pHead;
}LinkList,*pLinkList;
pLinkNode JosephCircle(pLinkList pList,int k,int m)//从k开始计数,数到m出列
{
	assert(pList);
	if (NULL == pList->pHead)
	{
		printf("空链表\n");
		return NULL;
	}
	pLinkNode cur = pList->pHead;
	pLinkNode del = NULL;
	while (--k)
	{
		cur = cur->next;
	}
	while (cur->next != cur)
	{
		int tmp = m;
		while (--tmp)
		{
			cur = cur->next;
		}
		printf("要删除的元素是%d\n",cur->data);
		del = cur->next;
		cur->data = cur->next->data;
		cur->next = cur->next->next;
		free(del);
	}
	return cur;
}


顺序表代码:

#define _CRE_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
void Joscircle(int n, int k, int m)
{
	int *p = (int *)malloc(n*sizeof(int));
	int i = 0;
	int out = 0;
	int count = 0;//用来计数,当count达到m时,所数到的人出列
	for (i = 0;i < n;i++)
	{
		*(p + i) = 1;//所有的人都被赋值为1,要是有人出列,将其值改为0
	}
	i = k - 1;//
	while (out != n - 1)
	{
		if (p[i] == 1)//如果该人所在的位置为1,说明此人还在队伍中,计数时就可以包括他
			count++;
		if (count == m)//如果数到某个人时,count刚好为m,此时,此人出列,将其所对应的数改为0
		{
			p[i] = 0;
			count = 0;
			out++;//出伍的人数加1
		}
		i++;
		if (i == n)//由于总共n个人,数组下标的i从0到n-1,如果数到n,我们就将其置为0
		{
			i = 0;
		}
	}
	for (i = 0;i < n;i++)
	{
		if (p[i])//那个没有被改为0的数对应的人就是最终没有出列的人
		{
			printf("第%d个人最终没有出列",i+1);
		}
	}
	free(p);
}
int main()
{
	Joscircle(10,2,3);//10个人围成一圈,从第二个人开始数数,数到3的那个人出列
	system("pause");
	return 0;
}


你可能感兴趣的:(约瑟夫环)