余腾

导航

链表学习总结(代码)

package com.yuteng.linkedlist;

import java.util.Stack;

/**
 * @version 1.0
 * @author: 余腾
 * @date: 2021-07-22 14:54
 */
public class SingleLinkedListDemo {
    public static void main(String[] args) {

        //进行测试
        //先创建节点
        HeroNode hero1 = new HeroNode(1, "宋江", "及时雨");
        HeroNode hero2 = new HeroNode(2, "卢俊义", "玉麒麟");
        HeroNode hero3 = new HeroNode(3, "吴用", "智多星");
        HeroNode hero4 = new HeroNode(4, "林冲", "豹子头");
        HeroNode hero5 = new HeroNode(4, "bzd", "bzd");
        //创建一个链表
        SingleLinkedList list = new SingleLinkedList();
        //加入数据
        list.addByOrder(hero1);
        list.addByOrder(hero4);
        list.addByOrder(hero2);
        list.addByOrder(hero3);
        list.addByOrder(hero4);
        list.list();
        //修改
//        list.update(hero5);
//        System.out.println("修改后的链表数据-》》》》》》》》》》");
//        list.list();
//        list.delete(2);
//        System.out.println("删除后的链表数据->>>>>>>>>>>>>>>");
//        list.list();
//        //测试单链表中有效数据的个数
//        System.out.println(getLength(list.getHead()));
//        //测试链表中倒数第几个数据
//        System.out.println("测试链表中倒数第几个数据");
//        System.out.println(findLastIndexNode(list.getHead(), 3));
//        //测试链表中获取第k个数
//        System.out.println("测试链表中获取第k个数据");
//        System.out.println(getHeroNodeByIndex(list.getHead(), 3));
        System.out.println("单链表的反转遍历");
        reverseList(list.getHead());

    }
    /**
     * 问题: 获取到单链表的节点的个数(如果是带头节点的链表,不统计头节点)
     */
    /**
     *
     * @param head 链表的头节点
     * @return 返回的就是有效的节点个数
     */
    public  static int getLength(HeroNode head){
        int length=0;
        if (head.next==null){
            return length;
        }
        HeroNode cur=head.next;
        while (cur!=null){
            length++;
            cur=cur.next;
        }
        return length;
    }

    /**
     * 查询单链表中的倒数为第K的节点
     * @param k
     * @return
     * 思路1 编写一个方法 接受 一个head 节点 同时接收一个index
     *  2、index 表示是倒数第index 个节点
     *  3 先把链表从头到尾遍历一下
     */
    public static HeroNode findLastIndexNode(HeroNode head,int k){
        HeroNode temp=head.next;
        //遍历一下一共有多少个节点
        if (temp==null){
            return null;
        }
        int index=0;
        while (temp!=null){
            index++;
            temp=temp.next;
        }
        if (index<k){
            System.out.println("该链表一共有"+index+"个数据 倒数第k"+k+"数据不存在");
            return null;
        }else {
            int trueK=index-k+1;
            return getHeroNodeByIndex(head, trueK);
        }
    }

    /**
     * 获取正数第K个节点的数据
     * @param head
     * @param k
     * @return
     */
    public static HeroNode getHeroNodeByIndex(HeroNode head,int k){
        HeroNode temp=head.next;
        if (temp==null){
            System.out.println("链表长度为空。");
            return null;
        }
        int count=1;
        while (count<k){
            if (temp==null){
                System.out.println("本链表只有"+count+"条数据,第"+k+"号数据不存在");
                return  null;
            }
            count++;
            temp=temp.next;
        }
        return temp;
    }
    /**
     * 使用方式2可以利用栈这个数据结构,将各个节点压入到栈中,然后利用栈的先进先出的特点,完成逆序打印
     *
     */
    public static void reverseList(HeroNode head){
        HeroNode temp=head.next;
        Stack<HeroNode> heroNodes = new Stack<>();
        while (temp!=null){
            //将链表中的所有节点压入栈(不是添加是压入)
            heroNodes.push(temp);
            temp= temp.next;
        }
        //利用栈先进后出的特点进行遍历
        while (heroNodes.size()>0){
            System.out.println(heroNodes.pop());
        }
    }

