关于链表的一些操作

阅读 203

2022-03-11

        还差一个功能没写,好像是哪个的面试题,晚上重新给补充上。其余的东西注释写的方法功能,以及分析都写在代码里面了。

package linkedListDemo;

/**
 * 在本类中,定义一个英雄节点。使用链表存储
 * 使用链表完成:
 * 1.添加新节点进链表;
 * 2.添加新节点进链表并且需要按照编号排序添加进去;
 * 3.修改链表中英雄节点的数据(根据编号)
 * 4.删除指定编号的英雄节点
 * 5.查询指定节点的英雄数据
 */

public class HeroNodeDemo {
    public static void main(String[] args) {
        SingleLinkedList hero = new SingleLinkedList();
        HeroNode hero1 = new HeroNode(1,"宋江","及时雨");
        HeroNode hero2 = new HeroNode(2,"卢俊义","玉麒麟");
        HeroNode hero3 = new HeroNode(3,"吴用","智多星");
        HeroNode hero4 = new HeroNode(4,"林冲","豹子头");
        hero.addByOrder(hero1);
        hero.addByOrder(hero4);
        hero.addByOrder(hero2);
        hero.addByOrder(hero3);
        hero.list();
        System.out.println("===============");

        hero.del(2);
        hero.list();
        System.out.println("===============");
        HeroNode hero_4 = new HeroNode(4,"鲁智深","花和尚");
        hero.update(hero_4);
        hero.list();
        System.out.println("===============");

        hero.find(4);
        System.out.println("===============");
        int length = hero.getLength();
        System.out.println("链表的长度为:"+length);
        System.out.println("===============");
        hero.reverseLinkedList();
        hero.list();
        System.out.println("===============");
        HeroNode lastK = hero.getLastK(2);
        System.out.println(lastK);

    }
}


