简单双向链表的实现&新约瑟夫问题
题目描述:
给定m个人,从s开始报数,数字顺加,报到n的人出列,然后数字顺减报到k的人出列,求出列顺序
样例输入:
8 1 3 2
样例输出:
3 6 1 5 2 8 4 7
分析:
约瑟夫问题主要就是处理边界,因此选用链表,第一个指向最后一个,最后一个指向第一个。
注意,这里链表不用指针!不用指针!为什么?因为m<=100,链表节点数量小,可直接用数组+结构体!
q为前驱,h为后继。
完整代码如下:
#include <iostream> #include <map> #include <cstdio> using namespace std; int m,s,n,k,cnt,pd=true,pd2=true; struct lb { int q,h; }a[105]; void del(int x)//删除节点 { a[a[x].q].h=a[x].h; a[a[x].h].q=a[x].q; } int main() { // freopen("newjsf.in","r",stdin); //打开输入文件 // freopen("newjsf.out","w",stdout); //打开输出文件 cin>>m>>s>>n>>k; a[1].q=m,a[1].h=2,a[m].q=m-1,a[m].h=1; cnt=m; for(int i=2;i<=m-1;i++) { a[i].q=i-1,a[i].h=i+1; } while(cnt>0) { if(pd) for(int i=1;i<=n;i++) { if(pd2)//判断是否第一个人 { pd2=false; continue; } s=a[s].h; } else for(int i=1;i<=k;i++) s=a[s].q; cout<<s<<" "; cnt--; del(s); } fclose(stdin);//关闭输入文件 fclose(stdout);//关闭输出文件 }