链队列约瑟夫环c++代码_047题-[编程入门||数据结构入门]报数问题-题解(C/C++代码)约瑟夫环问题详解,最短代码,循环链表/队列标准,公式推导On实现...

首先,该问题就是典型的约瑟夫环问题

# 什么是约瑟夫环问题?

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后 [1] 结果+1即为原问题的解。

(华丽的分割线)

------------------------------------------------

下面我们来解决这个问题,我们先建立约瑟夫环的一个模型,如下图所示

![](/image_editor_upload/20190612034129_17534.jpg)

就是如上这么个模型,理解起来也很简单,但对于新手来说,将其变成代码才是比较复杂的,下面先贴上我写的模拟最短代码,带有详细的注释

```cpp

#includeusing namespace std;

int main()

{

int n,m,s=0;scanf("%d",&n);

bool visit[200]={0};//visit赋初始值

for(int k=0;kn)s=1;if(visit[s])i--;}//类似取模,而因为序列是从1开始的,所以不取模,加判断;若visit过,则i--,使其继续循环

visit[s]=true;//输出,记录已出队

}

printf("%d ",s);

return 0;

}

```

简单可靠!!!

就是不停的遍历模拟的过程,注意判重问题,**防止重复遍历**

## 下面实现比较容易理解的方法,循环链表

虽然有些复杂,但这就是题目希望我们去做的意思

```cpp

#includeusing namespace std;

struct peo

{

int ID; //编号

peo *next = NULL, *front = NULL;

}n[100];

void _cut(peo *num)

{

num = num->front;

num->next = num->next->next;

num = num->next;

num->front = num->front->front;

}

int main()

{

int sum=0;//记录当前出队人数

int tot, outNum, nowNum = 1;

peo *now = &n[0]; //指向目前报数的人的指针

cin >> tot; //数据读入

for (int i = 1; i < tot - 1; i++)

{

n[i].front = &n[i - 1]; n[i].next = &n[i + 1]; n[i].ID = i + 1;

}

n[0].front = &n[tot - 1]; n[0].next = &n[1]; n[tot - 1].front = &n[tot - 2]; n[tot - 1].next = &n[0];

n[0].ID = 1; n[tot - 1].ID = tot;

//初始化链表

while (tot > 0)

{

if (nowNum == 3)

{

if(tot==1)

{

cout

}

//cout << now->ID << " "; 这是输出当前的

_cut(now); //出局

nowNum = 1; //初始化数字

tot--; //总人数-1

now = now->next; //下一个人

}

else

{

nowNum++; //数字+1

now = now->next; //下一个人

}

}

return 0;

}

```

下面再实现一种队列实现的方式,类似第一种模拟.

用了STL内封装的queue队列(不想手写队列,太懒了)

```cpp

#includeusing namespace std;

int main()

{

int tot, outNum, nowNum = 1;

queueq;

cin >> tot; //读取数据

for (int i = 1; i <= tot; i++)q.push(i); //初始化队列

while (!q.empty()) //在队列不为空时继续模拟

{

if (nowNum == 3)

{

if(q.size()==1)

cout << q.front() << " "; //打印最后一个人的编号

q.pop(); //出局

nowNum = 1; //初始化现在的数字

}

else

{

nowNum++;

q.push(q.front()); //排至队尾

q.pop();

}

}

return 0;

}

```

# STL大法好!

这基本包括所有约瑟夫环的求解方式了

最后给大家附上进阶的最优算法,由推导优化得出公式来计算,由原复杂度On^2降为On,具体推导过程有需要的可以私聊问我

```cpp

#includeusing namespace std;

int main()

{

int n, m,i,s=0;

cin>>n;

for(i=2;i<=n;i++)

s=(s+3)%i;

printf("%d", s+1);

return 0;

}

```

就这样,约瑟夫环降为了**On复杂度**

溜了溜了

0.0分

57 人评分

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值