java基于双向环形链表解决丢手帕问题的方法示例

本文实例讲述了java基于双向环形链表解决丢手帕问题的方法。分享给大家供大家参考,具体如下:

问题:设编号为1、2……n的几个小孩围坐一圈,约定编号为k(1=<k<=n)的小孩从1开始报数,数到m的那个出列,他的下一位又从1开始报数,数到m的那个人又出列,直到所有人出列为止,由此产生一个出队编号的序列。

我们现在用一个双向环形链表来解这一问题。先来看看下面这幅图:

圆圈代表一个结点,红色的指针指向下一个元素,紫色的指针指向上一个元素。first指针指向第一个元素,表明第一个元素的位置,cursor是游标指针,它的作用重大。那么这个环形的链表就可以模拟小孩排成的圆圈,下面是具体的代码:

public class Test {
  public static void main(String[] args){
      CycleLink cl=new CycleLink(5); //构造环形链表
      System.out.println("我们测试结果:");
      cl.print();
      cl.setK(2); //设置从第几个小孩开始数数
      cl.setM(3); //设置数几下
      cl.play(); //开始游戏
  }
}
class Child{
  int no;
  Child nextChild;
  Child previousChild;
  public Child(int no){
    this.no=no;
  }
}
class CycleLink{
  Child first;
  Child cursor;
  int length;
  //从第几个小孩开始数
  private int k=1;
  //数几下
  private int m=1;
  //构造函数
  public CycleLink(int len){
    this.length=len;
    for(int i=1;i<=length;i++){
      Child ch=new Child(i);
      if(i==1){
        first=ch;
        cursor=ch;
      }else if(i<length){
        cursor.nextChild=ch;
        ch.previousChild=cursor;
        cursor=ch;
      }else {
        cursor.nextChild=ch;
        ch.previousChild=cursor;
        cursor=ch;
        ch.nextChild=first;
        first.previousChild=ch;
      }
    }
  }
  //打印链表
  public void print(){
    cursor=first;
    do{
      System.out.print(cursor.no+"<<");
      cursor=cursor.nextChild;
    }while(cursor!=first);
    System.out.println();
  }
  //开始游戏
  public void play(){
    Child temp;
    cursor=first;
    //先找到第k个小孩
    while(cursor.no<k){
      cursor=cursor.nextChild;
    }
    while(length>1){
      //数m下
      for(int i=1;i<m;i++){
        cursor=cursor.nextChild;
      }
      System.out.println("小孩"+cursor.no+"出局了!");
      //找到前一个小孩
      temp=cursor.previousChild;
//     temp=cursor;
//     do{
//       temp=temp.nextChild;
//     }while(temp.nextChild!=cursor);
      temp.nextChild=cursor.nextChild;
      cursor.nextChild.previousChild=temp;
      cursor=cursor.nextChild;
      length--;
    }
    System.out.println("最后一个出局的小孩是"+cursor.no);
  }
  public void setK(int k) {
    this.k = k;
  }
  public void setM(int m) {
    this.m = m;
  }
}

这个代码的基本框架是根据韩顺平的视频的。不过他用的是一个单向的链表,上面的代码注释的部分是用来找cursor所指向的元素的上一个元素的,是将整个链表转了一圈来实现的。这里我改成了双向链表,直接用一个cursor.previousChild就可以了。

运行结果:

更多关于java算法相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》

希望本文所述对大家java程序设计有所帮助。

(0)

