双向链表和单向环形链表

一.双向链表

单向链表,查找的方向只能是一个方向,而双向链 表可以向前或者向后查找

单向链表不能自我删除,需要靠辅助节点 ,而双向 链表,则可以自我删除,单链表删除时节点,总是找到temp,temp是待删除节点的前一 个节点

双向链表自我删除

  • temp.pre.next = temp.next
  • temp.next.pre = temp.pre

1.双向链表添加节点

public void add(HeroNode1 heroNode) {
        //头节点不能动
        HeroNode1 temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = heroNode;
        heroNode.pre = temp;
    }

        需要让新增节点的pre指向前一个节点

2.双向链表遍历

 public  void list() {
        //头节点不能动
        HeroNode1 temp = head.next;

        if (head.next == null) {
            System.out.println("该链表为空");
            return;
        }
        while (true) {
            if (temp == null) {
                break;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }

        与单向链表基本一致

3.双向链表修改

public void update(HeroNode1 heroNode) {

        if (head.next == null) {
            return;
        }

        HeroNode1 temp = head.next;
        boolean flag = false;

        while (true) {

            if (temp == null) break;

            if (temp.no == heroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }

        if (flag) {
            temp.nickName = heroNode.nickName;
            temp.name = heroNode.name;
        } else System.out.printf("未找到 %d \n", heroNode.no);
    }

        与单链表基本一致

4.双向链表删除操作

 public void delete(int no) {
        HeroNode1 temp = head.next;
        boolean flag = false;

        while (true) {
            if (temp == null) break;

            if (temp.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }

        if (flag) {
            temp.pre.next = temp.next;

            if (temp.next != null) temp.next.pre = temp.pre;

        } else System.out.printf("此编号 %d 不存在", no);

    }

二.单向环形链表

        应用场景:Josephu(约瑟夫、约瑟夫环) 问题 Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数 到 m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由 此产生一个出队编号的序列。

        算法分析:n=5 有五个人 k=1 从第一个人开始报数 m=2 每次数三下

        出圈顺序为->24153

        1.将first指向圈首的节点上

        2.创建一个辅助变量helper,使其指向圈的最后一个节点

        3.报数前让first和helper移动k-1次

 for (int i = 0; i < startNo - 1; i++) {
            helper = helper.getNext();
            first = first.getNext();
        }

        4.当此节点开始报数first和helper向后移动m-1个节点

while (true){
            //圈中只有一个节点
            if (helper==first) break;
            for (int i = 0; i < contNum-1; i++) {
                helper = helper.getNext();
                first = first.getNext();
            }
            System.out.printf("编号: %d 出圈\n",first.getNo());

            first=first.getNext();
            helper.setNext(first);
        }
        System.out.printf("编号: %d 留在圈\n ",helper.getNo());

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值