循环链表(约瑟夫问题的衍生问题)

问题描述:

编号为1~N的N个人按顺时针方向围坐一圈,每个人持有一个密码(正整数,可以自由输入),开始任选一个正整数作为报数上限值M,从第一个人按照顺时针方向自1开始顺序报数,报到M时停止报数。报M的人出列,将他的密码作为新的上限值M,从他顺时针方向的下一个人开始从1报数,如此下去,直至所有人出列为止。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

struct node
{
	int data;
	struct node *next;
};

node * create(int n);
node * createRandom(int n);
void printList(node *p, int n);
void ysfProblem(node *);
node * createRear(int n);
node * connect(node *a, node *b);

int main()
{
	int len1=0, len2=0 ,n = 0;
	int i =0;
	node *a, *b;
	printf("请输入您想要创建的表的长度:\n");
	cin >> n;
	node *p = createRandom(n);
	printList(p, n);
	ysfProblem(p);

	//创建两个尾指针的循环链表
	//while (i != 2)
	//{
		printf("(尾指针)请输入表1的长度:\n");
		cin >> len1;
		a= createRear(len1);
		printf("表1的第一个节点为: %d\n",a->next->data);

		printf("(尾指针)请输入表2的长度:\n");
		cin >> len2;
		b = createRear(len2);
		printf("表2的第一个节点为: %d\n", b->next->data);
		//AB[i]= createRear(len);
		//i++;
	//}
	//连接表1和表2
	node *r = connect(a, b);
	printf("连接后的表1和表2:\n");
	printList(r,len1+len2);
	printf("连接后的表的第一个节点为: %d\n", r->next->data);

	return 0;
}



//创建一个数据从1自增的循环链表,返回指向第一个节点的指针node *
node *create(int n) {
	node *p = NULL, *head;
	head = (node*)malloc(sizeof(node));//分配头结点(指向第一个节点)内存
	p = head;
	node *s = NULL;
	int i = 1;
	if (0 != n)
	{
		while (i <= n)
		{
			s = (node*)malloc(sizeof(node));
			s->data = i++;
			p->next = s;
			p = s;
		}
		s->next = head->next;//将最后一个节点指向第一个节点
	}
	free(head); //当表创建完成以后,就可以释放掉指向第一个节点的指针了,因为通过最后一个节点可以访问到第一个节点
	return s->next;
}

//创建一个数据可自己输入的循环链表,返回指向第一个节点的指针node *
node *createRandom(int n) {
	node *p = NULL, *head;

	//分配一个node大小的空间,并把分配的空间的首地址强制转换成node *指针类型
	//执行完毕后head指针将指向该首地址
	head = (node*)malloc(sizeof(node));

	p = head;
	node *s = NULL;
	int i = 1;
	int input = 0;
	if (0 != n)
	{
		printf("请依次输入%d个正整数:\n", n);
		while (i <= n)
		{
			cin >> input;
			s = (node*)malloc(sizeof(node));
			s->data = input;
			p->next = s;
			p = s;
			i++;
		}
		s->next = head->next;//将最后一个节点指向第一个节点
	}
	free(head); //当表创建完成以后,就可以释放掉指向第一个节点的指针了,因为通过最后一个节点可以访问到第一个节点
	return s->next;
}


//创建一个返回尾指针(指向链表的最后一个节点)的循环链表
node * createRear(int n)
{
	node *p = NULL, *rear = NULL, *head;
	//p = (nodeRear *)malloc(sizeof(nodeRear));
	head = (node *)malloc(sizeof(node));
	//rear = (node *)malloc(sizeof(node));
	p = head;
	node *s = NULL;
	int i = 1, input = 0;
	if (n != 0) {
		printf("请依次输入%d个正整数:\n", n);
		while (i <= n)
		{
			cin >> input;
			s = (node *)malloc(sizeof(node));
			s->data = input;
			p->next = s;
			p = s;
			i++;
		}
		rear = p;
		rear->next = head->next;
	}
	free(head);
	return rear;
}

//连接两个以尾指针创建的链表
node * connect(node *a, node *b)
{
	node *temp = a->next;
	a->next = b->next;
	b->next = temp;
	free(temp);  //不要忘记释放创建的临时结点!!
	return b;
}

//打印第一个节点为p的长度为n的表
void printList(node *p, int n)
{
	printf("最初的顺序是:\n");
	for (int j = 1; j < n; j++)
	{
		printf("%d->", *p);
		p = p->next;
	}
	printf("%d\n", *p);
}

//约瑟夫问题,和其衍生问题
void ysfProblem(node *p) {
	//m %= n;
	node *temp = NULL;
	int first = 0;
	printf("请选择一个初始上限值M:\n");
	cin >> first;
	int m = first;
	printf("删除顺序是:\n");
	while (p != p->next) //终止条件!!
	{
		if (m == 1)
		{
			m = p->data;
			printf("%d->", p->data);//打印被删除的节点的数据
			temp->next = p->next;
			p = p->next; //将p指向下一个节点
		}
		else
		{
			//从p指向的节点开始,顺序读取到第m-1个节点
			for (int i = 1; i < m - 1; i++)
			{
				p = p->next;
			}
			m = p->next->data;
			if (m == 1)
				temp = p;
			printf("%d->", p->next->data);//打印第m个节点的数据
			p->next = p->next->next;//删除第m个节点
			p = p->next; //将p指向被删除的那个人的下一个人
		}

	}
	//当最后只剩一个人时,打印
	printf("%d\n", p->data);
}


测试结果:


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值