C语言链表实现约瑟夫环问题

需求表达:略

分析:

实现:

#include<stdio.h>
#include<stdlib.h>
typedef struct node {
        int payload ;
        struct node* next ;
}node ;

/*Function:在约瑟夫环尾部插入一个结点。add
 * param:node* tail 约瑟夫环的尾巴结点;
 * return: node* tail 返回新的约瑟夫环尾巴结点
 * */
node* add ( node* tail){
        if(tail == NULL){

           tail = (node* ) malloc(sizeof(node)) ;
           tail -> next = tail ;
           return tail ;
        }
        else{
           node* new_tail = (node* ) malloc (sizeof(node));
           new_tail -> next = tail -> next ;
           tail -> next = new_tail ;

           return new_tail;
        }
}

/*Function:遍历约瑟夫环,traverse_joseph_circle
 *param:node* tail
 *return :void
 *
 *
 * */
void traverse_joseph_circle(node* tail){
        node* move = tail  ;//作移动的指针
        //整体思路:有点结点的情况下,进入遍历;把尾结点和头结点的关系给干掉,展成一条链,回到头结点,往下移动,在往下移动前,先游历这个结点,在判断能不能往下
游历。
        while(move != NULL){
            move = move -> next ;//移动回头结点
            printf("%d ;", move -> payload) ;
            if (move == tail) break ;
        }
        printf("\n");
}
/*Function:约瑟夫环问题的实现。eliminate
 *param :node* tail; int step
 *return: void
 *
 * */
void eliminate(node* tail,int step){
        node* move = tail ;
        node* save_previous = tail ;
        int count = 0 ;
        while (NULL != tail){
            save_previous = move ;
            move = move -> next ;
            if (move == move ->next) break;
            if(++ count == step){
                save_previous -> next = move -> next ;
                printf("当前要删结点:%d\n",move -> payload);
                if (tail == move ) tail = save_previous ;//更新约瑟夫环
                free(move);
                printf("当前结点:\n");
                traverse_joseph_circle (tail) ;
                move = save_previous ;
                count = 0 ;

             }

        }
}
int main(){
        node* tail;
        //构建十个结点的约瑟夫环
        int i ;
        for ( i = 0 ; i < 20 ; i ++ ){
            tail = add (tail );
            tail -> payload = i ;
        }
        traverse_joseph_circle (tail) ;
        eliminate(tail,3);
}

效果:

[[email protected] joseph_circle]$ ./joseph_circle.out
0 ;1 ;2 ;3 ;4 ;5 ;6 ;7 ;8 ;9 ;
当前要删结点:2
当前结点:
0 ;1 ;3 ;4 ;5 ;6 ;7 ;8 ;9 ;
当前要删结点:5
当前结点:
0 ;1 ;3 ;4 ;6 ;7 ;8 ;9 ;
当前要删结点:8
当前结点:
0 ;1 ;3 ;4 ;6 ;7 ;9 ;
当前要删结点:1
当前结点:
0 ;3 ;4 ;6 ;7 ;9 ;
当前要删结点:6
当前结点:
0 ;3 ;4 ;7 ;9 ;
当前要删结点:0
当前结点:
3 ;4 ;7 ;9 ;
当前要删结点:7
当前结点:
3 ;4 ;9 ;
当前要删结点:4
当前结点:
3 ;9 ;
当前要删结点:9
当前结点:
3 ;
时间: 2024-10-12 12:11:16

C语言链表实现约瑟夫环问题的相关文章

循环单向链表(约瑟夫环)

#include <stdio.h> #include <stdlib.h> typedef struct List { int data; struct List *next; }List; //创建循环单向链表n为长度 List *list_create(int n) { List *head, *p; int i; head = (List *)malloc(sizeof(List)); p = head; p->data = 1; //创建第一个结点 for (i =

C语言数组实现约瑟夫环问题,以及对其进行时间复杂度分析