    /**
     * 将单链表数据进行反转
     * @param head
     */
    public static void  reverseHeroNode(HeroNode head){
        // 如果当前链表为空,或者只有一个节点,无需反转,直接返回
        if (head.next==null||head.next.next==null){
            return;
        }
        //定义一个辅助指针变量,帮助我们遍历原来的链表
        HeroNode cur=head.next;
        //指向当前节[cur]点的下一个节点
        HeroNode next=null;
        HeroNode reverseHead=new HeroNode(0,"","");
        //遍历原来的链表,取出其数据并放在reverseHead的最前端
        while (cur!=null){
            //先暂时保存当前节点的下一个节点因为后面要用
            next=cur.next;
            //将cur的下一个节点指向新的链表的最前端
            cur.next=reverseHead.next;
            reverseHead.next=cur;
            //让cur后移
            cur=next;
        }
        //将head.next指向 reverseHead.next,实现单链表的反转
        head.next=reverseHead.next;


    }

}

/**
 * 定义SingleLinkedList 管理我们的英雄
 */
class SingleLinkedList {
    /**
     * 先初始化一个头节点,头节点不要动,不存放具体的数据
     */
    private HeroNode head = new HeroNode(0, "", "");

    /**
     * 返回头节点的方法
     */
    public HeroNode getHead(){
        return head;
    }
    /**
     * 添加节点到单向链表
     * 思路:当不考虑编号顺序时
     * 1.找到当前链表的最后节点
     * 2.将最后这个节点的next指向新的节点即可
     *
     * @param heroNode 你想新建的链表的数据域
     */
    public void add(HeroNode heroNode) {
        //因为Head 节点不能动 因为我们需要一个辅助遍历temp
        HeroNode temp = head;
        //遍历链表,找到最后
        while (true) {
            //找到链表的最后
            if (temp.next == null) {
                break;
            }
            //如果找不到就让temp后移
            else {
                temp = temp.next;
            }
        }
        //当退出while循环时temp指向了链表的最后
        //将最后的这个节点的next指向新的节点
        temp.next = heroNode;
    }

    /**
     * 第二种添加方式在添加英雄时,根据排名将英雄插入到指定位置
     * // 如果这个排名存在,则添加失败,并给出提示
     *
     * @param heroNode
     */
    public void addByOrder(HeroNode heroNode) {
        HeroNode temp = head;
        //标识添加的编号是否存在,默认为false
        boolean flag = false;
        while (true) {
            //说明temp已经在链表的最后
            if (temp.next == null) {

                break;
            } else if (temp.next.no > heroNode.no) {
                break;
            } else if (temp.next.no == heroNode.no) {
                //希望添加的heroNode编号已经存在
                flag = true;
                break;
            }
            //后移
            temp = temp.next;
        }
        if (flag) {
            System.out.printf("不能添加,待插入的数据 %d 已存在\n", heroNode.no);
        } else {
            heroNode.next=temp.next;
            temp.next = heroNode;


        }
    }

    /**
     * 根据传过来的heroNode的编号对heroNode进行修改
     * @param newHeroNode
     */
    public void update(HeroNode newHeroNode){
        if (head.next==null){
            System.out.println("链表为空");
            return;
        }
        HeroNode temp=head;
        boolean flag=false;
        while (true){
            if (temp.next==null){
                break;
            } else if (temp.next.no== newHeroNode.no){
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if (flag){
            temp.next.name= newHeroNode.name;
            temp.next.nickname= newHeroNode.nickname;
        }else {
            System.out.println("没有找到编号为"+newHeroNode.no+"的英雄");
        }
    }
    /**
     * 删除一个节点
     * 根据其编号进行删除
     */
    public void delete(int  no){
        //指向第一个数据
        if (head.next==null){
            System.out.println("链表为空无法删除数据");
            return;
        }
        HeroNode temp=head;
        //判断是否存在要删除的数据
        boolean flag=false;
        while (true){
            if (temp.next==null){
                break;
            }
            else if (temp.next.no==no)
            {
                flag=true;
                break;
            }
            //如果不满足以上条件就往后遍历
            temp=temp.next;
        }
        if (flag){
            temp.next=temp.next.next;
        }else {
            System.out.println("链表中不存在编号为: "+no+"的数据");
        }
    }
    /**
     * 显示链表[遍历]
     */
    public void list() {
        //判断链表是否位为空
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        //因为头节点不能动因此我们需要一个辅助变量来遍历
        else {
            HeroNode temp = head.next;
            while (true) {
                //判断是否到最后了
                if (temp == null) {
                    break;
                }
                System.out.println(temp);
                //将next后移
                temp = temp.next;
            }
        }
    }

}

/**
 * 定义HeroNode节点,每个HeroNode 对象就是一个节点
 */
class HeroNode {
    public int no;
    public String name;
    public String nickname;
    public HeroNode next;

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

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}

posted on 2021-07-22 20:05  余腾  阅读(59)  评论(0)    收藏  举报

Fork me on Gitee