链表学习笔记二单链表代码

package com.hao.firstdemo.datastruct;

import java.util.Stack;

/**
 * @author haoxiansheng
 */
public class TestSingleLinkedList {
    public static void main(String[] args) {
        //测试 你就可以在这里玩链表了 哈哈
        HeroNode node1 = new HeroNode(1, "曹操", "奸雄");
        HeroNode node2 = new HeroNode(2, "刘备", "小人");
        HeroNode node3 = new HeroNode(3, "赵云", "忠义之士");
        HeroNode node4 = new HeroNode(4, "关羽", "关二爷");
        SingleLinkedList linkedList = new SingleLinkedList();
        linkedList.add(node1);
        linkedList.add(node2);
        linkedList.add(node3);
        linkedList.add(node4);
        linkedList.show();
        HeroNode node5 = new HeroNode(4, "关平", "关二爷");
        linkedList.update(node5);
        linkedList.show();

        //测试
        System.out.println("有效的头节点为" + getLength(linkedList.getHead()));
    }

    /**
     * 返回链表的有效个数 没有统计头节点
     *
     * @param heroNode 链表的头节点
     * @return
     */
    public static int getLength(HeroNode heroNode) {
        int len = 0;
        if (heroNode.next == null) {
            //空链表
            return len;
        }
        //借助辅助变量
        HeroNode current = heroNode.next;
        while (current != null) {
            len++;
            current = current.next;
        }
        return len;
    }

    /**
     * 思路
     * 1、编写一个接收 节点和 index 参数(标识倒数第几个)
     * 2、先得到链表的大小size,然后遍历size-index次就好
     * 3、找到返回 没有返回null
     *
     * @param head  头节点
     * @param index 倒数第几个数
     * @return 求指定倒数个数的节点
     */
    public static HeroNode getLastIndexNode(HeroNode head, int index) {
        if (head == null) {
            return null; //没有找到返回null
        }
        int size = getLength(head);
        if (index <= 0 || index > size) {
            return null;
        }
        //定义辅助变量
        HeroNode temp = head.next;
        for (int i = 0; i < size - index; i++) {
            temp = temp.next;
        }
        return temp;
    }

    /**
     * 将单链表反转
     * 头节点 => 1 => 2 => 5 => 9  反转 头节点 => 9 => 5 => 2 => 1
     * 1、先定义一个节点reverseHead = new HeroNode();
     * 2、从头到尾遍历原来的链表,每遍历一个,将其取出,并放在reverseHead的最前面;
     * 3、原来的链表的head.next=reverseHead.next
     * 这道题有点绕需要研究懂while种的几行代码
     */
    public static void reverseList(HeroNode head) {
        if (head.next == null || head.next.next == null) {
            return;
        }
        HeroNode current = head.next; //辅助遍历
        HeroNode next = null; //指向当前节点[current]的下一个节点
        HeroNode reverseHead = new HeroNode(0, "", "");
        //遍历原来的链表,每遍历一个就将其取出并放在链表reverseHead的下一个节点的最前端
        while (current != null) {
            next = current.next; //先暂时保存当前节点的下一个节点,因为后续要使用
            current.next = reverseHead.next; //将current的下一个节点指向新链表的最前端(也就是reverseHead 后面)
            reverseHead.next = current; //将current连接到最新的链表上
            current = next; //让current 后移
        }
        //将head.next 指向reverseHead.next, 实现链表的反转
        head.next = reverseHead.next;
    }

    /**
     *  从未到头打印单链表
     *  思路:用栈的方式
     */
    public static void reversePrint(HeroNode head) {
        if (head.next == null) {
            return;
        }
        //创建一个栈 将node压入栈中
        Stack<HeroNode> heroNodeStack = new Stack<>();
        HeroNode temp = head.next;
        while (temp != null) {
            heroNodeStack.add(temp);
            temp = temp.next;
        }
        while (heroNodeStack.size() > 0) {
            System.out.println(heroNodeStack.pop());
        }

    }
}