相关推荐

  • Java语言中链表和双向链表

    链表是一种重要的数据结构,在程序设计中占有很重要的地位.C语言和C++语言中是用指针来实现链表结构的,由于Java语言不提供指针,所以有人认为在Java语言中不能实现链表,其实不然,Java语言比C和C++更容易实现链表结构.Java语言中的对象引用实际上是一个指针(本文中的指针均为概念上的意义,而非语言提供的数据类型),所以我们可以编写这样的类来实现链表中的结点. class Node { Object data; Node next;//指向下一个结点 } 将数据域定义成Object类是因为

  • 浅谈java实现背包算法(0-1背包问题)

    0-1背包的问题 背包问题(Knapsack problem)是一种组合优化的NP完全问题.问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高.问题的名称来源于如何选择最合适的物品放置于给定背包中. 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放. 用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值.则其状态转移方程便是: f[i][v]=max{ f[i-1][v], f

  • Java编程删除链表中重复的节点问题解决思路及源码分享

    一. 题目 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 二. 例子 输入链表:1->2->3->3->4->4->5 处理后为:1->2->5 三. 思路 个人感觉这题关键是注意指针的指向,可以定义一个first对象(值为-1,主要用于返回操作后的链表),first.next指向head,定义一个last同样指向first(主要用于操作记录要删除节点的前一个节点),定义一个p指向head,指向当前节点.

  • java实现单链表、双向链表

    本文实例为大家分享了java实现单链表.双向链表的相关代码,供大家参考,具体内容如下 java实现单链表: package code; class Node { Node next; int data; public Node(int data) { this.data=data; } } class LinkList { Node first; //头部 public LinkList() { this.first=null; } public void addNode(Node no) {

  • java双向循环链表的实现代码

    例1: 复制代码 代码如下: package com.xlst.util; import java.util.HashMap;import java.util.Map;import java.util.UUID; /*** 双向循环链表* 完成时间:2012.9.28* 版本1.0* @author xlst**/public class BothwayLoopLinked {/*** 存放链表长度的 map* * 如果简单使用 static int 型的 size 基本类型变量,则只能维护一个

  • Java采用循环链表结构求解约瑟夫问题

    本文实例讲述了Java采用循环链表结构求解约瑟夫问题的方法.分享给大家供大家参考.具体分析如下: 这是第一次java考试的试题,对于没看过链表的同学来说就不会做,现在回头看看,还真不难. 约瑟夫问题: 有n个人,其编号分别为1,2,3,-,n.这n个人按顺序排成一个圈.现在给定s和d,从第s个人开始从1依次报数,数到d的人出列,然后又从下一个人开始又从1开始依次报数,数到d的人又出列,如此循环,直到最后所有人出列为止.要求定义一个节点类,采用循环链表结构求解约瑟夫问题. 以下java版的答案:

  • Java数据结构及算法实例:汉诺塔问题 Hanoi

    /** * 汉诺塔大学的时候就学过,但是根本没搞明白,唯一知道的就是要用递归的方法来求解. * 问题描述: * 有三根杆子A,B,C.A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小. * 要求按下列规则将所有圆盘移至C杆: * 1.每次只能移动一个圆盘: * 2.大盘不能叠在小盘上面. * 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆, * 但都必须尊循上述两条规则. * 问:如何移?最少要移动多少次? * 解决方法: * 假设只有2个盘子,柱子分别是A, B, C柱

  • java数据结构之实现双向链表的示例

    复制代码 代码如下: /** * 双向链表的实现 * @author Skip * @version 1.0 */public class DoubleNodeList<T> { //节点类 private static class Node<T>{  Node<T> perv;  //前节点  Node<T> next;  //后节点  T data;    //数据 public Node(T t){   this.data = t;  } } priv

  • Java递归算法经典实例(经典兔子问题)

    题目:古典问题:3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析:首先我们要明白题目的意思指的是每个月的兔子总对数:假设将兔子分为小中大三种,兔子从出生后三个月后每个月就会生出一对兔子, 那么我们假定第一个月的兔子为小兔子,第二个月为中兔子,第三个月之后就为大兔子,那么第一个月分别有1.0.0,第二个月分别为0.1.0, 第三个月分别为1.0.1,第四个月分别为,1.1.1,第五个月分别为2.1.2,第六个月分别为3.2.3,第

  • Java基于循环递归回溯实现八皇后问题算法示例

    本文实例讲述了Java基于循环递归回溯实现八皇后问题.分享给大家供大家参考,具体如下: 运行效果图如下: 棋盘接口 /** * 棋盘接口 * @author Administrator * */ public interface Piece { abstract boolean isRow(int line); abstract boolean isCol(int line,int col); } 棋盘类: /** * 棋盘 * @author Administrator * */ public

  • java中使用双向链表实现贪吃蛇程序源码分享

    使用双向链表实现贪吃蛇程序 1.链表节点定义: package snake; public class SnakeNode { private int x; private int y; private SnakeNode next; private SnakeNode ahead; public SnakeNode() { } public SnakeNode(int x, int y) { super(); this.x = x; this.y = y; } public int getX(

随机推荐