队列实现

#include <stdio.h>
#include <queue>
using namespace std;
//队列实现 
queue<int> q;
int n, m, cnt, out, a[101]; //a[i]=0表示在圈里 
int main()
{
	scanf("%d %d", &n, &m);
	for(int i=1; i<=n; i++){
		q.push(i);
	}
	while(!q.empty()){
		cnt++;
		if(cnt==m){
			cnt=0;
			printf("%d ", q.front());
			q.pop();
		}
		else{
			q.push(q.front());
			q.pop();
		}
	}
	return 0;
}
#include <bits/stdc++.h>//万能头文件   
//动态链表 
//动态链表需要临时分配链表节点,使用完毕后释放链表节点。
//动态链表的优点是能及时释放空间,不使用多余内存﹔缺点是需要管理空间,容易出错。
//动态链表是“教科书式”的标准做法。
/*
定义链表节点 
data  节点的值
next  单向链表指针 
*/ 
struct node{
	int data;
	node *next;
}; 
 
int main(){
 int n,m;
 scanf("%d%d",&n,&m);
 node *head,*p,*now,*r;//定义变量
 //分配第1个节点,数据设置为1 
 head = new node;head->data=1;head->next=NULL;
 now = head; //设置当前指针为头指针
 for(int i=2;i<=n;i++){
 	p=new node;p->data=i;p->next=NULL;//p是新节点
	now ->next=p;//把申请的新节点连到前面的链表上 
	now = p;//尾指针后移一个 
 } 
 now->next=head;//尾指针指向头,循环链表建立完成
 now = head;r=head;//从第1个开始数
 while((n--)>1) {
 	for(int i=1;i<m;i++)
 	{
 		r=now;//数到m,停下 
 		now=now->next;//记录上一个位置,用于下面跳过第m个节点 
	 }
	 printf("%d ",now->data);//输出第m个节点,带空格
	 r->next=now->next;//跳过这个节点
	 delete now;//释放节点
	 now=r->next;//新的一轮 
 }
  printf("%d",now->data);//打印最后一个节点,后面不带空格
  delete now;//释放最后一个节点 
  return 0; 
 }

双向链表参考题解

#include <iostream>   
// 双向链表节点  
struct Node {  
    int data;  
    Node* prev;  
    Node* next;  
   
    Node(int d) : data(d), prev(nullptr), next(nullptr) {}  
};  
   
// 约瑟夫问题求解函数  
void josephus(int n, int m) {  
    if (n < 1 || m < 1) {  
        //std::cerr << "输入错误!" << std::endl;  
        return;  
    }  
   
    // 创建一个虚拟头节点来简化操作  
    Node* dummyHead = new Node(0);  
    Node* current = dummyHead;  
    Node* prev = dummyHead;  
   
    // 创建双向链表  
    for (int i = 1; i <= n; ++i) {  
        current->next = new Node(i);  
        current->next->prev = current;  
        current = current->next;  
    }  
    // 闭合链表  
    current->next = dummyHead->next;  
    dummyHead->next->prev = current;  
    current = dummyHead->next; // 跳过虚拟头节点  
   
    // 约瑟夫问题求解过程  
    while (current != current->next) { // 当链表中还有多于一个节点时  
        // 报数到m-1  
        for (int count = 1; count < m; ++count) {  
            prev = current;  
            current = current->next;  
        }  
        // 输出出圈人的编号  
        std::cout << current->data << " ";  
        // 移除当前节点  
        prev->next = current->next;  
        current->next->prev = prev;  
        // 释放当前节点内存  
        Node* toDelete = current;  
        current = current->next;  
        delete toDelete;  
    }  
    // 输出最后一个出圈人的编号  
    std::cout <<  current->data << std::endl;  
    // 释放最后一个节点内存  
    delete current;  
   
    // 不需要再保留虚拟头节点  
    delete dummyHead;  
}  
   
int main() {  
    int n, m;   
    std::cin >> n >> m;    
    josephus(n, m);   
    return 0;  
}

一维数组

/* 
 使用一维数组实现单向静态链表的解法
 这是最简单的实现方法。
*/ 
#include<bits/stdc++.h>
using namespace std;
int n,m,arr[110]; 
int main(){
	scanf("%d%d",&n,&m);
	int i=1;
	int cnt=0;
	int t=1;
	while(n>cnt){
	 	if(i>n) i=1;
	 	if(arr[i]==0)
	 	{
	 		if(t==m){
	 			arr[i]=1;
	 			cnt++;
	 			printf("%d ",i);
	 			t=0;
			 }
			 t++;
		 } 
		 i++; 
	} 
    return 0;
}

STL

/* 
在算法竞赛或工程项目中常常使用 C++STL list。
list 是双向链表,由标准模板库Standard Template Library,STL)
管理通过指针访问节点数据高效率地删除和插入。 
*/ 
#include <bits/stdc++.h> 
using namespace std;
int main()
{
	int n,m;
	list<int> node;
	scanf("%d%d",&n,&m);
	//nodes[i]的值就是下一个节点 
	for(int i=1;i<=n;++i) node.push_back(i);//建立链表
	list<int>::iterator it=node.begin();
	while(node.size()>1){//list的大小由STL自己管理 
		for(int i=1;i<m;++i){//数到m 
			it++;
			if(it==node.end()) //循环到末尾后再回头 
				it=node.begin();
		}
		printf("%d ",*it);
		list<int>::iterator next=++it;
		if(next==node.end()) next=node.begin();//循环链表
		node.erase(--it);//删除节点,node.size()自动减1
		it=next; 
	} 
 	printf("%d",*it);
	return 0;
}