//定义一个类管理列表
class SingleLinkedList {
    //先初始化一个头节点,头节点不要动 不存放具体数据 后续遍历查找需要使用头节点
    private HeroNode head = new HeroNode(0, "", "");

    public HeroNode getHead() {
        return head;
    }

    /**
     * 添加节点到单向链表
     * 思路一:不考虑编号 1、找到当前链表的最后节点  2、将最后这个节点的next 指向新的节点
     */
    public void add(HeroNode heroNode) {
        //head节点不能动, 因此我们需要一个辅助遍历temp
        HeroNode temp = head;
        //循环遍历 找到最后 temp.next == null
        while (true) {
            if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        //将最后这个节点 next 指向新的节点
        temp.next = heroNode;
    }

    /**
     * 第二种思路
     * 添加时是有顺序的 然后根据这个number 大小
     * 如果有这个排名 添加失败并给出提示
     */
    public void addByOrder(HeroNode heroNode) {
        // 辅助遍历帮找添加的位置 因为是单链表 我们找的temp 是位于添加位置的前一个位置 否则添加不了
        HeroNode temp = head;
        boolean flag = false; //标识添加的编号是否存在 默认不存在
        while (true) {
            if (temp.next == null) { //已经在链表最后
                break;
            }
            if (temp.next.number > heroNode.number) { //位置找到,就在temp后面插入
                break;
            }
            if (temp.next.number == heroNode.number) { //说明添加的节点已经存在
                flag = true;
                break;
            }
            temp = temp.next;
        }

        if (flag) {
            System.out.printf("准备添加的数据%d 已经存在了", heroNode.number);
        } else {
            // 插入到链表中 这点有点绕 类似于 A  C  B 变量赋值
            heroNode.next = temp.next;
            temp.next = heroNode;
        }
    }

    /**
     * 显示链表
     */
    public void show() {
        if (head.next == null) {
            System.out.println("链表为null");
        }
        HeroNode temp = head.next;
        while (true) {
            if (temp == null) {
                System.out.println("链表为空");
                return;
            }
            //打印信息、节点后移
            System.out.println(temp);
            temp = temp.next;
        }
    }

    /**
     * 修改节点 根据number 来修改 number的编号不能变化
     */
    public void update(HeroNode newHeroNode) {
        //判断队列是否为null
        if (head.next == null) {
            System.out.println("队列为null");
            return;
        }
        //找到需要修改的节点 定义辅助变量
        HeroNode temp = head.next;
        boolean flag = false;
        while (true) {
            if (temp == null) {
                System.out.println("队列为null");
                break;
            }
            if (temp.number == newHeroNode.number) {
                flag = true;
                break;
            }
            temp = temp.next;
        }

        //判断
        if (flag) {
            temp.name = newHeroNode.name;
            temp.nickName = newHeroNode.nickName;
        } else {
            System.out.printf("没有找到%d的节点", newHeroNode.number);
        }
    }

    /**
     * 删除节点
     * 思路:1、head 不能动 需要一个辅助节点temp 找到删除节点的前一个节点
     * 2、temp.next.number 和要删除的进行比较
     */
    public void del(int number) {
        HeroNode temp = head;
        boolean flag = false; //标识是否找到代删除的节点。
        while (true) {
            if (temp.next == null) { //已经到链表的最后
                break;
            }
            if (temp.next.number == number) { //找到带删除节点的前一个节点
                flag = true;
                break;
            }
            temp = temp.next;
        }
        //判断是否找到 找到删除
        if (flag) {
            temp.next = temp.next.next;
        } else {
            System.out.println("没有找到待删除的节点");
        }
    }
}

//定义一个节点 每个HeroNode 对象就是一个节点
class HeroNode {
    public int number;
    public String name; //名字
    public String nickName; //昵称
    public HeroNode next; // 指向下一个域

    /**
     * 构造器
     *
     * @param number
     * @param name
     * @param nickName
     */
    public HeroNode(int number, String name, String nickName) {
        this.number = number;
        this.name = name;
        this.nickName = nickName;
    }

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值