数据结构程序设计--约瑟夫双向生死问题

来源:互联网 发布:阿里云北京分公司 编辑:程序博客网 时间:2024/05/22 08:02

随着一学年的学习,数据结构课已经结课了,随之而来的便是课程设计。此次课程设计老师安排的题目里大多都是系统之类的课题,研究起来逻辑复杂度较低,实现起来比较依靠代码量,所以我选择了一个逻辑较为复杂的约瑟夫衍生问题——约瑟夫双向生死问题。

一下是我的设计完成代码:

一、首先是主函数:

/************************************************************版权所有(C)2017,WangMingZe。**文件名称:main.cpp*文件标识:无*内容摘要:该代码是主函数代码,统筹算法库的功能。*其它说明:无*当前版本:V1.5*作者:王铭泽*完成日期:2017,12,20***********************************************************    题目:约瑟夫双向生死问题(先顺时针后逆时针计数);    描述:一共30人,从第1个人开始顺时针报数到9者被扔下去,然后从其顺时针的下一个人开始,逆时针报数到5者被扔下去,然后从其逆时针的下一个人开始    继续重复顺时针过程。知道剩余15人。    细节:一、function1的功能是建立一个双向循环链表,传入了一个整形数组a包含1-30个整数,和双向链表头b。          最后返回一个双向循环链表b。          二、function2包含function3和function4.其中f3是用来完成顺时针找人的函数,f4是用来完成逆时针找人的函数。f2用while(n<15)这个循环来完          反复的工作,在此过程中用一个positon[15]整形数组来记下被扔掉的人。          三、main()函数的工作室统筹一个function系列函数,使他们完成双向生死问题。***********************************************************/#include <stdio.h>#include <malloc.h>#include "cd.h"int main(){    printf("***This is a proeject on Joseph's question.***\n");    printf("(note:A array of type char is already included in this program.)\n\n");    Node *A,*temp;    char m[15];    int nums=0,i=0;    char t[31]= {'a','b','c','d','e','f','g','h','i','j',                 'k','l','m','n','o','p','q','r','s','t',                 'u','v','w','x','y','z','1','2','3','4','\0'                };    printf("Intialize the contestants:");    while(t[i]!='\0')    {        printf("%c ",t[i]);        i++;    }    printf("\n");    printf("\n");    CreateNode(A,t);    temp=A;    temp=FindPerson(temp,m,nums);    display(A,m,nums);    InsertNode(A,'&',3);    printf("\n");    display(A,m,nums);    printf("\n");    printf("\n");    return 0;}


二、其次是头文件

/************************************************************版权所有(C)2017,WangMingZe。**文件名称:main.cpp*文件标识:无*内容摘要:本文件为头文件,定义了节点结构体,和声明了函数头。*其它说明:无*当前版本:V1.5*作者:王铭泽*完成日期:2017,12,20***********************************************************/#ifndef CD_H_INCLUDED#define CD_H_INCLUDED//定义每一个节点类型,包含一个数据域,和一个指向后记节点nextnode和前驱节点的指针prenode。typedef struct node{    char data;    struct node *nextnode;    struct node *prenode;} Node;/**  功能实现的大体思路:  1.在主函数里声明一个大小为30的字符数组,调用函数CreateNode创建头结点为b的双向循坏链表。  2.接下来便是完成从30个人删除到15个人的操作,条用的函数是FindPerson,而该函数的内部大体分为两个步骤第一是顺时针删除第九个人,    第二是逆时针删除第五个人。所以FindPerson函数里面调用了顺时针删除ClockWise函数和逆时针删除CountClockWise函数。然后通过细节    连接实现。  3.最后一步便是输出这个删除后的链表。调用了Display函数。   说明:函数InsertNode是用来实现在链表里插入节点的功能,而SearchNode是实现在链表里搜索一个值是否存在功能的。        (以上具体实现细节在函数里说明)。**/void CreateNode(Node *&b,char a[]);//creat a Two-way circular linked list by array a;Node *ClockWise (Node *&b,char *m[],int &nums);//delete the node by clockwise;Node *CountClockWise(Node *&b,char *m[],int &nums);//delete the node by countclockwise;Node *FindPerson(Node *&b,char m[15],int &nums);//using CW and CCW;void display(Node *b,char *m,int &nums);void InsertNode(Node *&b,char a,int p);//insert node;bool SearchNode(Node *b,char a);//search the node,return true when a exists in b;#endif // CD_H_INCLUDED


三、最后便是头文件对应的实现

