(java實現)單向循環鏈表

什麼是單向循環鏈表

單向循環鏈表基本與單向鏈表相同,惟一的區別就是單向循環鏈表的尾節點指向的不是null,而是頭節點(注意:不是頭指針).
所以,單向循環鏈表的任何節點的下一部分都不存在NULL值。html

因爲單向循環鏈表的特性,它在處理一些環狀數據的時候十分有效.大名鼎鼎的約瑟夫環問題就能夠用循環單向鏈表求解,下面咱們會有進一步的介紹。java

因爲單向循環鏈表和單向鏈表的差異真的不大,增添改查原理都相同。所以在這裏咱們不詳細講解,只提供源碼。(若是你仍是不理解的話,這裏有單向鏈表的傳送門)node


源碼實現(Java)

public class Node<Anytype> {
    public Anytype data;
    public Node<Anytype> next;
    public Node(Anytype data,Node<Anytype> next){
        this.data=data;
        this.next=next;
    }
}

------------------------------------

public class SingleLink<AnyType> {


    //首元節點
    public Node<AnyType> first;

    //頭指針
    public Node<AnyType> head;

    //鏈表長度
    int thesize;

    //初始化鏈表
    public boolean initlist(){
        thesize=0;
        first=new Node<>(null,null);
        head=new Node<>(null,first);
        first.next=head;
        return true;
    }

    //判斷鏈表是否爲空
    public boolean isEmpty(){
        return thesize==0;
    }

    //獲取節點
    public Node<AnyType> getNode(int i){
        Node<AnyType> renode=head;
        for(int j=-2;j<i;j++){
            renode=renode.next;
        }
        return renode;
    }

    //在末尾添加元素
    public void add(AnyType a){
        Node<AnyType> renode=new Node<>(a,null);
        getNode(thesize-1).next=renode;
        renode.next=first.next;
        thesize++;
    }

    //刪除i位置節點,並返回刪掉的數據
    public AnyType remove(int i){
        if(i==thesize-1){
            AnyType a=getNode(thesize-1).data;
            getNode(thesize-2).next=first.next;
            return a;
        }
        Node<AnyType> prev=getNode(i-1);
        AnyType a=prev.next.data;
        prev.next=prev.next.next;
        thesize--;
        return  a;
    }

    public void remove2(Node<AnyType> n){

    }

    //在i位置插入新節點
    public void insert(int i,AnyType a){
        Node<AnyType> prev=getNode(i-1);
        Node<AnyType> renode=new Node<>(a,prev.next);
        prev.next=renode;
        thesize++;
    }

    //獲取i位置節點的數據
    public AnyType get(int i){
        return getNode(i).data;
    }

    //爲i位置元素從新賦值
    public void set(int i,AnyType a){
        getNode(i).data=a;
    }

    //返回鏈表節點個數
    public int length(){
        return thesize;
    }

    //清空鏈表
    public void clear(){
        initlist();
    }

    //打印鏈表
    public void print(){
        for(int i=0;i<thesize;i++){
            System.out.println(getNode(i).data);
        }
    }

}

單向循環鏈表的應用----約瑟夫環問題

問題來歷

聽說著名猶太曆史學家 Josephus有過如下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,因而決定了一個自殺方式,41我的排成一個圓圈,由第1我的開始報數,每報數到第3人該人就必須自殺,而後再由下一個從新報數,直到全部人都自殺身亡爲止。然而Josephus 和他的朋友並不想聽從。首先從一我的開始,越過k-2我的(由於第一我的已經被越過),並殺掉第k我的。接着,再越過k-1我的,並殺掉第k我的。這個過程沿着圓圈一直進行,直到最終只剩下一我的留下,這我的就能夠繼續活着。問題是,給定了和,一開始要站在什麼地方纔能避免被處決?Josephus要他的朋友先僞裝聽從,他將朋友與本身安排在第16個與第31個位置,因而逃過了這場死亡遊戲。this

思路分析

首先全部的人是圍城一圈的,並且須要循環不少圈纔可以將全部人依次排除,而這很是適合剛剛完成的單向循環鏈表才解決,尾節點的下一個節點又從新拿到的頭節點,剛剛和問題中的狀況契合。
首先咱們只要拿到鏈表的頭節點,而後依次經過頭節點的next指針日後拿到下一個節點,找到第3個移除鏈表,而後依次循環直到鏈表爲空,移除的順序就是咱們須要的死亡順序。spa

import java.util.Scanner;

public class JosephRing {
    public static void main(String[] args){
        int sum=0;
        int space=0;
        String s="";
        System.out.println("輸入環數和間隔");
        Scanner sc=new Scanner(System.in);
        sum=sc.nextInt();
        space=sc.nextInt();
        SingleLink<Integer> sl=new SingleLink<>();
        sl.initlist();
        //編號add進鏈表
        for(int i=0;i<sum;i++){
            sl.add(i+1);
        }
        Node<Integer> n=sl.first;
        while(n.next!=n){
            for(int i=1;i<space;i++){
                n=n.next;
            }
            int a=n.next.data;
            n.next=n.next.next;
            s=s+a+",";
        }
        System.out.println(s);
    }
}
/*
    輸入:41
          3
    輸出:3,6,9,12,15,18,21,24,27,30,33,36,39,1,5,10,14,19,23,28,32,37,41,7,13,20,26,34,40,8,17,29,38,11,25,2,22,4,35,16,
 */
相關文章
相關標籤/搜索