学数据结构,自编循环链表,解约瑟夫环问题

约瑟夫环问题是,有n个人围成一个圆圈,任意给定一个正整数m,从第一个人开始依次报数,数到m时,则第m个人退出圆圈,重复进行,直至只剩下一个人为止,问最后剩下的是哪一个人?

求解方法:给n个人每人一个编号,将n个编号放在一个循环链表中,然后循环计数,每数到m,则删除相应数据元素结点(头节点跳过),删除过程执行n-1次,即完成求解。

package com.zl.test;

public class Node<T>{
    public Object  data;
    public Node next;
}

package com.zl.test;

import com.zl.test.Node;


public class CirLink<T> {
    private static Node head=null;
    /**
     * 初始化
     */
    public void initCirLink(){
        head=new Node();
        head.data=null;
        head.next=head;
    }

    /**
     * 插入节点
     * @param element :节点元素值
     */
    public void insertCirLink(T element) {
        Node node = new Node(); //初始化节点
        node.data = element;
        if (head.next == head) {
            head.next = node;
            node.next = head;
        } else {
            Node temp = head;
            while (temp.next != head) {
                temp = temp.next;
            }
            temp.next = node;
            node.next = head;

        }
    }
    /**
     * 值删除
     *
     * @param element : 要删除的值
     * @return :删除则为true 否则为假
     */
    public boolean deleteCirLink(T element) {

        Node temp = head;
        if (temp.next == head) {
            System.out.println("链表已空,没有可删除的值");
            return false;
        }
        while (temp.next != head) {
            if (temp.next.data == element) {
                temp.next = temp.next.next;
                return true;
            } else {
                temp = temp.next;
            }
        }
        return false;
    }

    /**
     * 打印
     */
    public void printCirLink() {
        Node temp = head;
        System.out.print("打印循环链表: ");
        while (temp.next != head) {
            temp = temp.next;
            System.out.print(temp.data + " ");

        }
        System.out.println();
    }
    /**
     * 求长度
     *
     * @return : 返回的长度
     */
    public  int sizeCirLink() {
        Node temp = head;
        int size = 0;
        while (temp.next != head) {
            temp = temp.next;
            size++;
        }
        return size;
    }
    /**
     * 下标删除
     *
     * @param i : 要删除的值下标
     * @return :删除则为true 否则为假
     */
    public boolean deleteIndexCirLink(int i) {


        Node temp = head;
        int index = -1;
        if (temp.next == head) {
            System.out.println("链表为空,没有可删除的值");
            return false;
        }
        if (i < 0 || i >= sizeCirLink()) {
            System.out.println("下标越界");
            return false;
        }
        while (temp.next != head) {
            index++;
            if (index == i) {
                temp.next = temp.next.next;
            }
            temp = temp.next;
        }
        return false;

    }
    /**
     * 给定值求下标
     *
     * @param element :要找的元素
     */
    public void findIndexByData(T element) {
        Node temp = head;
        int index = -1;
        if (temp.next == head) {
            System.out.println("链表为空,无法查找!");

        }
        while (temp.next != head) {
            temp = temp.next;
            index++;
            if (temp.data == element) {
                temp = temp.next;
                System.out.println("下标为: " + index);
                return;
            }
        }
        System.out.println("要查找的值不存在!");
    }
    /**
     * 下标求值
     * @param index
     */
    public void findDataByIndex(int index) {
        Node temp = head;
        int size= 0;           //为增加下标用的
        if (temp.next == head) {
            System.out.println("链表为空,没有可查询的值!");
            return;
        }
        if (index >= sizeCirLink() || index < 0){
            System.out.println("下标越界");
            return;
        }

        while (temp.next !=head){
            temp = temp.next;

            if (size == index){
                System.out.println("要找的值为: "+temp.data);
                return;
            }
            size++;
        }
        System.out.println("要查找的值不存在");
    }
    /**
     * 下标求值
     * @param index
     */
    public Object  getDataByIndex(int index) {
        Node temp = head;
        int size= 0;           //为增加下标用的
        if (temp.next == head) {
            System.out.println("链表为空,没有可查询的值!");
            return null;
        }
        if (index >= sizeCirLink() || index < 0){
            System.out.println("下标越界");
            return null;
        }

        while (temp.next !=head){
            temp = temp.next;

            if (size == index){
                return  temp.data;
            }
            size++;
        }
        return null;
    }
}
    


package com.zl.test;
import com.zl.test.Node;
import com.zl.test.CirLink;

public class JosephusQuestion {
    public static void josephus(int n ,int m){
       //生成一个循环链表
        CirLink<Integer> cirList=new CirLink();
        //初始化
        cirList.initCirLink();
        //循环输入每个人的序号
        for (int i=1;i<=n;i++){
            cirList.insertCirLink(Integer.valueOf(i));
        }
        //从第targetIndex(数组下标)个开始重新数;
        int targetIndex = 0;
        while (cirList.sizeCirLink()!=1){
            targetIndex = (targetIndex + m)%cirList.sizeCirLink();
            if (targetIndex != 0) {//为0时为最后一个剩下来的人
                System.out.println(cirList.getDataByIndex(targetIndex-1)+"  退出");
                cirList.deleteIndexCirLink(targetIndex-1);
                targetIndex--;
            }else {
                System.out.println(cirList.getDataByIndex(cirList.sizeCirLink()-1)+"  退出");
                cirList.deleteIndexCirLink(cirList.sizeCirLink()-1);
            }
        }
        //打印剩下来的人
        System.out.println(cirList.getDataByIndex(0)+"  为最后剩下来的人 ");


    }

    public static void main(String[] args){
         // n=12  m=5
        josephus(12,5);
    }

}

当12个人围成一圈,每次数到5的人退出,依次退出和最后剩下来的人见下:

5 退出
10 退出
3 退出
9 退出
4 退出
12 退出
8 退出
7 退出
11 退出
2 退出
6 退出
1 为最后剩下来的人

发布了5 篇原创文章 · 获赞 0 · 访问量 622

猜你喜欢

转载自blog.csdn.net/helloworldchina/article/details/103948471