首页 > 其他分享 >C语言解决约瑟夫环(PTA链表)

C语言解决约瑟夫环(PTA链表)

时间:2024-10-19 20:48:09浏览次数:8  
标签:node current 结点 last int PTA next 链表 C语言

题意:就是 N个人围成一个圈(想到循环),开始报数,报到一个指定的数p,则这个人出局,后延,比如本题的样例,第三个人报了3,则第四个人继续从1开始报数,一直循环下去,第七个人报完之后,再到第一个人,直到只剩下一个人,那么下一个出局的只剩下这个人。

解题思路:我们看到,最后一个人报数之后,又回到了第一个人开始报数,则可以使用循环链表,首先建立循环链表,把各个结点存入,最后一个结点再连接到头结点,再写一个函数用来使得某人出局,抽象到链表中也就是删除某个结点(出局的人),最后输入人数N和count(报数为count的人出局)。

首先定义结构体

其包括两个域,数据域和指针域。

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

 createCircularList函数:建立循环链表

 最需要注意也是最核心的即为把新结点插入到链表中 具体思路的可以看上一篇文章

node* createCircularList(int N)
{	//给头结点创建空间
	node *L=(node *)malloc(sizeof(node));
	//带头结点的链表
	L->next=NULL;
	//p与L指向头结点
	node *p=L;
	int i;
	//第几个人i就是几 通过1到N的循环将把i赋值给结点data域
	for(i=1;i<=N;i++)
	{
		node *s=(node *)malloc(sizeof(node));
		s->data=i;
		//新结点s连接到头结点之后
		s->next=p->next;
		p->next=s;
		//更新p的位置 便于后续完成收尾相接
		p=s;
	}
	//首尾相接 此时p是尾结点 next连接到头结点 完成首尾相连
	p->next=L->next;
	//创建之后 返回L
	return L;
}

 work函数(用于删除结点 即让某人出局)

ps:要注意free(shan)与其它代码的顺序 一定要先把准备工作做好(q指向current下一个 current顺延) 然后再free 

void work(node *L,int count)
{	//current指针为实质性的遍历链表的指针
	node *current=L->next;
	//因为我们要删除结点 所以需要得到要删除结点的前一个结点 即q
	node *q;
	int j;
	//last指针用来指向头结点 完成首尾相连
	node *last=current;
	//last遍历到最后一个结点 与currrnt指向相同时 说明到了最后一个结点 退出循环
	while(last->next!=current)
	{
		last=last->next;
	}
	//首尾相连
	last->next=current;
	//所有人从第一个人开始报数 直到剩下一个人 退出循环
	while(current->next!=current)
	{	//for循环表示每次更新q的位置 让其始终在current前一位 
		for(j=1;j<count;j++)
		{
		q=current;
		current=current->next;
		}
		//退出for循环 说明current对应的人报数为count 则将其输出
		printf("%d ",current->data);
		//字面意思  shan指针用来存储current指针 因为要将其free掉
		node *shan=current;
		//表示q连接到current下一个结点
		q->next=current->next;
		//某个人报数为count 继续进行 currrnt->next 表示开始下一个人报数
		current=current->next;
		free(shan);	
	}
	//退出while循环 表示current==current->next 即链表中只剩下一个元素 人数为1 直接输出
	printf("%d\n",current->data);
	//从题中可以知道 N个人全部出局 则将最后的current也free掉
	free(current);
}

 main函数

int main()
{
	int N,count;
	//此处if保证输入的两个数均为%d 否则不执行
	if(scanf("%d %d",&N,&count)==2)
	{
		node *L=createCircularList(N);
		 work(L,count);
		 return 0;
	}
}

 完整代码

#include <stdio.h>
#include <stdlib.h>
typedef struct node 
{	
    int data;
    struct node* next;
} node;
node* createCircularList(int N)
{
	node *L=(node *)malloc(sizeof(node));
	L->next=NULL;
	node *p=L;
	int i;
	for(i=1;i<=N;i++)
	{
		node *s=(node *)malloc(sizeof(node));
		s->data=i;
		s->next=p->next;
		p->next=s;
		p=s;
	}
	p->next=L->next;
	return L;
}
void work(node *L,int count)
{
	node *current=L->next;
	node *q;
	int j;
	node *last=current;
	while(last->next!=current)
	{
		last=last->next;
	}
	last->next=current;
	while(current->next!=current)
	{
		for(j=1;j<count;j++)
		{
		q=current;
		current=current->next;
		}
		printf("%d ",current->data);
		node *shan=current;
		q->next=current->next;
		current=current->next;
		free(shan);	
	}
	printf("%d\n",current->data);
	free(current);
}
int main()
{
	int N,count;
	if(scanf("%d %d",&N,&count)==2)
	{
		node *L=createCircularList(N);
		 work(L,count);
		 return 0;
	}
}

 运行结果

 