尝试表达 本人试着去表达约瑟夫环问题:一群人围成一个圈,作这样的一个游戏,选定一个人作起点以及数数的方向,这个人先数1,到下一个人数2,直到数到游戏规则约定那个数的人,比如是3,数到3的那个人就离开这个游戏:按这样的规则,剩下一个人,游戏就结束,这个人就为赢家.(读者可以试着表达,不认同,直接忽略) 抽象分析 这个人就是一个数据个体,数据结点,数据元素.上面产生的数据结构为:单方向循环的链.可以用链表实现,也可以用数组来实现. 链表到数组的迁移 人(数据元素. 数据结点.数据个体) 结点关系 (

环形链表与约瑟夫环问题

思路: 代码: public class Josepfu { public static void main(String[] args) { // 测试一把看看构建环形链表,和遍历是否ok CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); circleSingleLinkedList.addBoy(125);// 加入5个小孩节点 circleSingleLinkedList.showBo

约瑟夫环 C语言 单循环链表

/*---------约瑟夫环---------*/ /*---------问题描述---------*/ /*编号为1,2,-,n的n个人围坐一圈,每人持一个密码(正整数). 一开始任选一个正整数作为报数上限值m, 从第一个人开始自1开始顺序报数,报到m时停止. 报m的人出列,将他的密码作为新的m值,从他的下一个人开始重新从1报数, 如此下去,直至所有人全部出列为止.试设计一个程序求出列顺序.*/ /*---------问题分析---------*/ /*n个人围坐一圈,且不断有人出列,即频繁

约瑟夫环(N个人围桌,C语言,数据结构)

约瑟夫环问题(C语言.数据结构版) 一.问题描述 N个人围城一桌(首位相连),约定从1报数,报到数为k的人出局,然后下一位又从1开始报,以此类推.最后留下的人获胜.(有很多类似问题,如猴子选代王等等,解法都一样) 二.思路分析 (1)可将人的顺序简单编号,从1到N: (2)构造一个循环链表,可以解决首位相连的问题,同时如果将人的编号改为人名或者其他比较方便 (3)将人的编号插入到结构体的Data域: (4)遍历人的编号,输出参与的人的编号: (5)开始报数,从头报数,报到k的人出局(删除次结点)

小朋友学数据结构(1):约瑟夫环的链表解法、数组解法和数学公式解法

约瑟夫环的链表解法.数组解法和数学公式解法 约瑟夫环(Josephus)问题是由古罗马的史学家约瑟夫(Josephus)提出的,他参加并记录了公元66-70年犹太人反抗罗马的起义.约瑟夫作为一个将军,设法守住了裘达伯特城达47天之久,在城市沦陷之后,他和40名死硬的将士在附近的一个洞穴中避难.在那里,这些叛乱者表决说"要投降毋宁死".于是,约瑟夫建议每个人轮流杀死他旁边的人,而这个顺序是由抽签决定的.约瑟夫有预谋地抓到了最后一签,并且,作为洞穴中的两个幸存者之一,他说服了他原先的牺牲品

约瑟夫环的C语言数组实现

约瑟夫环问题的具体描述是:设有编号为1,2,--,n的n个(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,才从他的下一个人起重新报数,报到m时停止报数,报m的出圈,--,如此下去,知道剩余1个人为止.当任意给定n和m后,设计算法求n个人出圈的次序. 一开始看到这这个题目就是觉得这是一个环形的,想到了用链表和用指针,然后看题目的要求是使用数组实现.就先暂时放弃用链表的办法,用数组实现之后再用链表来实现. 一开始的思路是: 1.建立一个长度为n的数组. 2.取出位置编号

约瑟夫环问题的两种实现[链表+数组]

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列. 以下是使用循环链表和数组的两种实现: 1 #include<iostream> 2 using namespace std; 3 4 struct Node 5 { 6 int data; 7 Node *next; 8 }; 9 void CreateLink

C语言用数组解决约瑟夫环问题

       在罗马人占领乔塔帕特后,39 个犹太人与约瑟夫及他的朋友躲到一个洞中,大家决定宁愿自杀也不要被敌人抓到,于是确定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止.然而约瑟夫和他的朋友并不想死去,那么他应该怎样安排他和他的朋友的位置,才能逃脱这场死亡游戏呢?         用C语言解决约瑟夫环问题的最佳方式是采用循环链表,但使用数组同样也可以解决瑟夫环的问题.采用循环链表的方法,以后详述.本节主