java数据结构4:链表

第4章:链表

1、单向链表

image-20201106212040897

image-20201106212046711

节点类

public class HeroNode {
    public int no;
    public String name;
    public String nickname;		//别名
    public HeroNode next;		

    public HeroNode(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}
添加节点到链表尾部

image-20201106212156969

按顺序添加节点到链表

image-20201106212348814

删除节点

image-20201106212940348

//链表操作
public class SingleLinkedList {
    private HeroNode head = new HeroNode(0, "", "");	//头节点,不存放数据

    //在尾部添加节点
    public void add(HeroNode heroNode) {
        HeroNode temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            //找到最后一个节点
            temp = temp.next;
        }
        temp.next = heroNode;
    }

    //按顺序添加节点
    public void addByOrder(HeroNode heroNode) {
        HeroNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no > heroNode.no) {
                break;
            } else if (temp.next.no == heroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            System.out.println("编号" + heroNode.no + "已存在");
        } else {
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    //修改节点信息
    public void update(HeroNode heroNode) {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no == heroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next.name = heroNode.name;
            temp.next.nickname = heroNode.nickname;

        } else {
            System.out.println("没有找到呢");
        }
    }

    //删除节点
    public void del(int no) {
        HeroNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next = temp.next.next;
        } else {
            System.out.println("不存在");
        }
    }

    //遍历
    public void list() {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode temp=head;
        while (true){
            if (temp.next==null){
                break;
            }
            System.out.println(temp.next);
            temp=temp.next;
        }
    }
}

2、单链表面试题

1. 求单链表中有效节点的个数
public int getLength(HeroNode heroNode){
    if (head.next==null){
        return 0;
    }
    int length=0;
    HeroNode temp=head;
    while (temp.next!=null){
        length++;
        temp=temp.next;
    }
    return length;
}
2. 查找单链表中的倒数第k个结点【新浪面试题】
  1. 方法传入参数head节点,倒数第index个节点
  2. getLength()获取链表总长度size
  3. 从头开始遍历size-index个
public HeroNode findLastIndexNode(HeroNode head,int index){
    if (head.next==null){
        return null;
    }
    int size=getLength(head);
    
    if (index<=0||index>size){
        System.out.println("输入错误");
    }

    HeroNode temp=head.next;
    //遍历size-index个
    for (int i = 0; i < size-index; i++) {
        temp=temp.next;
    }
    return temp;
}

当size=5,index=2(倒数第二个)时,size-index=3

3. 单链表的反转【腾讯面试题】
  1. 新建一个头节点,即新链表
  2. 遍历旧链表,每遍历到一个就放在新链表的最前面,紧跟新链表头节点后面
  3. 最后旧链表头节点指向新链表头节点.next

image-20201106213442769

image-20201106213841773

public void reverseList(HeroNode head){
    //没有节点或只有一个节点
    if (head.next==null||head.next.next==null){
        return;
    }
    HeroNode temp=head.next;
    HeroNode tempNext=null;
    HeroNode reverseHead=new HeroNode(0,"","");
    
    while (temp!=null){
        tempNext=temp.next; //保存temp的下一个节点
        temp.next=reverseHead.next; //放到最前边
        
        reverseHead.next=temp;  
        temp=tempNext;  //后移
    }
    head.next= reverseHead.next;
}
4. 从尾到头打印单链表 【百度,要求方式1:反向遍历 。 方式2:Stack栈】

image-20201106213935573

使用栈

public void reversePrint(HeroNode head){
    if (head.next==null){
        return;
    }
    Stack<HeroNode> stack = new Stack<>();
    HeroNode temp=head.next;
    
    while (temp!=null){
        stack.push(temp);
        temp=temp.next;
    }
    while (stack.size()>0){
        System.out.println(stack.pop());
    }
}
5. 合并两个有序的单链表,合并之后的链表依然有序

image-20201106214047773

public HeroNode merge(HeroNode head1,HeroNode head2){
    HeroNode heroNode=new HeroNode(0,"","");
    HeroNode temp=heroNode;

    while (head1!=null&&head2!=null) {
        if (head1.no > head2.no) {
            heroNode.next = head2;		//添加小的
            heroNode = head2;			//后移
            head2 = head2.next;			//head2也后移
        } else {
            heroNode.next = head1;
            heroNode = head1;
            head1 = head1.next;
        }
    }

        if (head1!=null){
            heroNode.next=head1;
        }
        if (head2!=null){
            heroNode.next=head2;
        }
        return temp.next;
}

3、双向链表

  1. 可以双向查找
  2. 可以自主删除节点

image-20201106214534164

