课程设计—约瑟夫双向生死问题

问题及描述:


约瑟夫双向生死问题是建立在约瑟夫问题基础上,正向计数后反向计数,然后在正向计数,然后在正向计数。具体描述如下:30个旅客同乘一条船,因为严重过载,加上风浪高大,危险万分;因此船长告诉乘客,只有将全船一半的旅客投入海中,其余人才能幸免遇难。无奈,大家只得同意这种方法,并议定30个人围成一圈,由第一个人开始,顺时针依次报数,数到第九人,便把他投入大海中,然后从他的下一个人数起,逆时针数到第5人,将他投入大海,然后从他逆时针的下一个人数起,顺时针数到第9人,再将他投入大海,如此循环,直到剩下15个乘客为止。问那些乘客是将被扔下大海的位置。


顺序表方式:

list.h

#define MaxSize 50    
typedef int ElemType;    
typedef struct    
{    
    ElemType data[MaxSize];    
    int length;    
} SqList;    
void CreateList(SqList *&L, ElemType a[], int n);//用数组创建线性表    
void InitList(SqList *&L);//初始化线性表InitList(L)    
void DestroyList(SqList *&L);//销毁线性表DestroyList(L)    
bool ListEmpty(SqList *L);//判定是否为空表ListEmpty(L)    
int ListLength(SqList *L);//求线性表的长度ListLength(L)    
void DispList(SqList *L);//输出线性表DispList(L)    
bool GetElem(SqList *L,int i,ElemType &e);//求某个数据元素值GetElem(L,i,e)    
int LocateElem(SqList *L, ElemType e);//按元素值查找LocateElem(L,e)    
bool ListInsert(SqList *&L,int i,ElemType e);//插入数据元素ListInsert(L,i,e)    
bool ListDelete(SqList *&L,int i,ElemType &e);//删除数据元素ListDelete(L,i,e)  

list.cpp    (对算法的listdelete进行修改)

#include <stdio.h>    
#include <malloc.h>    
#include "list.h"    
    
//用数组创建线性表    
void CreateList(SqList *&L, ElemType a[], int n)    
{    
    int i;    
    L=(SqList *)malloc(sizeof(SqList));    
    for (i=0; i<n; i++)    
        L->data[i]=a[i];    
    L->length=n;    
}    
    
//初始化线性表InitList(L)    
void InitList(SqList *&L)   //引用型指针    
{    
    L=(SqList *)malloc(sizeof(SqList));    
    //分配存放线性表的空间    
    L->length=0;    
}    
    
//销毁线性表DestroyList(L)    
void DestroyList(SqList *&L)    
{    
    free(L);    
}    
    
//判定是否为空表ListEmpty(L)    
bool ListEmpty(SqList *L)    
{    
    return(L->length==0);    
}    
    
//求线性表的长度ListLength(L)    
int ListLength(SqList *L)    
{    
    return(L->length);    
}    
    
//输出线性表DispList(L)    
void DispList(SqList *L)    
{    
    int i;    
    if (ListEmpty(L)) return;    
    for (i=0; i<L->length; i++)    
        printf("%d ",L->data[i]);    
    printf("\n");    
}    
    
//求某个数据元素值GetElem(L,i,e)    
bool GetElem(SqList *L,int i,ElemType &e)    
{    
    if (i<1 || i>L->length)  return false;    
    e=L->data[i-1];    
    return true;    
}    
    
//按元素值查找LocateElem(L,e)    
int LocateElem(SqList *L, ElemType e)    
{    
    int i=0;    
    while (i<L->length && L->data[i]!=e) i++;    
    if (i>=L->length)  return 0;    
    else  return i+1;    
}    
    
//插入数据元素ListInsert(L,i,e)    
bool ListInsert(SqList *&L,int i,ElemType e)    
{    
    int j;    
    if (i<1 || i>L->length+1)    
        return false;   //参数错误时返回false    
    i--;            //将顺序表逻辑序号转化为物理序号    
    for (j=L->length; j>i; j--) //将data[i..n]元素后移一个位置    
        L->data[j]=L->data[j-1];    
    L->data[i]=e;           //插入元素e    
    L->length++;            //顺序表长度增1    
    return true;            //成功插入返回true    
}    
    
