Josephus排列

博客探讨了Josephus排列的问题,分别分析了当m为常数和不为常数时的解决方案。对于m为常数的情况,使用循环链表和头尾指针实现,运行时间为O(n);而m不为常数时,采用顺序统计树,查找和删除结点的时间复杂度为O(lgn),总运行时间为O(nlgn)。
摘要由CSDN通过智能技术生成

思考与分析:

           对于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
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值