//定义一个单链表类,里面需要写很多关于链表的操作方法
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;
    }
    //根据编号顺序添加元素进入链表
    /*
        分析:
            1.先判断链表为空,就直接加入
            2.链表不为空时,用一个指针指向第一个节点,如果出现temp.no == hero.no,就输出英雄重复;
            3.判断temp.next.no < hero.no && temp.no < hero.no,这种就可以添加进去
            4.如果到了最后temp.no < hero.no,就直接添加到末尾
     */
    public void addByOrder(HeroNode heroNode){
        HeroNode temp = head;
        boolean flag = false;
        while(true){
            if(temp.next == null){
                //已经到了链表的末尾
                break;
            }
            if(temp.next.no > heroNode.no){
                //如果是当前节点的下一个节点的no大于当前插入节点,那么temp就到了位置了
                break;
            }else if(temp.next.no == heroNode.no){
                //如果是当前节点的下一个节点的no等于当前插入节点,那么就打印错误信息
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag){
            //no重复,插入不了
            System.out.println("已有该编号,插入失败...");
            return;
        }else {
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    //删除指定编号的节点对象
    /*
        分析:
            1.由于是单链表,我要是删除指定位置的结点的话,我就需要temp.next.no = no,删除
     */
    public void del(int no){
        if(head.next == null){
            System.out.println("空链表,不能删除...");
            return;
        }
        HeroNode cur = head;//直接指向头节点,防止删除的元素是第一个
        boolean flag = false;//防止找不到元素,打印错误信息
        while(true){
            if(cur.next.no == no){
                //找到元素
                flag = true;
                break;
            }
            cur = cur.next;
        }
        if(flag){
            cur.next = cur.next.next;
        }else{
            System.out.println("没找到指定编号的节点...");
            return;
        }
    }
    //修改指定编号的数值

    /*
        分析:
            1.遍历链表,找到指定no的节点,如果没找到,那就是返回错误信息
     */
    public void update(HeroNode heroNode){
        if(head.next == null){
            System.out.println("空链表,无法修改数据...");
            return;
        }
        HeroNode cur = head;
        boolean flag = false;
        while(true){
            if(cur.next == null){
                break;
            }
            if(cur.next.no == heroNode.no){
                //找到了指定编号的对象,可以修改数据,肯定是修改当前的节点数据
                flag = true;
                cur = cur.next;
                break;
            }
            cur = cur.next;
        }
        if(flag){
            //找到编号,修改数据
            cur.name = heroNode.name;
            cur.nickName = heroNode.nickName;
        }else{
            System.out.println("没有指定编号的数据,修改失败...");
            return;
        }
    }

    //查询指定编号的节点对象的数据
    /*
        分析:
            1.只是返回对象的话,打印就好了,而且我重写了toString;
            2.只要找到指定no的对象就好了,很简单
     */
    public void find(int no){
        if(head.next == null){
            System.out.println("链表为空,无法查询...");
            return;
        }
        HeroNode temp = head.next;
        boolean flag = false;
        while(true){

            if(temp.no == no){
                flag = true;
                break;
            }
            if(temp.next == null){
                //当前是链表的组后一个数据,还没找到,就打印错误信息
                break;
            }
            temp = temp.next;
        }
        if(flag){
            //输出当前temp
            System.out.println(temp);
        }else{
            System.out.println("未找到指定编号的节点...");
            return;
        }
    }

    //返回链表的长度
    /*
        分析:
            1.听说这个是新浪的面试题
            2.如果是查询链表长度的话,就是一直遍历到末尾,然后搞一个计数器在那累加就i好
     */
    public int getLength(){
        if(head.next == null){
            return 0;
        }
        HeroNode temp = head;
        int count = 0;
        while(true){
            if(temp.next == null){
                //如果是当前元素为链表最后一个结点的话,那么就可以返回count
                break;
            }
            temp = temp.next;
            count ++;
        }
        return count;
    }
    //得到链表倒数第k个结点的数据
    /*
        分析:
            1.遍历数组,其实就是获取第getLength - index位置的数据
            2.特殊情况:
                index > getLength() || index < 0都是要打印错误信息的
     */
    public HeroNode getLastK(int index){
        int size = getLength();
        if(head.next == null){
            System.out.println("链表为空,获取不到数据...");
            return null;
        }
        if(index < 0 || index > size){
            System.out.println("索引是错误的,无法查找数据...");
            return null;
        }

        HeroNode temp = head.next;
        int count = 0;
        int fin = size - index;// 3 - 1 = 2;宋江
        while(true){
            if(count < fin){
               count ++;
               temp = temp.next;
            }else{
                break;
            }
        }
        return temp;
    }

    //反转链表      4 -> 3 -> 1
    /*
        分析:
            1.如果要是反转链表的话,就是先创建一个新的头节点reverseNode;
            2.遍历原来的链表,除开头节点外,每遍历到一个元素,就把他给取下来,街道reverseNode的后边;
            3.在上面那个步骤中,需要多创建一个节点用于保存被取下元素的下一个结点的地址;
            4.遍历完成之后,将head.next = reverseNode.next;reverseNode.next = null;
     */
    public void reverseLinkedList(){

        if(head.next == null || head.next.next == null){
            return;
        }
        HeroNode reverseNode = new HeroNode(0,"","");
        HeroNode temp = head.next;
        HeroNode next = null;

        while(temp != null){
            next = temp.next;
            temp.next = reverseNode.next;
            reverseNode.next = temp;
            temp = next;
        }

        head.next = reverseNode.next;
        reverseNode.next = null;
    }


    //显式链表数据
    //这个是用来遍历链表的方法
    /*
        分析:判断temp.next == null,就停止遍历
     */
    public void list(){

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

}

/*
    定义一个英雄节点:包含编号,姓名,绰号,还有指向下一个英雄结点的对象
 */
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 + '\'' +
                '}';
    }



}

精彩评论(0)

0 0 举报