双向链表和环形链表(约瑟夫问题)

双向链表
package linkedlist;

public class DooubleLinkedListDemo {
    public static void main(String[] args) {
        HeroNode2 hero1 = new HeroNode2(1,"宋江","及时雨");
        HeroNode2 hero2 = new HeroNode2(2,"卢俊义","玉麒麟");
        HeroNode2 hero3 = new HeroNode2(3,"吴用","智多星");
        HeroNode2 hero4 = new HeroNode2(4,"林冲","豹子头");
        DoubleLinkeList dll = new DoubleLinkeList();
//      dll.add(hero1);
//      dll.add(hero2);
//      dll.add(hero3);
//      dll.add(hero4);
//      dll.list();
//      HeroNode2 hero5 = new HeroNode2(4,"零充","豹子头");
//      dll.update(hero5);
//      dll.list();
//      dll.del(3);
        dll.addByOrder(hero1);
        dll.addByOrder(hero2);
        dll.list();

    }
}

//创建一个双向链表的类
class DoubleLinkeList{
    //初始化一个头结点
    private HeroNode2 head = new HeroNode2(0,"","");
    public HeroNode2 getHead() {
        return head;
    }

    //遍历双向链表的方法
    public void list() {
        if(head.next == null) {
            System.out.println("链表为null");
            return;
        }
        //定义辅助变量来遍历
        HeroNode2 temp = head.next;
        while(true) {
            if(temp == null) {
                break;
            }
            System.out.println(temp);
            temp=temp.next;
        }

    }

    //添加节点
    public void add(HeroNode2 heroNode) {
        //创建辅助及节点
        HeroNode2 temp = head;
        //找到链表最后的节点
        while(true) {
            if(temp.next == null) {
                break;
            }
            //没有找到,往后移
            temp=temp.next;
        }
        temp.next = heroNode;
        heroNode.pre=temp;
    }

