循环链表的经典问题

版权声明:欢迎朋友们的观摩,标注原创的文章,如应用,请标明出处,谢谢。 https://blog.csdn.net/qq_37012770/article/details/78079992

在罗马人占领桥塔帕特之后,39人和约瑟夫以及他的朋友躲到一个山洞里,39个犹太人宁愿死,也不愿意被抓,于是他们想到一个自杀的方式:41人排成一圈,由第一个人开始报数,每数到三,该人就必须自杀,然后由下一个人再开始报数,直到所有人都自杀身亡为止。怎样安排顺序才能让约瑟夫和他的朋友活到最后呢?

这是一个循环链表的经典问题

顺便将之前学的不太扎实的链表的创建、元素删除一并练习了

#include<stdio.h>
#include<stdlib.h>

typedef struct node{
                                            /**结构体定义了一个节点data就是节点数据域,*next就是节点的指针域。
                                            用一个结构,整出链表要用到的每一个节点*/
    int data;//数据 
    struct node *next;//指向下一个位置的指针 
}node;

node* create/*创建*/(int n){              //指针类型的函数 ,所传的值n是总人数 
    node *p = NULL, *head;                  //用结构体指针声明一个临时的中间指针,指向当前节点 p是经常需要换人的 
    head = (node*)malloc(sizeof (node ));   //为头结点分配内存空间;;;创建一个头结
    p = head;                               //头结点指向中间节点
    node *s;
    int i = 1;                              //声明变量i,作为当前的元素位置记录 


    if( 0 != n){                            /**每次都会kill 一个人,所以(0 != n )就是说还有人活着 ,就继续*/
                                            // 前面那句说错了,应该是如果传经来的人数不为零,就开始工作 
        while(i <= n){                      //如果当前标记位置小于总人数 ,每次循环,都会i++ ,共执行41此 
            s = (node*)malloc(sizeof(node));//动态的分配存储空间 ,s和p是一样的,都是临时的 
            s->data = i++;                  //将s节点对应的数据赋值给i,之后i再++
                                            //其实就是为了循环链表初始化,第一个节点为1,第二个节点为2 
            p->next = s;                    //p是从头结点开始的,而s是从1号位置开始的,,
                                            // 这一行和下面一行是联合起来看的,头不是1,而是0位置,所以p总是比s慢一拍,所以才会有  一个指一个,一个指一个  的效果。 
            p = s;
        }
        s->next = head->next;               //这一切都结束之后,尾部指向第一个节点,而不是头节点 


    }
    free(head);                             //此时尾指针已经指向第一个节点了,所以就不需要头指针了,于是释放掉。
    return s->next;                         //++++++++++++++返回值是一个指针,指向链表第一个节点的指针 
                                            //s此时又是作为尾而指向第一个节点的,所以返回的就是第一个结点的地址 

}


int main()
{
    int n = 41;                             //确定人数 
    int m = 3;                              //每次间断的人数 
    int i;                                  //控制变量,不用管,后面加上的 
    node *p = create( n);                   //++++++++++++++返回值是一个指针,指向链表第一个节点的指针 ,改地址存放在p这个指针里面 
    node *temp;                             //声明临时指针,########################## 
    m %= n;                                 //这里是等于2;//这个取余数,就意味着总人数间隔三位下来,有两个人存活 

    while(p != p->next){                    //自个指向自个,就是只剩下一个人了,就是一个空表了,就结束 
        for(i = 1;i < m-1; i++){            //链表开始,要适应从1开始数数,而不是0 ,
                                            //m=2的话,该循环就执行一次, 
            p = p->next;                    //p当前指向第一个节点,p->next就是指向第二个节点了,再将第二个节点赋值给p,作为当前的地址 
        }
        printf("%d-->",p->next->data);      //输出p节点指针域指向的数据 p当前是第二个地址,那么输出端的p->next就是第三个人了p->next->data就是这个人的号码 


                                            //开始删除节点了  
        temp = p->next;                     //删除第m个节点
        p->next = temp->next ;
        free(temp);

        p = p->next;
    }
    printf("%d\n",p->data);                 //打印最后判定的人是谁 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37012770/article/details/78079992