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

来源:互联网 发布:unix环境高级编程 chm 编辑:程序博客网 时间:2024/05/22 09:07

问题及描述:


约瑟夫双向生死问题是建立在约瑟夫问题基础上,正向计数后反向计数,然后在正向计数,然后在正向计数。具体描述如下: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);    //输出剩余的序号          }     



运行结果:




                                             
0 0
原创粉丝点击