数据结构与算法单排日记-2020/3/4-链表之单链表

在这里插入图片描述

流程:

在这里插入图片描述

单链表的应用实例

1. 单链表的建立:

使用带head头的单向链表实现 –水浒英雄排行榜管理
完成对英雄人物的增删改查操作, 注: 删除和修改,查找
第一种方法在添加英雄时,直接添加到链表的尾部
第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)

1.1第一种方法:添加英雄时,直接添加到链表的尾部

添加(创建)
1.先创建一个head 头节点, 作用就是表示单链表的头
2.后面我们每添加一个节点,就直接加入到 链表的最后
遍历:
1.通过一个辅助变量遍历,帮助遍历整个链表

  • 首先定义数据节点信息
public class Node {
    private int num;
    private String name;
    private String nickname;
    private Node next;

    public Node(int num, String name, String nickname) {
        this.num = num;
        this.name = name;
        this.nickname = nickname;
    }

    public Node getNext() {
        return next;
    }
    public void setNext(Node next) {
        this.next = next;
    }

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

  • 定义链表规则
public class SingeLinkedList {
    //先创建一个head 头节点, 作用就是表示单链表的头
    private Node firstNode = new Node(0, "", "");

    //后面我们每添加一个节点,就直接加入到 链表的最后
    //思路 当不考虑编号的顺序的时候
    //1.找到当前链表的最后节点
    //2.将最后这个节点的next指向新的节点
    public void add(Node node) {
        //1.找到最后一个节点,每次查询元素都要从头开始
        Node temp = firstNode;
        while (true) {
            if (temp.getNext() == null) {
                break;
            } else {
                temp = temp.getNext();
            }
        }
        //2.将最后这个节点的next指向新的节点
        temp.setNext(node);
    }

    //通过一个辅助变量遍历,帮助遍历整个链表
    public void list() {
        //先判断链表是否为空
        if (firstNode.getNext() == null) {
            System.out.println("链表为空");
        } else {
            //因为头节点不能动 因此需要一个辅助变量
            Node temp = firstNode;
            while (true) {
                //判断链表是否到最后
                if (temp.getNext() == null) {
                    break;
                } else {
                    //输出节点的信息
                    System.out.println(temp.getNext());
                    //将 temp 后移
                    temp = temp.getNext();
                }
            }
        }
    }
}
  • 测试
public class DemoNode {
    public static void main(String[] args) {
        Node one = new Node(1,"宋江","及时雨");
        Node two = new Node(2,"卢俊义", "玉麒麟");
        Node three = new Node(3,"吴用","智多星");
        Node four = new Node(4,"公孙胜","入云龙");
        Node five = new Node(5,"关胜","大刀");

        SingeLinkedList singeLinkedList = new SingeLinkedList();
        singeLinkedList.add(four);
        singeLinkedList.add(five);
        singeLinkedList.add(one);
        singeLinkedList.add(three);
        singeLinkedList.add(two);

        singeLinkedList.list();
    }
}

在这里插入图片描述

1.2 第二种方法:添加英雄时,按照英雄排名排序

自己方法:
1.创建列表,盛放链表所有信息
2.使用collections.sort排序,使用lambda表达式重写Comparator比较器,根据num排序升序
3.stream流forEach遍历array

import java.util.*;

public class SingeLinkedList02 {
    //先创建一个head 头节点, 作用就是表示单链表的头
    private Node firstNode = new Node(0, "", "");

    //后面我们每添加一个节点,就直接加入到 链表的最后
    //思路 当不考虑编号的顺序的时候
    //1.找到当前链表的最后节点
    //2.将最后这个节点的next指向新的节点
    public void add(Node node) {
        //1.找到最后一个节点,每次查询元素都要从头开始
        Node temp = firstNode;
        while (true) {
            if (temp.getNext() == null) {
                break;
            } else {
                temp = temp.getNext();
            }
        }
        //2.将最后这个节点的next指向新的节点
        temp.setNext(node);
    }

