约瑟夫环问题
约瑟夫环是一个数学的应用问题:已知n个人(以编号a,b,c...分别表示)围坐在一张圆桌周围。从编号为1的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
约瑟夫环代码
数组约瑟夫环
#pragma warning(disable : 4996)
#include <stdio.h>
#include <assert.h>
#include <iostream> // std::cout, std::cin
#include <fstream> // fstream::read, ::write, ::getline
#include <string> // std::string
#include <algorithm>// std::transform
#include <cstring> // string.h/memory.h => string => cstring::memset, ::memcpy
#include <ctime> // time.h => ctime::srand(time(NULL)), ::rand(), ::clock()
#include <vector>
using namespace std;
void func(int number,int k)
{
printf("%d ",number);
vector<int> p;
p.resize(10000001);
printf("%d\n",k);
for(int i=0;i<number;i++)
{
p[i]=i+1;
}
int sum=0;
int t=0;
int i=0;
while(sum!=(number-1))
{
if(p[i]==0)
i++;
else{
t++;
if(t==k)
{
//printf("%d ",p[i]);
p[i]=0;
t=0;
sum++;
}
i++;
}
if(i==number)
{
i=0;
}
}
for(int i=0;i<number;i++)
{
if(p[i]!=0)
{
printf("%d\n",p[i]);
}
}
}
double elapse_time(void (*f)(int,int))
{
clock_t start,end;
start = clock();
f(7,3);
f(200000,20);
f(10000000,2);
f(100000000,2);
end = clock(); 检查运行时间,用于对比三种方法
return (double)(end-start)/CLOCKS_PER_SEC;
}
int main()
{
int n,m;
double et=elapse_time(func);
printf("C: %-.4fs\n",et);
}
时间复杂度:O(2*N+K)
空间复杂度:O(1)
链表约瑟夫环
#pragma warning(disable : 4996)
#include <stdio.h>
#include <assert.h>
#include <iostream> // std::cout, std::cin
#include <fstream> // fstream::read, ::write, ::getline
#include <string> // std::string
#include <algorithm>// std::transform
#include <cstring> // string.h/memory.h => string => cstring::memset, ::memcpy
#include <ctime> // time.h => ctime::srand(time(NULL)), ::rand(), ::clock()
#include <vector>
using namespace std;
typedef struct node
{
int data;
struct node* next;
}Node;
void f(int N,int M)
{
printf("%d %d\n",N,M);
Node *head = NULL,*p=NULL,*r=NULL;
head = (Node*)malloc(sizeof(struct node*));
head->data=1;
head->next=NULL;
p=head;
for(int i=2;i<=N;i++)
{
r=(Node*)malloc(sizeof(Node));
r->data=i;
r->next=NULL;
p->next=r;
p=r;
}
p->next=head;
p=head;
while(p->next!= p) //如果p的next=p,说明目前只有一个元素
{
for(int i=1;i<M;i++)
{
r=p;
p=p->next;
}
Node *temp = p;
// 输出
// printf("%d ",p->data);
r->next=p->next;
p=p->next;
free(temp);
}
printf("%d ",p->data);
}
double elapse_time(void (*f)(int ,int))
{
clock_t start,end;
start = clock();
f(7,3);
printf("\n");
f(200000,20);
printf("\n");
f(10000000,2);
printf("\n");
f(10000000,2);
printf("\n");
end = clock(); 检查运行时间,用于对比三种方法
return (double)(end-start)/CLOCKS_PER_SEC;
}
int main()
{
int n,m;
double et=elapse_time(f);
printf("C: %-.4fs\n",et);
}
时间复杂度:O(N + M)
空间复杂度:O(N)
数字约瑟夫环
#pragma warning(disable : 4996)
#include <stdio.h>
#include <assert.h>
#include <iostream> // std::cout, std::cin
#include <fstream> // fstream::read, ::write, ::getline
#include <string> // std::string
#include <algorithm>// std::transform
#include <cstring> // string.h/memory.h => string => cstring::memset, ::memcpy
#include <ctime> // time.h => ctime::srand(time(NULL)), ::rand(), ::clock()
#include <vector>
using namespace std;
void func(int number,int k)
{
printf("%d ",number);
printf("%d\n",k);
int i,s=0;
for(i=1;i<=number;i++)
{
s=(s+k)%i;
}
s++;
printf("%d ",s);
printf("\n");
}
double elapse_time(void (*f)(int,int))
{
clock_t start,end;
start = clock();
f(7,3);
f(200000,20);
f(10000000,2);
f(10000000,2);
end = clock(); //检查运行时间,用于对比三种方法
return (double)(end-start)/CLOCKS_PER_SEC;
}
int main()
{
int n,m;
double et=elapse_time(func);
printf("C: %-.4fs\n",et);
}
时间复杂度:O(N)
空间复杂度:O(1)
对比运行时间结果表格
数据\解约瑟夫环方法 | 数组 | 链表 | 数学 |
f(7,3); f(200,2); f(1000,2); f(10000,2); | 0.1130s | 0.0010s | 0.0000s |
f(7,3); f(20000,2); f(100000,2); f(10000000,2); | 0.9450s | 2.3200s | 0.0320s |
f(7,3); f(200000,20); f(10000000,2); f(10000000,2); | 2.0410s | 3.5490s | 0.1140s |
f(20000,20); f(100000,20); f(1000000,20); | 3.8970s | 1.8850s | 1.8270s |
f(200000,20); f(1000000,20); f(10000000,20); | 11.1250s | 2.5730s | 2.0790s |
f(20000,20); f(1000000,20); f(1000000,20); | 18.5780s | 3.6070s | 2.2590s |
f(20000,200); f(100000,200); f(1000000,200); | 7.6980s | 3.9660s | 0.040s |
f(200000,200); | 84.5030s | 71.3830s | 0.0390s |
总结
随总数增加,运行时间变长。
在n较小时,时间:链表>数组>数字
在n中等时,时间:数组>链表>数字
在n较大时,时间:数组>链表>数字
程序运行结果附录
数组
f(7,3);
f(200,2);
f(1000,2);
f(10000,2);
f(7,3);
f(20000,2);
f(100000,2);
f(10000000,2);
f(7,3);
f(200000,20);
f(10000000,2);
f(10000000,2);
f(20000,20);
f(100000,20);
f(1000000,20);
f(200000,20);
f(1000000,20);
f(10000000,20);
f(20000,20);
f(1000000,20);
f(1000000,20);
f(20000,200);
f(100000,200);
f(1000000,200);
f(200000,200);
f(1000000,200);
f(10000000,200);
数学
f(7,3);
f(200,2);
f(1000,2);
f(10000,2);
f(7,3);
f(20000,2);
f(100000,2);
f(10000000,2);
f(7,3);
f(200000,20);
f(10000000,2);
f(10000000,2);
f(20000,20);
f(100000,20);
f(1000000,20);
f(200000,20);
f(1000000,20);
f(10000000,20);
f(20000,20);
f(1000000,20);
f(1000000,20);
f(20000,200);
f(100000,200);
f(1000000,200);
f(200000,200);
f(1000000,200);
f(10000000,200);
链表
f(7,3);
f(200,2);
f(1000,2);
f(10000,2);
f(7,3);
f(20000,2);
f(100000,2);
f(10000000,2);
f(7,3);
f(200000,20);
f(10000000,2);
f(10000000,2);
f(20000,20);
f(100000,20);
f(1000000,20);
f(200000,20);
f(1000000,20);
f(10000000,20);
f(20000,20);
f(1000000,20);
f(1000000,20);
f(20000,200);
f(100000,200);
f(1000000,200);
f(200000,200);
f(1000000,200);
f(10000000,200);