//删除数据元素ListDelete(L,i,e)    
bool ListDelete(SqList *&L,int i,ElemType &e)    
{    
    int j;    
    if (i<0 || i>L->length)  //参数错误时返回false    
        return false; 
	if(i==0)        //
	i=L->length;    // 对j=0 的修改(2行)
    i--;        //将顺序表逻辑序号转化为物理序号    
    e=L->data[i];    
    for (j=i; j<L->length-1; j++) //将data[i..n-1]元素前移    
        L->data[j]=L->data[j+1];    
    L->length--;              //顺序表长度减1    
    return true;              //成功删除返回true    
}    
 


main.cpp

#include "list.h"    
#include <stdio.h>    
void main()        
{        
SqList *sq;    
int n,f,s;  //n代表船上的总人数,f代表第一次顺时针方向数的个数,s代表第二次逆时针的个数    
int i,j=1;   // j记录当前位置     
printf("请输入船上的总人数:\n");    
scanf("%d",&n);    
printf("请输入顺时针方向的人数:\n");    
scanf("%d",&f);    
printf("请输入逆时针方向的人数:\n");    
scanf("%d",&s);      
printf("请输入开始位置的人的序号:\n");  
scanf("%d",&j);  
ElemType x[1000],e;     
for(i=0;i<n;i++)    
x[i]=i+1;                    //初始化数组    
  
  
CreateList(sq, x, n);      // 创建线性表  
  
for(i=0;i<n/2;i++)                //从第一个位置开始,第一次顺时针9人,第二次逆时针5人如此循环    
{     
if(i%2==0)               // 以奇偶区分顺、逆时针方向    
{    
j=((j+f-1)+sq->length)%sq->length;   //从第一个位置开始,顺时针数9个位置,应移动8个位置8    
if(j==0)
j=sq->length;  //   j=0 表示为最后一个元素


if(ListDelete(sq,j,e))       
printf("第%d次出局的序号为:%d\n",i+1,e); //删除并输出该元素      


j=j%sq->length;   // 结果修正( 处理j为最后一个元素的情况  下一次j开始时是从第一个位置 )
}   
//顺时针的方法下一次开始的位置为j(在删除元素时是一次从下一个位置补上来)  




else    // 逆时针移动5个位置    
{    
j=((j-(s-1))+sq->length)%sq->length;   //从第一个位置开始,逆时针数5个位置,应为移动4个位置    
if(j==0)
j=sq->length;
if(ListDelete(sq,j,e))    


printf("第%d次出局的序号为:%d\n",i+1,e); //删除并输出该元素    
                
j=(j-1)%sq->length;  // 结果修正(j为第一个元素)
} //逆时针的方法下一次开始的位置为j-1  
  
  
}    
printf("剩余的序号为:\n");    
DispList(sq);    
  
  
}        


运行结果:





循环双链表方式:

cdlinklist.h

#ifndef CDLINKLIST_H_INCLUDED
#define CDLINKLIST_H_INCLUDED

//循环双链表基本运算函数
typedef int ElemType;
typedef struct DNode        //定义双链表结点类型
{
    ElemType data;
    struct DNode *prior;    //指向前驱结点
    struct DNode *next;     //指向后继结点
} CDLinkList;

void CreateListF(CDLinkList *&L,ElemType a[],int n); //头插法建立循环双链表
void CreateListR(CDLinkList *&L,ElemType a[],int n); //尾插法建立循环双链表
void InitList(CDLinkList *&L); //初始化循环双链表
void DestroyList(CDLinkList *&L);  //销毁
bool ListEmpty(CDLinkList *L); //判断是否为空
int ListLength(CDLinkList *L); //求链表长度
void DispList(CDLinkList *L);  //输出链表
bool GetElem(CDLinkList *L,int i,ElemType &e);  //取链表元素
int LocateElem(CDLinkList *L,ElemType e);  //查找元素
bool ListInsert(CDLinkList *&L,int i,ElemType e);  //插入节点
bool ListDelete(CDLinkList *&L,int i,ElemType &e);  //删除节点

#endif // CDLINKLIST_H_INCLUDED


cdlinklist.cpp

