数据结构 循环链表之约瑟夫问题



#include<stdlib.h>
#include<string>
#include<iostream>
using namespace std;   
#define ElemType string
typedef struct LNode
{
 ElemType info;
 struct LNode* next;
}LNode,* Listq;

//循环链表初始化 头针指Lq向最后一个数据
bool InitialList(Listq& Lq)
{
 int length=0;
 char lengthS[4];
 LNode *p=new LNode;
 if(!p) return false;
 Lq=p;
 Lq->next=Lq;
 ElemType x;
 cin>>x;
 while(x!="0"){
  p=new LNode;
  if(!p) return false;
  p->info=x;
  p->next=Lq->next;
  Lq->next=p;
  Lq=p;
  ++length;
  cin>>x;
 }
 itoa(length,lengthS,10);  //int转化为string类型   itoa(int,char[], 进制) 
 Lq->next->info=lengthS; //头结点的数据单存放表长信息
 return true;
}
bool OutputList(Listq Lq)   //输出函数
{
 LNode *p=Lq->next->next;
 while(p!=Lq->next){
  cout<<p->info<<" ";
  p=p->next;
 }
 cout<<endl;
 return true;
}
void DeleLNode(Listq& Lq,LNode* pre,LNode* pos)  //删除节点信息
{
 LNode *head,*del,*tmp;
 char lengthS[4];
 int length=atoi((Lq->next->info).c_str());  //string 类型转换成int型
 head=Lq->next;
 del=pos;
 tmp=pre;
 pre->next=pos->next;
 delete(del);
 --length;
 while(tmp->next!=head)  //重新确定Lq的位置 因为删除的元素可能是Lq原来指向的
  tmp=tmp->next;
 Lq=tmp;
 itoa(length,lengthS,10);  //int 化string
 Lq->next->info=lengthS; //改变长度
}
void Josephus(Listq Lq, int m)  //约瑟夫函数 m为间隔数
{
 int i,j,num;
 num=atoi((Lq->next->info).c_str());
 LNode* pre=Lq->next;  //设计前驱指针用来删除
 LNode* pos=Lq->next->next; //指向第一个数据元素
 LNode* del=NULL;
 for(i=0;i<num-1;++i)    //一共删除n-1个
 {
  for(j=0;j<m-1;++j)   //控制指针移动
  {
   pre=pre->next;
   pos=pos->next;
   while(pos==Lq->next)  //头结点不能算在里面  此题不用头结点会简单很多
   {
    pre=pre->next;
    pos=pos->next;
   }
  }
  del=pos;
  pos=pos->next;  //指向下一人
  DeleLNode(Lq,pre,del);  //删
  while(pos==Lq->next)   //如果下一人是头结点  pre和pos一定要同时后移  如果pos不指向头结点 则pre不必后移 切记!!!!
  {
   pos=pos->next;
   pre=pre->next;
  }
  OutputList(Lq);
 }
}
void DeleList(Listq& Lq)  //这函数没用
{
 LNode *del,*p;
 p=Lq->next;
 while(p!=Lq)
 {
  del=p;
  p=p->next;
  delete(del);
 }
 delete(p);
}
int main()
{
 Listq Lq;
 InitialList(Lq);
 OutputList(Lq);
 Josephus(Lq,3);
 return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值