ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【恋上数据结构】约瑟夫问题(循环链表解决)

2021-12-29 11:32:22  阅读:159  来源: 互联网

标签:Node node prev index 恋上 next 链表 数据结构 first


练习-约瑟夫问题

约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3。

分析:

(1)由于对于每个人只有死和活两种状态,因此可以用布尔型数组标记每个人的状态,可用true表示死,false表示活。

(2)开始时每个人都是活的,所以数组初值全部赋为false。

(3)模拟杀人过程,直到所有人都被杀死为止。

在这里插入图片描述

为了活到最后,我们只能写个算法来帮我们算了!!

思路:

  • 使用循环链表
  • 用一个指针,用于指向节点
  • 增加一个reset方法,重置指针指向头结点
  • 增加一个next方法,让指针往后走一步
  • 增加一个remove方法,用于杀死指针指向的节点,删除后指向下一个节点。
public class JosephusProblem {
    public static void main(String[] args) {
       josephus(3,8);
    }

    /**
     * @param m 数到几淘汰
     * @param people 共有几个人
     */
    public static void josephus(int m,int people){
        CircleLinkedList<Integer> list = new CircleLinkedList<>();
        for (int i = 1; i <= people; i++) {
            list.add(i);
        }
        System.out.println(list.toString());
        //指向头结点
        list.reset();
        //循环杀
        while(! list.isEmpty()){
            for (int i = 1; i < m; i++) {
                list.next();
            }
            System.out.println(list.remove());
        }
    }
}

package 链式结构.test;

import common.AbstractList;

/**
 * @ClassName: CircleLinkedList
 * @Description: 循环链表
 * @author: wangz48
 * @date: 2021-12-29 10:39
 */
public class CircleLinkedList<E> {
    /**
     * 第一个节点
     */
    private Node<E> first;
    /**
     * 最后一个节点
     */
    private Node<E> last;
    /**
     * 当前节点指针
     */
    private Node<E> current;

    /**
     * 双向循环链表节点类
     * @param <E>
     */
    private static class Node<E> {
        E element;
        Node<E> prev;
        Node<E> next;
        public Node(Node<E> prev, E element, Node<E> next) {
            this.prev = prev;
            this.element = element;
            this.next = next;
        }
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            if (prev != null) {
                sb.append(prev.element);
            } else {
                sb.append("null");
            }
            sb.append("_").append(element).append("_");

            if (next != null) {
                sb.append(next.element);
            } else {
                sb.append("null");
            }
            return sb.toString();
        }
    }
    /*===================================================*/

    /**
     * 重置节点
     */
    public void reset(){
        current = first;
    }

    /**
     * 移动指针
     */
    public E next(){
        if (current == null){
            return null;
        }
        current = current.next;
        return current.element;
    }

    /**
     * 删除指向的节点
     */
    public E remove(){
        if(current == null){return null;}
        Node<E> next = current.next;
        E element = remove(current);
        if (size == 0) {
            current = null;
        } else {
            current = next;
        }

        return element;
    }
    private E remove(Node<E> node) {
        if (size == 1) {
            first = null;
            last = null;
        } else {
            Node<E> prev = node.prev;
            Node<E> next = node.next;
            prev.next = next;
            next.prev = prev;

            if (node == first) { // index == 0
                first = next;
            }

            if (node == last) { // index == size - 1
                last = prev;
            }
        }

        size--;
        return node.element;
    }

    public void add(int index, E element) {
        rangeCheckForAdd(index);

        // size == 0
        // index == 0
        if (index == size) { // 往最后面添加元素
            Node<E> oldLast = last;
            last = new Node<>(oldLast, element, first);
            if (oldLast == null) { // 这是链表添加的第一个元素
                first = last;
                first.next = first;
                first.prev = first;
            } else {
                oldLast.next = last;
                first.prev = last;
            }
        } else {
            Node<E> next = node(index);
            Node<E> prev = next.prev;
            Node<E> node = new Node<>(prev, element, next);
            next.prev = node;
            prev.next = node;

            if (next == first) { // index == 0
                first = node;
            }
        }

        size++;
    }

    /**
     * 获取index位置对应的节点对象
     * @param index
     * @return
     */
    private Node<E> node(int index) {
        rangeCheck(index);

        if (index < (size >> 1)) {
            Node<E> node = first;
            for (int i = 0; i < index; i++) {
                node = node.next;
            }
            return node;
        } else {
            Node<E> node = last;
            for (int i = size - 1; i > index; i--) {
                node = node.prev;
            }
            return node;
        }
    }
    /*====================================================*/

在这里插入图片描述

标签:Node,node,prev,index,恋上,next,链表,数据结构,first
来源: https://blog.csdn.net/Ares___/article/details/122211718

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有