#include <stdio.h>
#include <malloc.h>
#include "cdlinklist.h"
void CreateListF(CDLinkList *&L,ElemType a[],int n) //头插法建立循环双链表
{
    CDLinkList *s;
    int i;
    L=(CDLinkList *)malloc(sizeof(CDLinkList));     //创建头结点
    L->next=NULL;
    for (i=0; i<n; i++)
    {
        s=(CDLinkList *)malloc(sizeof(CDLinkList));//创建新结点
        s->data=a[i];
        s->next=L->next;            //将*s插在原开始结点之前,头结点之后
        if (L->next!=NULL) L->next->prior=s;
        L->next=s;
        s->prior=L;
    }
    s=L->next;
    while (s->next!=NULL)           //查找尾结点,由s指向它
        s=s->next;
    s->next=L;                      //尾结点next域指向头结点
    L->prior=s;                     //头结点的prior域指向尾结点


}
void CreateListR(CDLinkList *&L,ElemType a[],int n) //尾插法建立循环双链表
{
    CDLinkList *s,*r;
    int i;
    L=(CDLinkList *)malloc(sizeof(CDLinkList));  //创建头结点
    L->next=NULL;
    r=L;                    //r始终指向尾结点,开始时指向头结点
    for (i=0; i<n; i++)
    {
        s=(CDLinkList *)malloc(sizeof(CDLinkList));//创建新结点
        s->data=a[i];
        r->next=s;
        s->prior=r; //将*s插入*r之后
        r=s;
    }
    r->next=L;              //尾结点next域指向头结点
    L->prior=r;             //头结点的prior域指向尾结点
}
void InitList(CDLinkList *&L) //初始化循环双链表
{
    L=(CDLinkList *)malloc(sizeof(CDLinkList));     //创建头结点
    L->prior=L->next=L;
}
void DestroyList(CDLinkList *&L)  //销毁
{
    CDLinkList *p=L,*q=p->next;
    while (q!=L)
    {
        free(p);
        p=q;
        q=p->next;
    }
    free(p);
}
bool ListEmpty(CDLinkList *L) //判断是否为空
{
    return(L->next==L);
}
int ListLength(CDLinkList *L) //求链表长度
{
    CDLinkList *p=L;
    int i=0;
    while (p->next!=L)
    {
        i++;
        p=p->next;
    }
    return(i);
}
void DispList(CDLinkList *L)  //输出链表
{
    CDLinkList *p=L->next;
    while (p!=L)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    printf("\n");
}
bool GetElem(CDLinkList *L,int i,ElemType &e)  //取链表元素
{
    int j=0;
    CDLinkList *p;
    if (L->next!=L)     //双链表不为空表时
    {
        if (i==1)
        {
            e=L->next->data;
            return true;
        }
        else            //i不为1时
        {
            p=L->next;
            while (j<i-1 && p!=L)
            {
                j++;
                p=p->next;
            }
            if (p==L)
                return false;
            else
            {
                e=p->data;
                return true;
            }
        }
    }
    else                //双链表为空表时
        return 0;
}
int LocateElem(CDLinkList *L,ElemType e)  //查找元素
{
    int n=1;
    CDLinkList *p=L->next;
    while (p!=NULL && p->data!=e)
    {
        n++;
        p=p->next;
    }
    if (p==NULL)
        return(0);
    else
        return(n);
}
bool ListInsert(CDLinkList *&L,int i,ElemType e)  //插入节点
{
    int j=0;
    CDLinkList *p=L,*s;
    if (p->next==L)                 //原双链表为空表时
    {
        s=(CDLinkList *)malloc(sizeof(CDLinkList)); //创建新结点*s
        s->data=e;
        p->next=s;
        s->next=p;
        p->prior=s;
        s->prior=p;
        return true;
    }
    else if (i==1)                  //原双链表不为空表但i=1时
    {
        s=(CDLinkList *)malloc(sizeof(CDLinkList)); //创建新结点*s
        s->data=e;
        s->next=p->next;
        p->next=s;  //将*s插入到*p之后
        s->next->prior=s;
        s->prior=p;
        return true;
    }
    else
    {
        p=L->next;
        while (j<i-2 && p!=L)
        {
            j++;
            p=p->next;
        }
        if (p==L)               //未找到第i-1个结点
            return false;
        else                    //找到第i-1个结点*p
        {
            s=(CDLinkList *)malloc(sizeof(CDLinkList)); //创建新结点*s
            s->data=e;
            s->next=p->next;    //将*s插入到*p之后
            if (p->next!=NULL) p->next->prior=s;
            s->prior=p;
            p->next=s;
            return true;
        }
    }
}
bool ListDelete(CDLinkList *&L,int i,ElemType &e)  //删除节点
{
    int j=0;
    CDLinkList *p=L,*q;
    if (p->next!=L)                 //原双链表不为空表时
    {
        if (i==1)                   //i==1时
        {
            q=L->next;              //删除第1个结点
            e=q->data;
            L->next=q->next;
            q->next->prior=L;
            free(q);
            return true;
        }
        else                        //i不为1时
        {
            p=L->next;
            while (j<i-2 && p!=NULL)
            {
                j++;
                p=p->next;
            }
            if (p==NULL)                //未找到第i-1个结点
                return false;
            else                        //找到第i-1个结点*p
            {
                q=p->next;              //q指向要删除的结点
                if (q==NULL) return 0;  //不存在第i个结点
                e=q->data;
                p->next=q->next;        //从单链表中删除*q结点
                if (p->next!=NULL) p->next->prior=p;
                free(q);                //释放*q结点
                return true;
            }
        }
    }
    else
        return false;   //原双链表为空表时
}