双向链表

  1. 遍历:和单链表一样,可以向前,也可以向后

  2. 添加:默认添加到最后

    1. 1 找到最后的节点temp

    2. 2 temp.next=newHeroNode

    3. 3 newHeroNode.pre=temp

  3. 修改:和单链表一样

  4. 删除:找到要删除节点temp

    1. 1 temp.pre.next=temp.next

    2. 2 temp.next.pre=temp.pre

删除

image-20201106214627163

//节点类
public class HeroNode2 {
    public int no;
    public String name;
    public String nickname;
    public HeroNode2 next;
    public HeroNode2 pre;


    public HeroNode2(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}
//双向链表
public class DoubleLinkedList {
    private HeroNode2 head = new HeroNode2(0, "", "");

    public HeroNode2 getHead() {
        return head;
    }

    //添加
    public void add(HeroNode2 heroNode) {
        HeroNode2 temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = heroNode;
        heroNode.pre=temp;
    }

    //按顺序添加
    public void addByOrder(HeroNode2 heroNode) {
        HeroNode2 temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no > heroNode.no) {
                break;
            } else if (temp.next.no == heroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            System.out.println("编号" + heroNode.no + "已存在");
        } else {
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    //修改
    public void update(HeroNode2 heroNode) {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode2 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.name = heroNode.name;
            temp.nickname = heroNode.nickname;

        } else {
            System.out.println("没找到呢");
        }
    }

    //删除
    public void del(int no) {

        if (head.next==null){
            System.out.println("空");
            return;
        }

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

        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next = temp.next.next;
            if (temp.next!=null){   //不是最后一个节点时执行
                temp.next.pre=temp.pre;

            }
        } else {
            System.out.println(no+"不存在");
        }
    }

    //遍历
    public void list() {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode2 temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            System.out.println(temp.next);
            temp = temp.next;
        }
    }


}

4、单向环形链表

约瑟夫问题:数到的那个人出队列

image-20201106220727142

创建环形链表思路

image-20201106220916899

添加小孩

image-20201106221051938

出队列思路

image-20201106221011970

出队列

image-20201106221104999

节点类

public class Boy {
    private int no;
    private Boy next;

    public Boy(int no){
        this.no=no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Boy getNext() {
        return next;
    }

    public void setNext(Boy next) {
        this.next = next;
    }
}
public class CircleSingleLinkedList {
    private Boy first=null;

    //添加nums:一共多少个boy
    public void addBoy(int nums){

        if (nums<1){
            System.out.println("小孩个数不能小于1");
            return;
        }
        Boy temp=null;
        for (int i = 1; i <= nums; i++) {
            Boy boy=new Boy(i);

            if (i==1){
                first=boy;
                first.setNext(first);   //形成环
                temp=first;
            }else {
                temp.setNext(boy);
                boy.setNext(first);
                temp=boy;
            }
        }
    }
    
	 //遍历
    public void showBoy(){ 
        if (first==null){
            System.out.println("空");
            return;
        }
        Boy temp=first;
        while (true){
            System.out.println("小孩:"+temp.getNo());
            if (temp.getNext()==first){
                break;
            }
            temp=temp.getNext();
        }
    }

    //出圈(开始位置,数几下,多少个小孩)
    public void countBoy(int startNo,int countNum,int nums){
        if (first==null||startNo<1||startNo>nums){
            System.out.println("参数错误");
            return;
        }
        Boy temp=first;
        while (true){   //让temp指向最后一个节点,即first的后面
            if (temp.getNext()==first){
                break;
            }
            temp=temp.getNext();
        }

        for (int i = 0; i < startNo-1; i++) {   //定位到开始计数的位置
            first=first.getNext();
            temp=temp.getNext();

        }

        while (true){
            if (temp==first){   //只一个
                break;
            }

            for (int i = 0; i < countNum-1; i++) {
                first=first.getNext();
                temp=temp.getNext();
            }
            System.out.println("出圈小孩:"+first.getNo());
            first=first.getNext();     //当前first为要出圈的孩子,移动后直接让temp的next指向它
            temp.setNext(first);
        }
        System.out.println(first.getNo()+"为最后一个");
    }
}

        for (int i = 0; i < startNo-1; i++) {   //定位到开始计数的位置
            first=first.getNext();
            temp=temp.getNext();

        }

        while (true){
            if (temp==first){   //只一个
                break;
            }

            for (int i = 0; i < countNum-1; i++) {
                first=first.getNext();
                temp=temp.getNext();
            }
            System.out.println("出圈小孩:"+first.getNo());
            first=first.getNext();     //当前first为要出圈的孩子,移动后直接让temp的next指向它
            temp.setNext(first);
        }
        System.out.println(first.getNo()+"为最后一个");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值