【C语言】约瑟夫环(用单向循环链表解决)

约瑟夫环:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。这里我用单向循环链表来解决这个问题。

我们先考虑几种情况:

当m=1和k=1的时候,要挨个删除链表中的结点。

在k!=1和m=1的情况下,指针必须先向后移动到k的位置,并且记住k的前驱结点,以便删除结点不断链。

在k!=1和m!=1的情况下,此处我只让指针移动到了要删除结点的前驱结点处进行删除。

注意这里的每一种情况都没有完全的把链表删除,链表中还剩下一个 结点,即没有出列的那个人,我在这里依然将它输了出来。

代码如下:

 

#define _CRT_SECURE_NO_WARNINGS 1 
#ifndef _JOSEPH_H__
#define _JOSEPH_H__

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

typedef struct Joseph_ring
{
	int num;
	struct Joseph_ring* next;
}Joseph,*pJoseph;

pJoseph CreateJoseph(int n);
void joseph_r(pJoseph head, int k, int m);

#endif

函数实现:

 

 

 

#include"Joseph ring.h"

pJoseph CreateJoseph(int n)
{
	int i = 0;
	pJoseph head = NULL;
	pJoseph tail = NULL;
	head = (pJoseph)malloc(sizeof(Joseph));
	head->next = head;    //先让第一个结点head指向自己形成一个环
	head->num = 1;
	tail = head;
	for (i = 2; i <= n; i++)     //循环向环中插入结点
	{
		pJoseph New = (pJoseph)malloc(sizeof(Joseph));
		New->num = i;
		New->next = tail->next;
		tail->next = New;
		tail = New;
	}
	return head;
}

void joseph_r(pJoseph head, int k, int m)
{
	assert(head);
	pJoseph cur = NULL;
	pJoseph prev = NULL;
	pJoseph del = NULL;
	cur = head;
	if (k == 1 && m == 1)   //如果从第一个人开始,数到1就出列。
	{
		while (cur->next != head)
		{
			printf("%d ", cur->num);
			del = cur;
			cur = cur->next;
			free(del);
		}
		printf("%d\n", cur->num);
	}

	else if (k != 1 && m == 1)    //从第k个人开始报数,报到1的人出列。
	{
		while (cur->num != k)//找到第k个人的前一个
		{
			prev = cur;
			cur = cur->next;
		}
		while (head->next != head)
		{
			del = cur;
			prev->next = cur->next;
			cur = cur->next;
			printf("%d ", del->num);
			if (cur == head)
			{
				head = cur->next;
			}
			free(del);
		}
		printf("%d\n", head->num);
	}
	else
	{
		int i = 0;
		while (cur->num != k)//找到第k个人,从他开始报数
		{
			cur = cur->next;
		}
		while (head->next != head)
		{
			for (i = 1; i < m - 1; i++)  //找到要出列的人的前一个
			{
				cur = cur->next;        
			}                          //cur当前表示要出列的人的前一个
			del = cur->next;
			cur->next = del->next;
			printf("%d ", del->num);
			if (del == head)
			{
				head = del->next;
			}
			free(del);
			cur = cur->next;
		}
		printf("%d\n", head->num);
	}
}

测试部分:

 

 

 

#include"Joseph ring.h"

void test1()
{
	pJoseph head;
	head = CreateJoseph(10);
	joseph_r(head, 1, 1);
}

void test2()
{
	pJoseph head;
	head = CreateJoseph(10);
	joseph_r(head, 2, 1);
}
int main()
{
	pJoseph head;
	test1();
	test2();
	head=CreateJoseph(10);
	joseph_r(head, 2, 2);
	getchar();
	return 0;
}



 

  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值