main.cpp

#include <malloc.h>    
#include <stdio.h>    
#include "cdlinklist.h"    
   
void main()    
{    
    int n,f,s,st,m=1;  //n代表船上的总人数,f代表第一次顺时针方向数的个数,s代表第二次逆时针的个数,a为开始位置的人的序号  


	CDLinkList *dl,*p;    //*dl 为双链表的头指针    *p指向当前指针    
   
	printf("请输入船上的总人数:\n");    // 在创建循环双链表的时候,实际创建的有n+1个元素 头结点也算在其中  


	scanf("%d",&n);  
   
	printf("请输入顺时针方向的人数:\n");  


	scanf("%d",&f);  


	printf("请输入逆时针方向的人数:\n");  


	scanf("%d",&s);  


	printf("请输入开始位置的人的序号:\n");  
    
	scanf("%d",&st); 
	
	int a[1000];       
    
	int i;


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


		a[i]=i+1;                // 初始化数组    
     


	InitList(dl);    
    


	CreateListR(dl, a, n);   //尾插法建立双链表    


	p=dl->next;    //指向表头节点
    
	while(m<st)    //指向开始位置的节点
	{
	
	p=p->next;
	
	m++;
	
	}


//  删除过程    
     
for(i=0;i<n/2;i++)  //从第一个位置开始,第一次顺时针9人,第二次逆时针5人如此循环    
  
  
if(i%2==0)   // 以奇偶区分顺、逆时针方向    
  
  
{     


	CDLinkList *a;    


	int j=0;    
  
while(j<f-1)    //顺时针数9个人,即从第一个位置开始移动8个位置  
  
  
{    
  
  


	p=p->next;    


	if(p==dl)  
              
		j--;    // 运行到头结点时在进行一次移动  
  
  
j++;   
  
  
}    
  
  
printf("出局的序号为:%d\n",p->data);    
     
a=p;                                    
  
  
a->prior->next=a->next;    
  
  
a->next->prior=a->prior;    
    
p=a->next;    // 下一次节点开始的位置(顺时针)  
     
free(a);    
  
  
}    
  
  
else    // 逆时针移动5个位置   
  
  
{    
     
CDLinkList *a;   
  
  
int j=0;    
  
  
while(j<s-1)  //逆时针数5个人,即从第一个位置开始移动4个位置  
  
  
{    
p=p->prior;    
   
if(p==dl)  
  
  
j--;  
  
j++;    
  
  
}    
  
  
printf("出局的序号为:%d\n",p->data);    
     
a=p;                                  //删除节点    
  
  
a->prior->next=a->next;    
  
  
a->next->prior=a->prior;    
     
p=a->prior;    // 下一次节点开始的位置(逆时针)  
     
free(a);    
}    
    
     printf("剩余的序号为:\n");   
  
  
  
  
  
  
  
  
DispList(dl);    //输出剩余的序号  
      
  }    





 



运行结果:










  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值