关于约瑟夫环用list实现遇到的奇怪问题

该问题是在Weiss著的《数据结构与算法分析(C++描述+第三版)习题中的3.6题遇到的


先把自己遇到问题的代码粘出来,本人的编译环境是windows7下的g++ (GCC) 4.6.1
#include<iostream>
#include<list>
using namespace std;

int main()
{
	int n=0,m=0,i=0;
	cout<<"please input the number of player : "<<endl;
	cin>>n;
	cout<<"please input the times of transfer"<<endl;
	cin>>m;
	list<int> aa; 
	for(i=0;i<n;i++)
		aa.push_back(i+1);
	list<int>::iterator itr=aa.begin();
	while(aa.size()>1)
	{
		for(i=0;i<m;i++)
		{
			if(itr==aa.end())
				itr=aa.begin();
			cout<<*itr++<<endl;
			cout<<*itr<<endl;
		}
		cout<<*itr<<" player game over!"<<endl;
		itr=aa.erase(itr);
	}
	return 0;
}
先试一种简单的情况,输入n=5,m=1
please input the number of player :
5
please input the times of transfer
1
1
2
2 player game over!
3
4
4 player game over!
5
1
1 player game over!
到此处程序就挂掉了,根据上面的输出,刚开始分析以为第三次进入while后
itr已经指向的值是5,进入for语句cout<<*itr++<<endl;输出itr指向5后自加一次,
然后cout<<*itr<<endl;输入itr指向1,认为itr在最后一个元素做自加运算会自动指向list的第一个位置,按此思路,程序继续往下走把cout<<*itr<<" player game over!"<<endl;打出来,接下来调用erase方法删除第一个元素,把返回值即下一个元素的迭代器给itr,看似没有问题但程序却挂那儿不走了
下面给出找出问题后正确的代码
#include<iostream>
#include<list>
using namespace std;

int main()
{
	int n=0,m=0,i=0;
	cout<<"please input the number of player : "<<endl;
	cin>>n;
	cout<<"please input the times of transfer"<<endl;
	cin>>m;
	list<int> aa; 
	for(i=0;i<n;i++)
		aa.push_back(i+1);
	list<int>::iterator itr=aa.begin();
//	cout<<*aa.begin()<<" "<<*aa.end()<<endl;
	while(aa.size()>1)
	{
		for(i=0;i<m%n;i++)
		{
			if(itr==aa.end())
				itr=aa.begin();
//			cout<<*itr<<endl;
			itr++;
//			cout<<*itr<<endl;
			if(itr==aa.end())
				itr=aa.begin();			
		}
		cout<<*itr<<" player game over!"<<endl;
		itr=aa.erase(itr);
		n--;
		if(itr==aa.end())
			itr=aa.begin();		
	}
	cout<<*aa.begin()<<" player win the game!"<<endl;
	return 0;
}


输入同上,输出的结果如下
please input the number of player :
5
please input the times of transfer
1
1 1
1
2
2 player game over!
3
4
4 player game over!
5
1
1 player game over!
3
5
5 player game over!
3 player win the game!
问题其实出在迭代器指向最后一个元素时,做自加运算后itr实际是指向了end标记,
那为什么上面出问题的情形下cout<<*itr<<endl;输出了1呢,难道是巧合吗???
这个我也不知道是不是巧合还是C++标准里有什么特殊的规定,输出的1其实是list中end标记指向的值,
原因可以见cout<<*aa.begin()<<" "<<*aa.end()<<endl;的输出值 1 1
所以当接下来调用erase方法删除end当然就出错了
总结:一些需要做循环操作的程序中,在自加运算前后都要判断迭代器是否指向end,
是的话手动让它指向begin。
本人刚学数据结构和算法,不知道这问题是不是很二,大牛轻拍哈
有兴趣的童鞋可以研究一下迭代器end指向的值是不是都是1或者end指向的值是怎么规定的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值