约瑟夫环问题-顺序表-删头添尾法

一、问题描述

       有15个人围成一圈,顺序从115编号。从第一个人开始报数,凡报到n的人退出圈子。用C语言写出程序,输入n(n>1)的值,输出最后留在圈子里的人的编号。

二、算法描述

void  main( )

{

构建顺序表 L

把1-15这15个数逐个插入到 L 的尾部

输入n

While(顺序表 L 中元素多于一个)

{

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

{

取 L[0] 放到L的尾部;

删除L[0]

}

输出L[0]

删除 L[0];

}

输出L[0]

}

三、实现

#include<vector>
#include<iostream>
using namespace std;
void print(vector<int> &L)
{
	if(L.size()==0)
	{
		cout<<"No data\n";
		return;
	}
		
	int i;
	for(i=0;i<L.size();i++)
	{
		cout<<L[i]<<" ";
	}
	cout<<endl;
}

int main( )
{
	vector<int> L;
	
	int i,n;
	for(i=1;i<16;i++)
	{
		L.push_back(i);
	}
	
	//cin>>n;
	n=3;
	while(L.size()>1)
	{
		for(i=1;i<n;i++)
		{
			L.push_back(L[0]);
			L.erase(L.begin());
		}		
		cout<<L[0]<<" ";
		L.erase(L.begin());
		
	}
	cout<<endl;
	cout<<"最后剩余的是:"; 
	cout<<L[0]<<" "<<endl;
	
	return 0;
}


 

四、效率分析

这是一个双重循环,假设开始时有m个人

外层第 1 次循环时,插入尾部n-1次,删除头部n次。删除头部时,每次需要移动m-1次,则共移动n*(m-1)次;

外层第 2 次循环时,插入尾部n-1次,删除头部n次。删除头部时,每次需要移动m-1-1次,则共移动n*(m-1-1)次;

...

外层第 m-1 次循环时,剩余2个元素,插入尾部n-1次,删除头部n次。删除头部时,每次需要移动1次,则共移动n*1次;

综上,需要移动:n*[1+2+3+...+(m-1)]=n*m*(m-1)/2次。

所以,改算法的时间复杂度还是比较高的,主要在删除L[0]时,移动得比较频繁造成的。

怎样改进算法呢?

1、数到n的才删除;

2、用链表实现!!

我们在后续博客实现。

猜你喜欢

转载自blog.csdn.net/weixin_43917370/article/details/108688568