1、链表介绍:

 

 2、单链表:

我们以梁山英雄排行榜举例说明:

 

 

 

 

 

 

 代码演示:

package com.linkedlist;

public class LinkedListDemo {
    public static void main(String[] args) {
        HeroNode node1 = new HeroNode(1,"宋江","及时雨");
        HeroNode node3 = new HeroNode(3,"卢俊义","玉麒麟");
        HeroNode node5 = new HeroNode(5,"林冲","豹子头");
        HeroNode node4 = new HeroNode(4,"吴用","智多星");
        HeroNode node2 = new HeroNode(2,"晁盖","天王");

        LinkedList linkedList = new LinkedList();

        linkedList.addByOrder(node1);
        linkedList.addByOrder(node3);
        linkedList.addByOrder(node5);
        linkedList.addByOrder(node4);
        linkedList.addByOrder(node2);
        linkedList.showLinkedList();
        System.out.printf("节点个数为%d个",linkedList.getLength());

        System.out.println();
        System.out.println("删除编号为3的卢俊义后:");
        linkedList.deleteByNo(3);
        linkedList.showLinkedList();

        System.out.println();
        System.out.println("修改编号为5林冲后:");
        HeroNode node6 = new HeroNode(5,"林冲的仇人高俅","靠足球上位的高太尉");
        linkedList.update(node6);
        linkedList.showLinkedList();

    }
}

//定义HeroNode类,表示每一个节点
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 + '\'' +
                '}';
    }
}

//定义LinkedList类,表示链表,管理HereNode类
class LinkedList {
    //定义一个空的头节点,不存放数据
    private HeroNode head = new HeroNode(0, "", "");

    //获取该单链表的节点个数
    public int getLength(){
        if(head.next == null){
            return 0;
        }
        int length = 0;
        HeroNode temp = head.next;
        while(true){
            if(temp == null){
                break;
            }
            length ++;
            temp = temp.next;
        }
        return length;
    }

    //添加节点到链表,不考虑顺序,直接加到当前链表的最后
    public void add(HeroNode node) {
        if (node == null) {
            return;
        }
        //定义一个辅助节点temp,帮助找到链表的最后
        HeroNode temp = head;
        while (true) {
            //找到链表的最后了
            if (temp.next == null) {
                break;
            }
            //没有找到,后移temp
            temp = temp.next;
        }
        temp.next = node;
    }

    //添加节点到链表,按照编号no插入
    public void addByOrder(HeroNode node) {
        if (node == null) {
            return;
        }
        //定义一个辅助节点temp,帮助找到链表的最后
        HeroNode temp = head;
        boolean flag = false;
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no > node.no) {//从小到大的顺序插入
                break;//找到位置了,结束循环
            } else if (temp.next.no == node.no) {
                flag = true;//已经存在有这个编号的heroNode了
                break;
            }
            temp = temp.next;
        }
        if (flag == true) {
            System.out.printf("已经存在编号为%d的了,不能插入", node.no);
        } else {
            node.next = temp.next;//将插入的节点与后一个节点连接
            temp.next = node;//将插入的节点与前一个节点连接
        }
    }

    //根据HeroNode的no来修改 节点信息
    public void update(HeroNode node) {
        if (node == null) {
            return;
        }
        //定义一个辅助节点temp,帮助找到链表的最后
        HeroNode temp = head.next;
        boolean flag = false;
        if (temp == null) {
            System.out.println("链表为空");
            return;
        }
        while (true) {
            if (temp == null) {
                break;
            }
            if (temp.no == node.no) {//找到要修改的节点
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag == true) {
            temp.name = node.name;
            temp.nickName = node.nickName;
        } else {
            System.out.printf("没有编号为%d的节点,不能修改", node.no);
        }
    }

    //根据编号no删除节点
    public void deleteByNo(int no) {
        //定义一个辅助节点temp,帮助找到链表的最后
        HeroNode temp = head;
        boolean flag = false;
        if (temp.next == null) {
            System.out.println("链表为空");
            return;
        }
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.no == no) {//找到要删除的节点
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag == true) {
            temp.next = temp.next.next;//把要删除的节点的后一个节点指向被删除的节点的前一个节点,没有了指针指向,相当于删了
        } else {
            System.out.printf("没有编号为%d的节点,不能删除", no);
        }
    }

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

结果输出:

HeroNode{no=1, name='宋江', nickName='及时雨'}
HeroNode{no=2, name='晁盖', nickName='天王'}
HeroNode{no=3, name='卢俊义', nickName='玉麒麟'}
HeroNode{no=4, name='吴用', nickName='智多星'}
HeroNode{no=5, name='林冲', nickName='豹子头'}
节点个数为5个
删除编号为3的卢俊义后:
HeroNode{no=1, name='宋江', nickName='及时雨'}
HeroNode{no=2, name='晁盖', nickName='天王'}
HeroNode{no=4, name='吴用', nickName='智多星'}
HeroNode{no=5, name='林冲', nickName='豹子头'}

修改编号为5林冲后:
HeroNode{no=1, name='宋江', nickName='及时雨'}
HeroNode{no=2, name='晁盖', nickName='天王'}
HeroNode{no=4, name='吴用', nickName='智多星'}
HeroNode{no=5, name='林冲的仇人高俅', nickName='靠足球上位的高太尉'}

 

 关于辅助指针的问题:

A、如果是增加,删除操作,牵涉到指针next的改变的,初始temp = head,使得操作的是temp的下一个节点

B、如果是遍历,修改操作,不涉及到指针next的改变的,初始temp = head.next,直接把辅助指针定位到要操作的节点上

 

3、单链表相关的面试题

  3.1查找单链表中倒数第k个节点

class LinkedList {
    //定义一个空的头节点,不存放数据
    private HeroNode head = new HeroNode(0, "", "");

    //查找单链表的倒数第k个节点
    public HeroNode findNode(int k){
        int length = getLength();//总的节点个数
        int index = length-k;//要找的第几个节点数
        HeroNode temp = head.next;
        for(int i=0;i<index;i++){
            temp = temp.next;
        }
        return temp;
    }
}

  3.2单链表的反转

//单链表反转
    public void reverseList(){
        if(head.next == null && head.next.next == null){
            return;
        }
        HeroNode temp = head.next;//辅助指针,帮助遍历原来的链表
        HeroNode next = null;//指向当前节点的下一个节点
        HeroNode reverseHead = new HeroNode(0,"","");
        while(temp != null){
            next = temp.next;
            temp.next = reverseHead.next;
            reverseHead.next = temp;
            temp = next;
        }
        head.next = reverseHead.next;
    }

  3.3单链表的逆序打印

//单链表的逆序打印,根据栈的特点,使用栈
    public void reversePrint(){
        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().toString());
        }
    }

 

posted on 2020-08-15 15:02  二十二画生的执著  阅读(59)  评论(0编辑  收藏  举报