    //通过一个辅助变量遍历,帮助遍历整个链表
    public void list() {
        //创建列表,盛放链表所有信息
        List<Node> array = new ArrayList<>();
        Map<Integer,Node> map = new HashMap<>();
        //先判断链表是否为空
        if (firstNode.getNext() == null) {
            System.out.println("链表为空");
        } else {
            //因为头节点不能动 因此需要一个辅助变量
            Node temp = firstNode;
            while (true) {
                //判断链表是否到最后
                if (temp.getNext() == null) {
                    break;
                } else {
                    array.add(temp.getNext());
                    temp=temp.getNext();
                }
            }
            //使用collections.sort排序,使用lambda表达式重写Comparator比较器,根据num排序升序
            Collections.sort(array,(Node t,Node t1)->{return t.getNum()-t1.getNum();});
            //stream流forEach遍历array
            array.stream().forEach(i-> System.out.println(i));
        }
    }
}
public class DemoNode {
    public static void main(String[] args) {
        Node one = new Node(1, "宋江", "及时雨");
        Node two = new Node(2, "卢俊义", "玉麒麟");
        Node three = new Node(3, "吴用", "智多星");
        Node four = new Node(4, "公孙胜", "入云龙");
        Node five = new Node(5, "关胜", "大刀");

/*        SingeLinkedList singeLinkedList = new SingeLinkedList();
        singeLinkedList.add(four);
        singeLinkedList.add(five);
        singeLinkedList.add(one);
        singeLinkedList.add(three);
        singeLinkedList.add(two);

        singeLinkedList.list();*/
        SingeLinkedList02 singeLinkedList02 = new SingeLinkedList02();
        singeLinkedList02.add(five);
        singeLinkedList02.add(one);
        singeLinkedList02.add(three);
        singeLinkedList02.add(two);
        singeLinkedList02.add(four);

        singeLinkedList02.list();
    }
}

在这里插入图片描述

教程方法:
1.首先找到新添加的节点的位置, 是通过辅助变量temp(指针), 通过遍历来搞定
在这里插入图片描述
2.新的节点.next = temp.next
在这里插入图片描述
3.将temp.next = 新的节点
在这里插入图片描述
在这里插入图片描述

public class SingeLinkedList {
    //先创建一个head 头节点, 作用就是表示单链表的头
    private Node firstNode = new Node(0, "", "");

    //后面我们每添加一个节点,就直接加入到 链表的最后
    //思路 当不考虑编号的顺序的时候
    //1.找到当前链表的最后节点
    //2.将最后这个节点的next指向新的节点
    public void add(Node node) {
        //1.找到最后一个节点,每次查询元素都要从头开始
        Node temp = firstNode;
        while (true) {
            if (temp.getNext() == null) {
                break;
            } else {
                temp = temp.getNext();
            }
        }
        //2.将最后这个节点的next指向新的节点
        temp.setNext(node);
    }

    //添加考虑编号的顺序
    //如果存在相同顺序,则添加失败,并显示已存在
    public void addByOrder(Node node) {
        Node temp = firstNode;
        boolean flag = false;//标识插入node的序号是否已经存在

        //使用循环,寻找node节点的前一个节点
        while (true) {
            if (temp.getNext()==null){
                break;//如果首节点的下一个节点为空,首节点就是node前一个节点,找到node的前一个节点
            }else if (temp.getNext().getNum()>node.getNum()){//如果temp的下一个节点的编号大于node的编号,说明node应该插入temp和temp的下一个节点之间
                break;//找到node的前一个节点
            }else if (temp.getNext().getNum()==node.getNum()){//如果temp的下一个节点的编号等于node的编号,说明节点重复
                flag=true;
                break;
            }
            temp=temp.getNext();//循环
        }

        //node应该插入链表
        //如果存在相同顺序,则添加失败,并显示已存在
        if (flag==true){
            System.out.println("编号为"+node.getNum()+"的节点已经存在");
        }else {
            node.setNext(temp.getNext());//将node节点插到temp后一个节点之前
            temp.setNext(node);//将节点插到temp节点之后
        }
    }

    //通过一个辅助变量遍历,帮助遍历整个链表
    public void list() {
        //先判断链表是否为空
        if (firstNode.getNext() == null) {
            System.out.println("链表为空");
        } else {
            //因为头节点不能动 因此需要一个辅助变量
            Node temp = firstNode;
            while (true) {
                //判断链表是否到最后
                if (temp.getNext() == null) {
                    break;
                } else {
                    //输出节点的信息
                    System.out.println(temp.getNext());
                    //将 temp 后移
                    temp = temp.getNext();
                }
            }
        }
    }
}
public class DemoNode {
    public static void main(String[] args) {
        Node one = new Node(1, "宋江", "及时雨");
        Node two = new Node(2, "卢俊义", "玉麒麟");
        Node three = new Node(3, "吴用", "智多星");
        Node four = new Node(4, "公孙胜", "入云龙");
        Node five = new Node(5, "关胜", "大刀");

        SingeLinkedList singeLinkedList = new SingeLinkedList();
        singeLinkedList.addByOrder(four);
        singeLinkedList.addByOrder(five);
        singeLinkedList.addByOrder(one);
        singeLinkedList.addByOrder(three);
        singeLinkedList.addByOrder(two);
        singeLinkedList.addByOrder(two);

        singeLinkedList.list();
/*        SingeLinkedList02 singeLinkedList02 = new SingeLinkedList02();
        singeLinkedList02.add(five);
        singeLinkedList02.add(one);
        singeLinkedList02.add(three);
        singeLinkedList02.add(two);
        singeLinkedList02.add(four);
        singeLinkedList02.list();*/
    }
}

在这里插入图片描述

2.节点信息的修改

根据node编号,修改node里面的信息

public class SingeLinkedList {
    //先创建一个head 头节点, 作用就是表示单链表的头
    private Node firstNode = new Node(0, "", "");


