数据结构(三):单向循环链表的实现及约瑟夫问题

单向循环链表并不复杂,主要要和约瑟夫问题结合起来,才能更好地感受到单向循环链表的好处。

约瑟夫问题

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

java实现单向循环列表(不带头结点)
package com.study;

public class TestCircleLinkList {
    public static void main(String[] args) {
        CircleLinkList circleLinkList = new CircleLinkList();
        circleLinkList.create(4);
        circleLinkList.show();
        System.out.println("===========");
        circleLinkList.deleteOrder(2,2);
    }
}
//结点
class Node {
    int data;
    Node next = null;//指向下一结点
    public Node(int data){
        this.data = data;
    }
}
//链表
class CircleLinkList{
    Node first = null;//指向首结点
    Node curNode = null;//指向尾结点

    /*
    * 创建指定结点个数的循环链表
    * */
    public void create(int n){
        if(n<1){
            System.out.println("请输入大于0的整数");
            return;
        }
        for(int i=1;i<=n;i++){
            Node newNode = new Node(i);
            if(i==1){
                first = newNode;
                curNode = newNode;
                newNode.next = first;
            }else{
                curNode.next = newNode;
                curNode = newNode;
                curNode.next = first;
            }
        }
    }

    /*
    * @param start:从第几个结点开始
    * @param m:计算几次
    * */
    public void deleteOrder(int start ,int m){
        if(first==null || start < 1 || m < 0){
            System.out.println("输入有误");
            return;
        }
        for(int i=1;i<start;i++){//将first和curNode指针指向对应位置
            if(start==1){
                break;
            }
            first = first.next;
            curNode = curNode.next;
        }
        Node temp = curNode;
        int count = 1;
        while(temp!=first){
            if(count == m){
                System.out.println(first.data);
                first = first.next;
                temp.next = first;
                count = 1;
            }else{
                first = first.next;
                temp = temp.next;
                count++;
            }
        }
        System.out.println(first.data);
    }

    /*
    * 遍历循环链表
    * */
    public void show(){
        if(first == null){
            System.out.println("当前链表为空");
            return;
        }
        Node temp = first;
        while(temp.next!=first){
            System.out.println(temp.data);
            temp = temp.next;
        }
        System.out.println(temp.data);
    }
}

在这里插入图片描述
对于单项循环链表,我们要注意一下几点
1.要有两个指针辅助,first和curNode指针。前者指向第一个结点,后者指向最后一个结点。循环链表虽然首尾相连,但是我们人为给它设定了第一个结点和最后一个结点。
2.对于约瑟夫问题,我们需要再借助一个temp指针,开始时指向最后一个结点(curNode指向的结点);当开始报数报到M的时候,让first和temp同时往前移动m-1次(因为first指向的的人也会报一次数);然后让first = first.next, temp.next=first,这样就达到了删除的目的。然后循环往复,直至结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值