思考与分析:
对于m为常数,可以用循环链表,用head,tail标志头尾指针使其易于表示循环结构。循环输出后删除结点n次,每次外层循环时,内层都固定循环m次。所以运行时间为O(mn)=O(n).
对于m为非常数。可以用顺序统计树,用size属性记录每个结点在当前树中所在的位置。经过一个取余过程,每次都能正确找到并输出删除每个结点,在经过n次循环,每次循环都要找到一个结点输出并删除它,所以每次循环都要花费O(lgn)时间。总的运行时间是O(nlgn).
代码如下:
m为常数时:
#include <iostream>
using namespace std;
#define n 10
#define m 3
#define LEN sizeof(struct circular_list)
struct circular_list
{
int key;
struct circular_list* next;
};
struct circular_list*tail=NULL;
struct circular_list*Insert(struct circular_list*&head,int k)
{
struct circular_list*z=new struct circular_list[LEN];
z->key=k;
if (head==NULL)
{
head=tail=z;
head->next=tail;
}
else
{
tail->next=z;
z->next=head;
tail=z;
}
return head;
}
struct circular_list* Delete(struct circular_list*&head,struct circular_list*z)
{
struct circular_list*p=head;
while (p->next!=z)
{
p=p->next;
}
if (head==tail)
{
p->next=NULL;
}
else
{
if (head==p->next)
{
head=p->next->next;
}
else if (tail==p->next)
{
tail=p;
}
p->next=p->next->next;
}
return p->next;
}
void n_m_Josephus(struct circular_list*&head)
{
struct circular_list*p=head;
while (p)
{
int i=0;
while (i!=m-1)
{
p=p->next;
i++;
}
struct circular_list*z=p;
cout<<z->key<<" ";
p=Delete(head,z);
}
}
void main()
{
int a[n]={0};
for (int i=0;i<n;i++)
{
a[i]=i+1;
}
int j=0;
struct circular_list*head=NULL;
while (j!=n)
{
head=Insert(head,a[j]);
j++;;
}
struct circular_list*p=head;
do
{
cout<<p->key;
p=p->next;
} while (p!=head);
cout<<endl;
n_m_Josephus(head);
}
m不是常数时:
#include <iostream>
#include <time.h>
using namespace std;
#define BLACK 0
#defi