环形链表

定义:环形链表是将 单向链表的首尾相连,可以通过头节点往下再次寻找到头节点。
链表主要作用就是方便删除和增加节点使用的,在查找方面有一定的缺陷。

环形链表主要用于解决约瑟夫问题
约瑟夫问题:
设编号为 1,2,3,…n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出列编号的序列。

当然这个问题用数组也能够实现,这里仅考虑使用环形链表,打开算法思路和了解环形链表

export default class CricleLinkedList<T>{

    private first: Node<T>;

    
    public add(data: T): void {
        if (!this.first) {
            this.first = new Node(data);
            this.first.next = this.first;  // 环形链表会将首尾相连
        } else {
            let temp = this.first;
            while (temp.next !== this.first) { // 循环找到最后一个节点赋值给temp
                temp = temp.next;
            }
            temp.next = new Node<T>(data); // 将最后一个节点的next属性指向 添加的数据
            temp.next.next = this.first;  // 将添加的节点的next属性指向第一个节点,完成首尾相连的环形
        }
    }

    public remove(node: Node<T>): boolean {
        let temp = this.first;
        let result = false;
        while (temp) {
            if (temp == node) {
                temp.next = temp.next.next;
                result = true;
                this.showList();
                break;
            }
            temp = temp.next;
        }
        return result;
    }
    
    public getNodeAndRemoveNode(countNum: number, startNo:number): T[] {
        let arr = [];
        let temp = this.first;
        let helper = this.first;
        while(true){
            if(helper.next == this.first){
                break;
            }
            helper = helper.next;
        }

        for (let index = 0; index < startNo - 1; index++) { // 第一次同时向后移动找到对应的开始位置 
            temp = temp.next;
            helper = helper.next;
        }
    
        while(true){
            if(temp == helper){ // 如果helper等于了temp 说明当前链表中只存在了一个数据
                temp.next = helper;
                arr.push(temp.data);
                break;
            }
            for (let index = 0; index < countNum - 1; index++) { // 通过循环 countNum-1 次完成移动计数
                temp = temp.next;
                helper = helper.next;
            }
            console.log("小孩出圈: " , temp.data);
            arr.push(temp.data);

            temp = temp.next;
            helper.next = temp; // 将helper的下一个节点指向第一个节点,完成首尾连接,方便下一个循环使用
        }

        console.log("最后留存的小孩: " , temp.data);
        return arr;
    }

    public showList() : void{
        let temp = this.first;
        console.log("--------------------------- 打印链表")
        while(true){
            console.log(" node :" ,temp.data);
            if(temp.next == this.first){
                break;
            }
            temp = temp.next;
        }
        
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值