标签:node,current,结点,last,int,PTA,next,链表,C语言
From: https://blog.csdn.net/Zhao111111__/article/details/143083637

相关文章

  • C语言 【操作符(上)】
        最开始提到C语言操作符,我还是有一些不屑的,这玩意有啥学的呀?今天静下心来阅读学习了一下操作符部分的知识,这部分还真得认真学习学习!下面我将操作符中一些比较关键的点进行罗列和详细说明。一来帮助我加深理解,二来希望能帮助到有缘点击进来的读者。1、算术操作符:+ ......
  • C语言经典游戏代码大全(珍藏版)
    前言发现很多朋友都想要一些小项目来练手,却找不到从哪里寻找,给大家整理了游戏项目开发源代码汇总。一、最经典游戏之俄罗斯方块#include<iostream>#include<math.h>#include<Windows.h>#include<conio.h>#include<ctime>usingnamespacestd; enumDIR{   UP......
  • Linux C语言TCP协议实战
    文章目录1.TCP简介2.搭建框图3.相关函数介绍3.1socket函数3.2bind函数3.3listen函数3.4accept函数3.5connect函数3.6send函数3.7recv函数3.8其他函数4.实战4.1一对一模型4.1.1server.c4.1.2client.c4.1.3终端结果4.2多进程模型4.2.1server.c4.2.2cl......
  • 汉诺塔问题和青蛙跳台阶问题(c语言)
     这俩道题都是利用到了函数递归的思想,其中汉诺塔问题较难理解,青蛙跳台阶则较简单汉诺塔问题题述:设有三根柱子分别时A,B,C,在A柱子上放着n个盘子,每个盘子大小不一样,从下往上盘子大小依次减小,要求将A柱子上的盘子移动到C柱,且不改变盘子顺序(由大往小排序)。规则:1.一次只能......
  • 代码随想录算法训练营第四天| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点
    1.leetcode24两两交换链表中的节点题目链接:24.两两交换链表中的节点-力扣(LeetCode)文章链接:代码随想录(programmercarl.com)视频链接:帮你把链表细节学清楚!|LeetCode:24.两两交换链表中的节点_哔哩哔哩_bilibili1.1代码这个代码是用循环的思路来进行判断的,写的过程挺......
  • LeetCode 707 - 设计链表
    题目描述你可以选择使用单链表或者双链表,设计并实现自己的链表。单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 ......
  • 【C语言】动态内存管理(上)
    本篇博客将讲解以下知识点:(1)为什么要有动态内存分配(2)malloc和free1、为什么要有动态内存分配我们已经掌握的内存开辟方式有:intval=40;//向内存中申请4个字节空间存储valchararr[10];//向内存申请10个字节空间 上述的开辟空间的方式有两个特点:(1)空间的开辟......
  • 【C语言】strncat、strncmp、strstr函数讲解
    本篇博客将讲解函数:strncat、strncmp、strstr函数注意:使用strncat、strncmp、strstr函数时要包含头文件:string.h1、strncat函数的使用(是从目标空间中第一个的‘\0’位置开始追加的)strncat函数原型: char*   strncat(char*destination,  const char* sourc......
  • 利用iptables实现端口映射(支持动态域名)
    将下列代码保存到/bin/ddns_portmap.sh#!/bin/bash#检查参数if["$#"-ne2];thenecho"Usage:$0<domain><local_port1:remote_port1,local_port2:remote_port2,...>"exit1fi#从参数获取动态域名和端口映射domain=$1port_mappings=$2#获取......
  • c语言语法(76-79)10.19
    一.定义数组1.数组定义:2.数组的特点:补:数组内部的特点:左值是读,右值是写3.数组的下标:从0开始计数4.有效的下标范围:从0开始到数组的大小-1的范围当出现以下标志表示数组的下标越界:eg.此代码中的10超过了有效下标9,所以无效会报错二.数组的例子1.eg题目:代码:三.......