    /*链表添加节点法一:每添加一个节点,就直接加入到 链表的最后*/

    //后面我们每添加一个节点,就直接加入到 链表的最后
    //思路 当不考虑编号的顺序的时候
    //1.找到当前链表的最后节点
    //2.将最后这个节点的next指向新的节点
    public void add(Node node) {
        //1.找到最后一个节点,每次查询元素都要从头开始
        Node temp = firstNode;
        while (true) {
            if (temp.getNext() == null) {
                break;
            } else {
                temp = temp.getNext();
            }
        }
        //2.将最后这个节点的next指向新的节点
        temp.setNext(node);
    }


    /*链表添加节点法二:每添加一个节点,添加考虑编号的顺序*/

    //添加考虑编号的顺序
    //如果存在相同顺序,则添加失败,并显示已存在
    public void addByOrder(Node node) {
        Node temp = firstNode;
        boolean flag = false;//标识插入node的序号是否已经存在

        //使用循环,寻找node节点的前一个节点
        while (true) {
            if (temp.getNext()==null){
                break;//如果首节点的下一个节点为空,首节点就是node前一个节点,找到node的前一个节点
            }else if (temp.getNext().getNum()>node.getNum()){//如果temp的下一个节点的编号大于node的编号,说明node应该插入temp和temp的下一个节点之间
                break;//找到node的前一个节点
            }else if (temp.getNext().getNum()==node.getNum()){//如果temp的下一个节点的编号等于node的编号,说明节点重复
                flag=true;
                break;
            }
            temp=temp.getNext();//循环
        }

        //node应该插入链表
        //如果存在相同顺序,则添加失败,并显示已存在
        if (flag==true){
            System.out.println("编号为"+node.getNum()+"的节点已经存在");
        }else {
            node.setNext(temp.getNext());//将node节点插到temp后一个节点之前
            temp.setNext(node);//将节点插到temp节点之后
        }
    }

    /*遍历整个链表*/
    //通过一个辅助变量遍历,帮助遍历整个链表
    public void list() {
        //先判断链表是否为空
        if (firstNode.getNext() == null) {
            System.out.println("链表为空");
        } else {
            //因为头节点不能动 因此需要一个辅助变量
            Node temp = firstNode;
            while (true) {
                //判断链表是否到最后
                if (temp.getNext() == null) {
                    break;
                } else {
                    //输出节点的信息
                    System.out.println(temp.getNext());
                    //将 temp 后移
                    temp = temp.getNext();
                }
            }
        }
    }

    /*修改节点信息*/
    public void updata(Node node){
       if (firstNode.getNext()==null){//如果头结点的下一个节点为null,则链表为空
           System.out.println("链表为空");
       }else{
           Node temp = firstNode;//若不为空,开始遍历链表,寻找num
           while (true){
               if (temp.getNum()==node.getNum()){//找到编号,修改数据
                   temp.setName(node.getName());
                   temp.setNickname(node.getNickname());
                   break;
               }else if (temp.getNext()==null){//找不到编号,打印信息
                   System.out.println("不存在编号为"+node.getNum()+"的节点");
                   break;
               }else {//temp指针循环
                   temp=temp.getNext();
               }
           }
       }
    }
}
public class Demo02 {
    public static void main(String[] args) {
        Node one = new Node(1, "宋江", "及时雨");
        Node two = new Node(2, "卢俊义", "玉麒麟");
        Node three = new Node(3, "吴用", "智多星");
        Node four = new Node(4, "公孙胜", "入云龙");
        Node five = new Node(5, "关胜", "大刀");

        SingeLinkedList singeLinkedList = new SingeLinkedList();
        singeLinkedList.addByOrder(four);
        singeLinkedList.addByOrder(five);
        singeLinkedList.addByOrder(one);
        singeLinkedList.addByOrder(three);
        singeLinkedList.addByOrder(two);

        singeLinkedList.list();

        Node newNode =  new Node(2,"更改name","更改nickname");
        singeLinkedList.updata(newNode);
        System.out.println("更新如下:");
        singeLinkedList.list();

        Node newNode2 =  new Node(12,"更改name","更改nickname");
        singeLinkedList.updata(newNode2);
        System.out.println("更新如下:");
        singeLinkedList.list();

    }
}

在这里插入图片描述

3.删除节点

这里是引用

public class SingeLinkedList {
    //先创建一个head 头节点, 作用就是表示单链表的头
    private Node firstNode = new Node(0, "", "");


