题目描述
有 N 个人围成一圈,按顺时针给他们编号为 1-N。
紧接着,指定编号为 M 的人开始报数,报数按顺时针进行。
报到 D 的人出列,下一个人重新开始报数。按此规律,每次报到 D 的人都出列。
要求同学编程求出出列的顺序。
输入
输入包括多组测试用例。
对于每组用例,第一行是一个整数 N,表示人数。N<100。
接下来 N 行是每个人的人名。人名为长度不超过 20 连续字符串。
最后是以两个以","分割的整数 M,D。代表从 M 个人开始,每报 D 个数出列。
输出
输出所求的顺序
样例输入
8
Zhao
Qian
Sun
Li
Zhou
Wu
Zheng
Wang
4,4
样例输出
Zheng
Sun
Wang
Zhou
Li
Wu
Qian
Zhao
题目分析
另外我必须来说一下,怎样让游标可以在name数组中循环,也就是当指向最后一个数据之后,又会重新回到数组的开头进行循环轮替
(cur + 1) % n 这样一个代码就可以实现,比如当cur游标处在数组中最后一个位置的时候,也就是n-1这样一个位置,也就是说当前游标的下一个游标就是(n - 1 + 1) % n,也就是0,这个时候游标又回到了开头
代码实现
demo1.cpp
#include
#include
#include
#include using namespace std;int main()
{int total_num;//总人数int start_num;//最起始位置int end_num;//每次结束报数位置char str[21] = {'\0'};//控制下整体的大循环while(scanf("%d",&total_num) != EOF) {//每次进来定义一个容器queue q;//循环往里面放值while(total_num > 0) {scanf("%s",str);//输入之后入栈q.push(str); total_num--;}//按照思路,先把第一个开始报数的人找到scanf("%d,%d",&start_num,&end_num);string top_elem;for(int i = 0;i < start_num - 1;i++) {//把除了第一个之外的数据都放到队列尾巴上面去top_elem = q.front();//栈顶元素q.pop();q.push(top_elem);}//开始整体执行判断操作while(q.size()) { //下面开始进行报数找人for(int j = 0;j < end_num;j++) {//还是上面的方法top_elem = q.front();//拿到栈顶往后放q.pop();q.push(top_elem); }//上面循环完了,此时栈顶元素就是我们想要的数printf("%s\n",q.front().c_str());//并且把这个数据给出栈掉q.pop();}}return 0;
}
demo2.cpp
#include
#include
#include int len = 0;typedef struct _node{char name[21];struct _node *next;
}node;node *init_node()
{node *p_head = (node *)malloc(sizeof(node));if(p_head != NULL) {//memset(p_head->name,'\0',sizeof(p_head->name));strcpy(p_head->name,"我是头结点");p_head->next = p_head;//循环链表指向自己}return p_head;
}void insert_node(node *p_head,const char *name)
{if(p_head != NULL && name != NULL) {node *p_node = (node*)malloc(sizeof(node));if(p_node != NULL) {//p_node->name = name;//字符串直接放到数组里面strcpy(p_node->name,name);//把name赋值到p_node->name指向的空间p_node->next = NULL;node *p_move = p_head;//把这个结点插入到链表的尾部for(int i = 0;i < len;i++) {p_move=p_move->next;}p_move->next = p_node;p_node->next = p_head;len++;//len是一个全局变量}}
}//不要头结点只要数据结点,返回每一个结点地址
//拿到结点地址进行操作
node *insert_node1(node *p_head ,const char *name)
{if(name != NULL) {node *p_node = (node *)malloc(sizeof(node));if(p_node != NULL) {strcpy(p_node->name,name);if(len == 0) {//说明这是一个头结点p_node->next = p_node;} else {//往下移动到最后一个数据if(p_head != NULL) {node *p_move = p_head;while(p_move->next != p_head){//指向最后一个结点p_move = p_move->next;}p_move->next = p_node;p_node->next = p_head;}}len++; }return p_node;}
}//根据节点地址删除数据
char* delete_node(node *p_head,node *p_node)
{char *res = NULL;if(p_head != NULL && p_node != NULL && len > 0) {res = p_node->name;//字符串node *p_move = p_head;//移动到p_node的上一个节点while(p_move->next != p_node) {p_move = p_move->next;}p_move->next = p_node->next;len--;}return res;
}//这里的删除操作我们是不需要头结点的
//为什么不需要头结点
//因为头结点也很有可能被删除
char *delete_node1(node *p_node)
{char *res = NULL;//只需要移动到上一个结点然后进行删除操作就可以了if(p_node != NULL) {res = p_node->name;//这里返回一个字符串node *p_move = p_node;while(1) {if(p_move->next == p_node) {//程序跳出break;} p_move = p_move->next;}//只要程序跳出之后,说明就已经指向了上一个删除结点上一个节点p_move->next = p_node->next;len--;}return res;
}//打印数据
void print_node(node *p_head)
{if(p_head != NULL && len > 1) {node *p_move = p_head->next;printf("%p %s %p\n",p_head,p_head->name,p_head->next);while(p_move != p_head) {printf(" %p %s %p\n",p_move,p_move->name,p_move->next);p_move = p_move->next; }}
}int main()
{ int total_num;scanf("%d",&total_num);char str[21] = {'\0'};scanf("%s",str);//数组作为参数会退化成为一级指针node *p1 = insert_node1(NULL,str);while(total_num > 1) {scanf("%s",str);insert_node1(p1,str);total_num--;}//确定好开始循环的指针位置int start,step_over;node *p_move = p1;//移动结点开始肯定是头结点scanf("%d,%d",&start,&step_over);for(int i = 0;i < start - 1;i++) {//开始进行移动p_move = p_move->next;}while(len) {for(int j = 0;j < step_over - 1;j++) {p_move = p_move->next;}char * res=delete_node1(p_move);//把这个节点删除,len会自动减少 //销毁了之后,给p_move重新赋上新值就可以了p_move = p_move->next;//p_node结点被删了,指向p_node结点的下一个结点printf("%s\n",res);}return 0;
}
这里循环链表我在多说一句,我想利用自己写的库来做,也就是自己写的一个循环链表容器解决问题
demo3.cpp
#include
#include
#include //定义整体输入的数据大小
#define MAX_N 100
//定义字符串的最大长度
#define MAX_LEN 20//定义数组来存储要进行出列大的字符串信息
char name[MAX_N][MAX_LEN + 1];
//定义一个标记数组来标记数组里面的每一个人是否已经出列
int out[MAX_N];
int n;//总人数int main()
{//整体循环while(scanf("%d",&n) != EOF) {//循环输入数据到name数组里面for(int i = 0;i < n;i++) {scanf("%s",name[i]);}//初始化out数组这片空间//全部初始化为0表示没哟出队列memset(out,0,sizeof(out));int cur = 0;//游标开始的位置,每次前进两个游标int out_len = 0;//代表出对的个数,如果全部出队之后,个数应该是等于nint start_index,end_step;scanf("%d,%d",&start_index,&end_step);while(out_len < n) {int step = 0;while(step < end_step) {//让cur不断往下面前进,这也是它循环真正目的cur = (cur + 1) % n;//判断一下标记是否是有效前进值if(!out[cur]) {step++;}}//上面就会移动到我们需要出队的数据里面//把这个位置标记改了out[cur] = 1;out_len++;printf("%s\n",name[cur]);}}return 0;
}