一个改了版的约瑟夫

这个程序是通过约瑟夫问题进行改编。

利用循环链表,每个节点都有自己的ID,同时持有其他节点的ID。

每找到一个ID,就对其进行删除。

编译环境:vs2012

 

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

#ifndef NULL
#define NULL 0
#endif

enum BOOL
{
	FALSE, TRUE
};

typedef struct node
{
	int ID;					//每个节点的id
	int GetId;				//其他节点的id,通过这个可以查找下一个节点
	struct node *next;
}Node, *Link;

Link CreaList(int idmax);
Link GetNode(int id, int password);
Link StatGame(Link head, int passw, int idmax);
void Print(Link head);
int EmptyList(Link head);

/*************************************
名称:CreaList[初始化链表]
调用:Crealist(int idmax)
作用:生成并初始化一个用户设定大小的链表
参数:idmax,需要设定链表长度的值
返回:返回头指针
*************************************/
Link CreaList(int idmax)
{
	Link head, pnow, ptemp;
	int idnow = 1, pass;
	head = pnow = NULL;
	do
	{
		while(1)
		{
			printf("请输入当前节点的密码:");
			if ( scanf_s("%d", &pass, 1) == 1 )
			{
				break;
			}
			printf("输入错误,请重新输入\n");
		}

		ptemp = GetNode(idnow, pass);

		if(!head)
		{
			head = (Link)malloc(sizeof(Node));
			head->next = ptemp;
			pnow = ptemp;
		}
		else
		{
			pnow->next = ptemp;
			pnow = ptemp;
		}

		idnow = idnow + 1;
	}while (idnow <= idmax);

	//设置结尾指向头节点;
	pnow->next = head->next;
	free(head);

	return pnow->next;
}


/*************************************
名称:GetNode[获取节点]
调用:GetNode(int id, int password)
作用:生成,初始化节点并返回
参数:id,节点的序号。password,节点所持密码
返回:返回节点的指针
*************************************/
Link GetNode(int id, int password)
{
	Link tenode;
	tenode = (Link)malloc(sizeof(Node));

	//初始化
	tenode->ID = id;
	tenode->GetId = password;
	tenode->next = NULL;
	
	return tenode;
}


/*************************************
名称:StatGame[改版的约瑟夫]
调用:StatGame(Link head, int passw, int idmax)
作用:用约瑟夫自杀功能对链表操作
参数:head,要操作的链表节点
返回:返回操作后的头节点
*************************************/
Link StatGame(Link head, int passw, int idmax)
{
	Link tailpoint, pfree;
	int num = 0;
	int ifalg = 1;				//结束标志
	tailpoint = head;			//节点尾指针,删除某节点后,用来连接上一个节点。

	if(EmptyList(head))
	{
		printf("表空,无法进行!\n");
		exit(1);
	}

	while (ifalg)
	{
		passw = passw % idmax;
		while (passw != tailpoint->next->ID)
		{
			if (num>9)
			{
				printf("[木有找到或被删除。]\n");
				break;
			}

			tailpoint = tailpoint->next;
			num++;
		}

		pfree = tailpoint->next;
		tailpoint->next = pfree->next;		//将 a->b->c 变成 a->c,实现从链表中删除
		
		passw =  pfree->GetId;				//备份密码,用来查找下一个节点的指针

		printf("第%d个人出列,密码:%d\n", pfree->ID, pfree->GetId);

		//检测是否为最后一个结点
		if (pfree == tailpoint)
		{
			ifalg = 0;
		}

		free(pfree);						//释放才是真正的删除
		num = 0;

	}
	return tailpoint;

}

/*************************************
名称:Print[打印]
调用:Print(Link head)
作用:打印指定的循环链表
参数:head,链表头节点
*************************************/
void Print(Link head)
{
	Link temp;
	temp = head;

	if(EmptyList(head))
	{
		printf("表空,无打印数据!\n");
		return;
	}

	while (head->next != temp)
	{
		printf("%d ->", head->ID);
		head = head->next;
	}
	printf("%d", head->ID);


}


/*************************************
名称:EmptyList[空表检测]
调用:EmptyList(Link head)
作用:检测传入的循环链表是否为空;
参数:head,要检测的链表头节点
返回:如果为空返回true,反之false;
*************************************/
int EmptyList(Link head)
{
	if ( !head )
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}


int main()
{
	Link head;
	int idmax, password;

	printf("请输入要设定的链表长度:");
	scanf_s("%d", &idmax, 1);
	printf("请输入初始的密码:");
	scanf_s("%d", &password, 1);

	head = CreaList(idmax);

	printf("*****************当前链表数据*****************\n\n");
	Print(head);
	printf("\n\n");

	printf("*****************运行约瑟夫后*****************\n\n");
	head = StatGame(head, password, idmax);

	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值