/************************************************************版权所有(C)2017,WangMingZe。**文件名称:main.cpp*文件标识:无*内容摘要:本文件是头文件实现即资源文件,文件里定义了函数内容。*其它说明:无*当前版本:V1.5*作者:王铭泽*完成日期:2017,12,20***********************************************************/#include<stdio.h>#include<malloc.h>#include"cd.h"/**功能:创建双向循环链表。输入参数:Node节点b和一个字符数组a。输出:一个b节点为头结点的循环双向链表实现思路:用while 循环调用字符数组里的每一个元素用ch存放,在每次调用的时候都创建一个Node节点连接到b链表上,**/void CreateNode(Node *&b,char a[])//creat a Two-way circular linked list by array a;{    Node *p,*tail;                  //p用来保存每次循环创建的空间指针头,tail永远指向当前链表的最后一个节点即尾巴节点。    int i=1;    char ch;                        //存放a数组里的值    b=(Node *)malloc(sizeof(Node));//初始化头结点b,给b开一个新的Node大小的空间。    b->data=a[0];//给头结点赋值。    if(b==NULL)//开辟空间是否成功(一般都成功,防止bug加上比较妥当点儿。。。)。    {        printf("creat fail\n");        exit(1);//失败便退出。    }    tail=b;//第一次尾巴节点等于头结点。    ch=a[i++];//ch存放a的第一个元素,并且让i指向序号2为下一次ch存放做准备。    while(ch!='\0')//while循环节结束标志是'\0'即在a数组中循环按a【0】,a【1】,a【2】...一直循环到a【30】结束。也就是说while中ch只                   //表示了一个值    {        p=(Node *)malloc(sizeof(Node));//开辟新的节点。        if(p==NULL)//判断开辟是否成功。        {            printf("creat fail\n");            exit(1);        }    //下面代码是完成新节点插入到当前列表最后一个元素后面。        p->data=ch;//先把ch赋值给p节点的数据域。        p->prenode=tail;//因为tail永远指向链表的最后一个元素,所以这一步完成的是新节点的前驱指针指向tail,        tail->nextnode=p;//尾巴指针的后继指针指向新节点。        tail=p;//因为新节点在tail的后面所以更新tail的值指向新节点p。    //更新ch值指向a的下一个元素。        ch=a[i++];    }    //这个链表还是循环列表所以还得把链表最后一个元素与头结点连接起来。    tail->nextnode=b;//尾巴节点的后继指针指向头结点。    b->prenode=tail;//头结点的前驱指针指向尾巴节点。}/**    功能:从节点b开始顺序报数到9的人被删除。    输入参数:Node节点b    输出:无    实现思路:找出b开始的第九个节点p,然后记住p的前节点x和后节点x1,最后令x与x1相连,最后释放p;**/Node *ClockWise (Node *&b,char *m,int &nums)//delete the node by clockwise{    int num=9;    Node *p=b,*x,*x1;//x指向第九个元素指针的前一个元素,x1指向第九个指针的后一个元素。    //用循环令p指向第九个节点的指针。    while(num>1)    {        p=p->nextnode;        num--;    }    //找到后开始删除操作    m[nums++]=p->data;//由于要求需要记下被删除人的节点所以定义了一个全局变量字符数组m来记录删除人。此条代码是记录当前要删除人的信息。    x=p->prenode;//x记下p的前一个节点的地址    x1=p->nextnode;//x1记下p的后一个节点的地址。    x->nextnode=x1;//x的后继指针指向x1;    x1->prenode=x;//x1的前驱指针指向x;    //由此完成了节点的链接    free(p);//释放要删除的节点。    return x1;//要求里写,顺序删除之后下次计数的开始节点是删除节点的后一个节点,所以返回删除节点的后一个节点x1;}/**    功能:从节点b开始逆时针报数到第5人被删除。    输入参数:Node节点b    printf("\n");    输出:无    实现思路:找出b开始的第五个节点p,然后记住p的前节点x和后节点x1,最后令x与x1相连,最后释放p;**///由于是双向链表,顺序删除和逆向删除是一样的,只不过是用nextnode和prenode的区别。Node *CountClockWise(Node *&b,char *m,int &nums)//delete the node by countclockwise;{    int num=5;    Node *p=b,*x,*x1;    //令p指向第五个人。    while(num>1)    {        p=p->prenode;        num--;    }    m[nums++]=p->data;    x=p->prenode;    x1=p->nextnode;    x->nextnode=x1;    x1->prenode=x;    free(p);    return x;}/**    功能:综合clockswise函数和countclockswise实现传入一个指针b删除15个人。    传入参数:Node节点b    输出:无    大体实现思路:在一个while循环里循环判断条件是n>0,由于n是从15开始递减的所以共删除了15个人。**/Node *FindPerson(Node *&b,char *x,int &nums)//using CW and CCW;note:the x pointer point to the head of array,m is the same way in function CW ang CCW.{    Node *temp;    temp=b;    int n=15;    while(n>0)    {        temp=ClockWise(temp,x,nums);//先顺序删除第九个人,返回第十个人的地址。        n--;//15个人-1。        if(n<1)break;//过程中判断一下是否已经删除了15个人了,如果删除到了15个人则直接退出 用break退出while循环        temp=CountClockWise(temp,x,nums);        n--;    }    return temp;}/*    功能:输出链表b里的数据域和被删除的人    传入参数:Node节点b    输出:间隔3个空格的15个数据。和被删除的15个人位置。*/void display(Node *b,char *m,int &nums){    Node *p=b;    if(b==NULL)    {        printf("NULL!\n");        exit(1);    }    else    {        printf("The following is the final result:\n");        while(p->nextnode!=b)        {            printf("%3c",p->data);            p=p->nextnode;        }            printf("%3c",p->data);    }    int j=0;    printf("\nThe position and number of person to be delete:\n");    while(j<nums)    {        printf("%3c",m[j]);        j++;    }}/*    功能:往b的第p个位置插入一个字符a,    传入参数:Node节点b,字符a和插入位置b。    输出:无*/void InsertNode(Node *&b,char a,int p)//insert node;{    Node *news,*s=b,*pre;    int x=p;    while(x>1)    {        s=s->nextnode;        x--;    }    pre=s->prenode;    news=(Node *)malloc(sizeof(Node));    news->data=a;    pre->nextnode=news;    news->prenode=pre;    news->nextnode=s;    s->prenode=news;    if(p==1)    {        b=b->prenode;    }}/**    功能:从Node节点b中查找是否有a字符的节点存在。如果存在返回true,如果不存在返回false。    传入参数:Node节点b和要查找的字符a。    输出:无**/bool SearchNode(Node *b,char a)//search the node,return true when a exists in b;{    Node *p;    p=b;    while(p->nextnode!=b)    {        if(p->data==a)            return true;        p=p->nextnode;    }    if(p->data==a)        return true;    else        return false;}




运行结果附图:



原创粉丝点击