    //有序添加
    public void addByOrder(HeroNode2 heroNode) {
        HeroNode2 temp = head;//临时变量
        boolean flag = false;//英雄没有存在就添加
        while(true) {
            if(temp.next == null) {
                break;
            }
            if(temp.next.no>heroNode.no) {
                break;
            }else if(temp.next.no == heroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;

        }
        if(flag) {
            System.out.println("编号已经存在");
        }else {
            temp.next=heroNode;
            heroNode.pre=temp;
        }

    }

    //修改节点的内容
    public void update(HeroNode2 newHeroNode) {
        if(head.next == null) {
            System.out.println("链表为空");
            return;
        }
        //定义辅助变量
        HeroNode2 temp = head.next;
        boolean flag = false;
        while(true) {
            if(temp == null) {
                break;
            }
            if(temp.no == newHeroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag) {
            temp.name = newHeroNode.name;
            temp.nickname = newHeroNode.nickname;
        }else {
            System.out.println("没有找到要修改的编号");
        }
    }

    //删除节点
    public void del(int no) {
        if(head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode2 temp = head.next;
        boolean flag = false;
        while(true) {
            if(temp == null) {
                break;
            }
            if(temp.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag) {
            temp.pre.next = temp.next;
            if(temp.next != null ) {
                temp.next.pre = temp.pre;
            }
        }else {
            System.out.println("没有找到要删除的节点");
        }
    }

}

//定义HeroNode,每个HeroNode 对象就是一个节点
class HeroNode2{

    public int no;
    public String name;
    public String nickname;
    public HeroNode2 next;//指向下一个节点
    public HeroNode2 pre;//指向上一个节点

    //构造器
    public HeroNode2(int no, String name ,String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    @Override
    public String toString() {
        return "HeroNode [no=" + no + ", name=" + name + ", nickname=" + nickname + "]";
    }
}

约瑟夫问题

package linkedlist;

public class Josephu {
    public static void main(String[] args) {
        CircleSingleLinkedList csll = new CircleSingleLinkedList();
        csll.addBoy(5);
        csll.showBoy();

        csll.countBoy(1, 2, 5);
    }
}

//创建一个环形单向链表
class CircleSingleLinkedList{
    //创建一个first节点,当前没有编号
    private Boy first = null;
    //添加小孩节点,构建成一个环形的链表
    public void addBoy(int nums) {
        //nums 做一个数据校验
        if(nums < 1) {
            System.out.println("nums的值不正确");
            return;
        }
        Boy curBoy = null;//辅助指针,帮助构建环形链表
        //使用for循环创建我们环形链表
        for(int i=1; i<=nums; i++) {
            //根据编号,创建小孩节点
            Boy boy = new Boy(i);
            //如果是第一个小孩
            if(i == 1) {
                first =boy;
                first.setNext(first);//构成环装
                curBoy = first;//让curBoy指向第一个小孩
            }else {
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }
        }
    }

    //遍历
    public void showBoy() {
        if(first.getNext() == null) {
            System.out.println("链表为空");
            return;
        }
        Boy curBoy = first;
        while(true){
            System.out.println(curBoy.getNo());
            if(curBoy.getNext() == first) {
                break;
            }
            curBoy = curBoy.getNext();
        }
    }

    //根据用户输入,计算出小孩的出圈顺序
    //startNo 表示从第几个小孩开始数数
    //countNum 表示数几下
    //nums 表示最初由多少个小孩在圈中
    public void countBoy(int startNo,int countNum,int nums) {
        if(first == null || startNo <1 || startNo>nums) {
            System.out.println("参数输入有误");
            return;
        }
        //创建辅助指针,帮助完成小孩出圈
        Boy helper = first;
        //需求创建一个辅助指针helper,事先应该指向环形链表的最后这个节点
        while(true) {
            if(helper.getNext() == first) {
                break;
            }
            helper = helper.getNext();
        }
        for(int j=0;j<startNo-1;j++) {
            first = first.getNext();
            helper = helper.getNext();
        }
        while(true) {
            if(helper == first) {
                break;
            }
            //让first和helper指针同时移动
            for(int j=0;j<countNum-1;j++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            System.out.println("小孩出圈"+first.getNo());
            first=first.getNext();
            helper.setNext(first);
        }
        System.out.println("最后留在圈中额小孩编号"+first.getNo());
    }
}

class Boy{
    private int no;//编号
    private Boy next;//指向下一个节点

    public Boy(int no) {
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Boy getNext() {
        return next;
    }

    public void setNext(Boy next) {
        this.next = next;
    }
}

原文地址:https://www.cnblogs.com/train99999/p/11107839.html

时间: 2024-11-02 15:22:38

双向链表和环形链表(约瑟夫问题)的相关文章

php实现单,双向链表,环形链表解决约瑟夫问题

传智播客PHP学院 韩顺平 PHP程序员玩转算法第一季  http://php.itcast.cn 聊天篇: 数学对我们编程来说,重不重要? 看你站在什么样的层次来说. 如果你应用程序开发,对数学要求不高 但是,如果你开发系统软件,比如(搜索/识别软件[图像,语言识别]/操作系统...)对数学高 建模.大量数学模型. 老师啊啊.我是学C++的.麻烦,谈哈对QT和MFC的看法嘛.前景什么的, 记住 : 打好基础,大有可为! 初中毕业能去传智学习吗? 学习It, 不管是java ,php ,c#,对

数据结构和算法--3链表(单向链表、双向链表、环形单向链表和约瑟夫问题)

链表 链表是以节点的方式来存储 每个节点包含data域和next域,指向下一个节点 链表的各个节点不一定是连续存储 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定 单向列表 最大特点是可以将物理地址上不连续的数据连接起来,通过指针来对物理地址进行操作,实现增删改查等功能. 单链表分为两种:有头链表和无头链表. 有头节点的增删改查 定义一个单链表的类: //定义一个SingleLinkedList,单链表,管理HeroNode class SingleLinkedList{ //初始

java 环形链表实现约瑟夫(Joseph)问题

约瑟夫问题又名丢手绢问题.相传著名犹太历史学家 Josephus 利用其规则躲过了一场自杀游戏,而后投降了罗马. 问题: 已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.* 从编号为k的人开始报数,数到m的那个人出列:* 他的下一个人又从1开始报数,数到m的那个人又出列:* 依此规律重复下去,直到圆桌周围的人全部出列. 用节点来模拟游戏中的人,用链表来表示游戏中的人按一定的顺序排列.每一个节点给一个编号,从编号为k的节点开始计数,计到m的节点从链表中退出.之后m的下一个节点从新

实现约瑟夫环形链表

题目 41个人排成一个圆圈,由第1个人 开始报数,每报数到第3人,该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止.约瑟夫与朋友在第16与第31个位置,于是活了下来.请用单向环形链表描述该结构并呈现整个自杀过程. 设计 首先要设计一个节点模型 class Node { int value; Node next; Node(int value) { this.value = value; } } 遍历并用 last 节点做成一个单向线性的链表,之后将自身的初始节点指向last.ne

Java数据结构之单向环形链表(解决Josephu约瑟夫环问题)

1.Josephu(约瑟夫.约瑟夫环)问题: 设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列. 提示: 用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法

约瑟夫问题 环形链表及递归

//--------------------环形链表 //#include <windows.h> //#include <iostream> //using namespace std; // //#define R 40//人数 //#define N 4//每隔多少删去一个节点 // //struct node //{ // int id; // node *next; //}; // //void initCircle(node *phead, int num) //{ /

环形链表与约瑟夫环问题

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

C# 数据结构 - 单链表 双链表 环形链表

链表特点(单链表 双链表) 优点:插入和删除非常快.因为单链表只需要修改Next指向的节点,双链表只需要指向Next和Prev的节点就可以完成插入和删除操作. 缺点:当需要查找某一个节点的时候就需要一个节点一个节点去访问,这样所花的时候就比较多了.(顺序表可以弥补这缺点,但插入和删除就非常耗性能) 单链表 单链表的构成:必须要有一个链表头(head),每个节点里面有一个Next用于指向下一个节点(类似于指针).最后一个节点的Next为null来标识链表的尾. 如下图 代码实现 1 /* ----

单向环形链表

单向环形链表(Josepfu) 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)按顺时针方向围坐在一张圆桌周围,每个人持有一个密码(正整数).一开始任选一个整数作为报数上限值m,从第一个人开始顺时针自1报数,报到m时停止报数,报m的那个人出列,他的密码作为新的m值,从他在顺时针方向上的下一个人又开始重新从1报数,报到m的那个人出列又出列:依此规律重复下去,直到圆桌周围的人全部出列 /* 约瑟夫问题 */ public class Josepfu { pu