(C语言)构造循环链表解决约瑟夫问题

本文介绍了一个使用循环链表实现约瑟夫问题的解决方案。通过建立一个包含m个节点的循环链表,每个节点的数据域从1到m进行编号。程序实现了链表的创建、遍历,并按特定规则移除节点直至剩下最后两个节点。
//循环链表解决josephus问题 m个人1-3循环报数,数到3的人自杀,最后剩余2个人结点数据
#include<stdio.h>
#include<malloc.h>

typedef struct Queue_LinkList
{
	int data;
	struct Queue_LinkList *next;
}Node,*pNode;

typedef struct LinkList
{
	pNode front;
	pNode rear;
	int size;
}List,*pList;

void InitList(pList);			 //初始化链表
void Creat(pList,int);			//建立一个长度为m的链表,数据域分别赋值为1到m
void Traverse(pList);			//遍历
void Delete(pList);			//删除数到3的结点

int main()
{
	int m;
	List s1;
	printf("请输入人数: ");
	scanf("%d",&m);
	InitList(&s1);
	Creat(&s1,m);
	Traverse(&s1);
	Delete(&s1);
	Traverse(&s1);

	return 0;
}

//初始化
void InitList(pList ps1)
{
	ps1->front=(pNode)malloc(sizeof(Node));
	ps1->rear=(pNode)malloc(sizeof(Node));
	ps1->front->next=ps1->rear;
	ps1->rear->next=ps1->front;
	ps1->size=0;
	return;
}

//创建链表(头插法)
void Creat(pList ps1,int m)
{
	pNode p;
	while(m>0)
	{
		p=(pNode)malloc(sizeof(Node));
		p->data=m;
		p->next=ps1->front->next;
		ps1->front->next=p;
		ps1->size++;
		m--;
	}
	return;
}

//遍历
void Traverse(pList ps1)
{
	pNode p;
	if(ps1->front->next==ps1->rear)
		printf("链表为空!\n");
	else
	{
		printf("遍历结果为: ");
		for(p=ps1->front->next;p!=ps1->rear;p=p->next)
			printf("%d ",p->data);
		printf("\n");
	}
	printf("链表长度为: %d",ps1->size);
	printf("\n");
	return;
}

//删除数到3的结点
void Delete(pList ps1)
{
	int i;
	pNode p,q;
	p=ps1->front->next;
	for(i=0;ps1->size>2;i=(i+1)%3)
	{
		if(p==ps1->rear)				//若p指向尾结点,则将其指向第一个结点
			p=p->next->next;
		if(p==ps1->front)
			p=p->next;
		if(i==1)
		{
			if(p->next==ps1->rear)			//若删除的结点为链表的第一位
			{
				q=ps1->front->next;
				ps1->front->next=q->next;
				printf("被删除的元素为: %d\n",q->data);
				free(q);
				q=NULL;
				ps1->size--;
			}
			else
			{
				q=p->next;
				p->next=q->next;
				printf("被删除的元素为: %d\n",q->data);
				free(q);
				q=NULL;
				ps1->size--;
			}
		}
		else p=p->next;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值