    /*链表添加节点法一:每添加一个节点,就直接加入到 链表的最后*/

    //后面我们每添加一个节点,就直接加入到 链表的最后
    //思路 当不考虑编号的顺序的时候
    //1.找到当前链表的最后节点
    //2.将最后这个节点的next指向新的节点
    public void add(Node node) {
        //1.找到最后一个节点,每次查询元素都要从头开始
        Node temp = firstNode;
        while (true) {
            if (temp.getNext() == null) {
                break;
            } else {
                temp = temp.getNext();
            }
        }
        //2.将最后这个节点的next指向新的节点
        temp.setNext(node);
    }


    /*链表添加节点法二:每添加一个节点,添加考虑编号的顺序*/

    //添加考虑编号的顺序
    //如果存在相同顺序,则添加失败,并显示已存在
    public void addByOrder(Node node) {
        Node temp = firstNode;
        boolean flag = false;//标识插入node的序号是否已经存在

        //使用循环,寻找node节点的前一个节点
        while (true) {
            if (temp.getNext() == null) {
                break;//如果首节点的下一个节点为空,首节点就是node前一个节点,找到node的前一个节点
            } else if (temp.getNext().getNum() > node.getNum()) {//如果temp的下一个节点的编号大于node的编号,说明node应该插入temp和temp的下一个节点之间
                break;//找到node的前一个节点
            } else if (temp.getNext().getNum() == node.getNum()) {//如果temp的下一个节点的编号等于node的编号,说明节点重复
                flag = true;
                break;
            }
            temp = temp.getNext();//循环
        }

        //node应该插入链表
        //如果存在相同顺序,则添加失败,并显示已存在
        if (flag == true) {
            System.out.println("编号为" + node.getNum() + "的节点已经存在");
        } else {
            node.setNext(temp.getNext());//将node节点插到temp后一个节点之前
            temp.setNext(node);//将节点插到temp节点之后
        }
    }

    /*遍历整个链表*/
    //通过一个辅助变量遍历,帮助遍历整个链表
    public void list() {
        //先判断链表是否为空
        if (firstNode.getNext() == null) {
            System.out.println("链表为空");
        } else {
            //因为头节点不能动 因此需要一个辅助变量
            Node temp = firstNode;
            while (true) {
                //判断链表是否到最后
                if (temp.getNext() == null) {
                    break;
                } else {
                    //输出节点的信息
                    System.out.println(temp.getNext());
                    //将 temp 后移
                    temp = temp.getNext();
                }
            }
        }
    }

    /*修改节点信息*/
    public void updata(Node node) {
        if (firstNode.getNext() == null) {//如果头结点的下一个节点为null,则链表为空
            System.out.println("链表为空");
        } else {
            Node temp = firstNode;//若不为空,开始遍历链表,寻找num
            while (true) {
                if (temp.getNum() == node.getNum()) {//找到编号,修改数据
                    temp.setName(node.getName());
                    temp.setNickname(node.getNickname());
                    break;
                } else if (temp.getNext() == null) {//找不到编号,打印信息
                    System.out.println("不存在编号为" + node.getNum() + "的节点");
                    break;
                } else {//temp指针循环
                    temp = temp.getNext();
                }
            }
        }
    }


    /*根据节点编号,删除节点*/
    public void deletNode(int n) {
        if (firstNode.getNext() == null) {
            System.out.println("链表为空");
        } else {
            Node temp = firstNode;
            while (true) {
                if (temp.getNext().getNum() == n) {//如果temp的下一个节点num为n,找到要删的节点
                    temp.setNext(temp.getNext().getNext());//将temp的下一个节点链接到下下个节点
                    break;
                } else if (temp.getNext() == null) {
                    System.out.println("链表中没有" + n + "节点");
                    break;
                } else {
                    temp = temp.getNext();
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值