数据结构—单项循环链表解决约瑟夫问题

单向循环循环链表实现约瑟夫问题

X个人围成一圈,每个人手里都有不同的密码,选择一个人,从他开始,以他的密码为初始开始报数,如果有人报的数字为1,这个人退出并且以退出这个人手中的密码作为新的起始,直到所有人都出列他为止
在这里插入图片描述
在这里插入图片描述

单项循环链表实现

#include "stdafx.h"                          //头文件 不说了

struct man
{
	int num;									//序号
	int password;							//数据域
	struct man *next;						//指针域
};

typedef struct man Node;
typedef Node* Ptr;

int main()
{
	Ptr head;
	int num;
	Ptr CreatLink(int num);
	void Show(Ptr head, int num);
	printf_s("请输入人数:");
	scanf_s("%d", &num);
	head = CreatLink(num);
	Show(head, num);
	return 0;
}

Ptr CreatLink(int num)
{
	int i;																		
	Ptr head, previous, last;				//头,当前,尾指针


	head = (Ptr)malloc(sizeof(Node));			//给头结点分配空间
	if (head == NULL)						//创建失败报错
	{
		printf_s("wrong!");
		return NULL;
	}

	last = head;									//将头结点的地址赋值给尾结点

	for (i = 0; i < num; i++)					//循环输入所有人的密码放到对应的结点的对应数据域(对应的次序)
	{
		previous = last;							//把尾结点的地址复制到当前指针
		printf_s("请输入第%d个人的密码", i + 1);
		scanf_s("%d", &previous->password);		//把所的密码依次存入对应结点的数据区
		previous->num = i + 1;					//对应序号加一

		last = (Ptr)malloc(sizeof(Node));			//为last创建新的结点(为了存入新的数据)

		if (last == NULL)						//创建失败报错
		{
			printf_s("wrong!");
			return NULL;
		}
		previous->next = last;					//链接结点,使得上一个last结点(复制给previous)的指针域指向新的last结点
	}

	previous->next = head;						//循环结束,多余的结点不需要,最后一个结点直接指向头结点,形成循环
	free(last);									//释放多余的结点
	last = previous;								//最后一个结点复制给last结点
	return last;																
}

void Show(Ptr head, int num)
{	
	int num1, i, j;												//num1是报数的人的序号
	Ptr previous, last;											//当前指针和尾指针
	last = head->next;											//尾指针直接指向头指针的下一个结点
	previous = head;												//头指针复制给当前指针
	printf_s("请输入第一个报数的人:");
	scanf_s("%d", &num1);

	printf_s("输出顺序为:");

	for (i = num; i > 0; i--)										//人数递减
	{
		for (j = num1; j > 1; j--)									//密码递减
		{
			previous = last;											//尾指针成为当前指针
			last = last->next;										//下一个指针成为尾指针
		}
		previous->next = last->next;									//尾指针的下一个指针复制给当前指针的下一个指针
		printf_s("%d", last->num);									//打印尾指针的数据域的序号
		num1 = last->password;										//将尾指针数据域的密码赋值给num1;
		free(last);													//释放尾指针
		last = previous->next;										//将当前指针的指针域next指向尾指针
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值