数据结构和算法004——队列(单链表的增删改查)

1、链表(Linked List)介绍

链表是有序得,分为带头结点和不带头结点

如下图不带头节点,不是连续存储得(内存中实际的存储    )

 

如下图,带头节点的,是逻辑结构,看起来是连续存储

单链表的添加

package linkedList;

/**
 * @author 14308
 * @create 2020/11/14 10:49
 * @description  单链表
 * 场景描述:
 *     添加水浒传英雄,并按照自有排名排序
 *
 */
public class SingleLinkedList {
    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, "林冲", "豹子头");

        //创建一个链表
        oneLinkedList oneLinkedList = new oneLinkedList();

        //添加
        oneLinkedList.add(hero1);
        oneLinkedList.add(hero3);
        oneLinkedList.add(hero2);
        oneLinkedList.add(hero4);

        //显示
        oneLinkedList.list();
    }

}

//定义一个SingleLinkedList管理我们的英雄
class oneLinkedList{
    //先初始化一个头节点 不存放具体的数据
    private HeroNode head = new HeroNode(0,"","");
    //添加节点到单向链表
    //思路:当不考虑编号的顺序时,
    //1、找到当前链表的最后节点
    //2、将最后这个节点的next域指向新的节点
    public void add(HeroNode heroNode){
        //因为head节点不能动,因此我们需要一个辅助变量,temp相当于目前的链表
        HeroNode temp = head;
        while (true) {
            //找到链表最后
            if (temp.next == null){
                break;
            }
            //如果没有找到,就将temp后移
            temp = temp.next;
        }
        //当退出while循环时,temp就指向链表的最后,则将新增的节点连上上个节点的next
        temp.next = heroNode;
    }

    //显示链表[遍历]
    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 = temp.next;
        }
    }
}

//先定义一个Hero,每个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;
    }

    //为了显示方便,重写toString();
    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +

                '}';
    }
}

 

 这个时候有一个问题,添加之后没有管no,所以no没有按照实际顺序排

第二种方式添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名的话,提示排名已经存在)

 

  

package linkedList;

/**
 * @author 14308
 * @create 2020/11/14 10:49
 * @description  单链表
 * 场景描述:
 *     添加水浒传英雄,并按照自有排名排序
 *
 */
public class SingleLinkedList {
    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, "林冲", "豹子头");

        //创建一个链表
        oneLinkedList oneLinkedList = new oneLinkedList();

        //添加
//        oneLinkedList.add(hero1);
//        oneLinkedList.add(hero3);
//        oneLinkedList.add(hero2);
//        oneLinkedList.add(hero4);

        //添加按照编号的顺序
        oneLinkedList.addByOrder(hero1);
        oneLinkedList.addByOrder(hero4);
        oneLinkedList.addByOrder(hero2);
        oneLinkedList.addByOrder(hero3);
        oneLinkedList.addByOrder(hero3);

        //显示
        oneLinkedList.list();
    }

}

//定义一个SingleLinkedList管理我们的英雄
class oneLinkedList{
    //先初始化一个头节点 不存放具体的数据
    private HeroNode head = new HeroNode(0,"","");
    //添加节点到单向链表
    //思路:当不考虑编号的顺序时,
    //1、找到当前链表的最后节点
    //2、将最后这个节点的next域指向新的节点
    public void add(HeroNode heroNode){
        //因为head节点不能动,因此我们需要一个辅助变量,temp相当于目前的链表
        HeroNode temp = head;
        while (true) {
            //找到链表最后
            if (temp.next == null){
                break;
            }
            //如果没有找到,就将temp后移
            temp = temp.next;
        }
        //当退出while循环时,temp就指向链表的最后,则将新增的节点连上上个节点的next
        temp.next = heroNode;
    }

    //第二种方式添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名的话,提示排名已经存在)
    public void addByOrder(HeroNode heroNode){

        //因为头节点不能动,因此仍然通过一个辅助变量来帮助找到添加的位置
        //因为是单链表,因为我们找的是temp,是位于添加位置的前一个结点,否则插入不了
        HeroNode temp = head;
        //标识添加的编号是否存在,默认为false
        Boolean flag = false;

        while (true) {
            //说明temp已经再链表最后
            if (temp.next == null){
                break;
            }

            //位置找到了,就在temp的后面插入
            if (temp.next.no > heroNode.no){

                break;
            } else if (temp.next.no == heroNode.no) {  //说明希望添加的heroNode的编号已然存在

                flag = true;//说明编号已经存在
                break;
            }

            temp = temp.next;  //后移,遍历当前链表
        }

        //判断flag的值
        if (flag){  //不能添加,编号已经存在
            System.out.printf("准备加入的英雄的编号%d已经存在,不能加入\n",heroNode.no);
        } else {
            //插入到链表temp的后面
            //***这里说明先是后一个结点赋值,因为如果前抑恶结点赋值,那么temp的下一个位置就先变成了heroNode,
            //***heroNode.next又指向了自己

            //后一个结点
            heroNode.next = temp.next;

            //前一个结点
            temp.next = heroNode;


        }
    }


    //显示链表[遍历]
    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 = temp.next;
        }
    }
}

//先定义一个Hero,每个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;
    }

    //为了显示方便,重写toString();
    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +

                '}';
    }
}

单链表的修改

package linkedList;

/**
 * @author 14308
 * @create 2020/11/14 10:49
 * @description  单链表
 * 场景描述:
 *     添加水浒传英雄,并按照自有排名排序
 *
 */
public class SingleLinkedList {
    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, "林冲", "豹子头");

        //创建一个链表
        oneLinkedList oneLinkedList = new oneLinkedList();

        //添加
//        oneLinkedList.add(hero1);
//        oneLinkedList.add(hero3);
//        oneLinkedList.add(hero2);
//        oneLinkedList.add(hero4);

        //添加按照编号的顺序
        oneLinkedList.addByOrder(hero1);
        oneLinkedList.addByOrder(hero4);
        oneLinkedList.addByOrder(hero2);
        oneLinkedList.addByOrder(hero3);

        //显示
//        oneLinkedList.list();

        //测试修改结点的代码
        HeroNode newHeroNode = new HeroNode(2, "小卢", "小尾巴");
        oneLinkedList.update(newHeroNode);

        oneLinkedList.list();
    }

}

//定义一个SingleLinkedList管理我们的英雄
class oneLinkedList{
    //先初始化一个头节点 不存放具体的数据
    private HeroNode head = new HeroNode(0,"","");
    //添加节点到单向链表
    //思路:当不考虑编号的顺序时,
    //1、找到当前链表的最后节点
    //2、将最后这个节点的next域指向新的节点
    public void add(HeroNode heroNode){
        //因为head节点不能动,因此我们需要一个辅助变量,temp相当于目前的链表
        HeroNode temp = head;
        while (true) {
            //找到链表最后
            if (temp.next == null){
                break;
            }
            //如果没有找到,就将temp后移
            temp = temp.next;
        }
        //当退出while循环时,temp就指向链表的最后,则将新增的节点连上上个节点的next
        temp.next = heroNode;
    }

    //第二种方式添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名的话,提示排名已经存在)
    public void addByOrder(HeroNode heroNode){

        //因为头节点不能动,因此仍然通过一个辅助变量来帮助找到添加的位置
        //因为是单链表,因为我们找的是temp,是位于添加位置的前一个结点,否则插入不了
        HeroNode temp = head;
        //标识添加的编号是否存在,默认为false
        Boolean flag = false;

        while (true) {
            //说明temp已经再链表最后
            if (temp.next == null){
                break;
            }

            //位置找到了,就在temp的后面插入
            if (temp.next.no > heroNode.no){

                break;
            } else if (temp.next.no == heroNode.no) {  //说明希望添加的heroNode的编号已然存在

                flag = true;//说明编号已经存在
                break;
            }

            temp = temp.next;  //后移,遍历当前链表
        }

        //判断flag的值
        if (flag){  //不能添加,编号已经存在
            System.out.printf("准备加入的英雄的编号%d已经存在,不能加入\n",heroNode.no);
        } else {
            //插入到链表temp的后面
            //***这里说明先是后一个结点赋值,因为如果前抑恶结点赋值,那么temp的下一个位置就先变成了heroNode,
            //***heroNode.next又指向了自己

            //后一个结点
            heroNode.next = temp.next;

            //前一个结点
            temp.next = heroNode;


        }
    }

    //修改结点的信息,根据no编号来修改,即no编号不能改,
    //根据newHeroNode的no来修改即可
    public void update(HeroNode newHeroNode){
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }

        //找到需要修改的结点,根据no编号
        //先定义一个辅助变量
        HeroNode temp = head.next;
        boolean flag = false;   //表示是否找到该结点
        while (true) {
            if (temp == null){
                break;    //已经遍历完链表了
            }

            if (temp.no == newHeroNode.no){
                //说明已经找到了
                flag = true;
                break;
            }
            temp = temp.next;
        }

        //根据flag,判断是否找到要修改的结点
        if (flag){
            temp.name = newHeroNode.name;
            temp.nickName = newHeroNode.nickName;
            //这里newHeroNode.next传的是null
//            temp.next = newHeroNode.next;
        } else {  //说明没找到
            System.out.printf("没有找到编号%d的结点,不能修改\n",newHeroNode.no);
        }
    }


    //显示链表[遍历]
    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 = temp.next;
        }
    }
}

//先定义一个Hero,每个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;
    }

    //为了显示方便,重写toString();
    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +

                '}';
    }
}

 

 删除链表

 

package linkedList;

/**
 * @author 14308
 * @create 2020/11/14 10:49
 * @description  单链表
 * 场景描述:
 *     添加水浒传英雄,并按照自有排名排序
 *
 */
public class SingleLinkedList {
    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, "林冲", "豹子头");

        //创建一个链表
        oneLinkedList oneLinkedList = new oneLinkedList();

        //添加
//        oneLinkedList.add(hero1);
//        oneLinkedList.add(hero3);
//        oneLinkedList.add(hero2);
//        oneLinkedList.add(hero4);

        //添加按照编号的顺序
        oneLinkedList.addByOrder(hero1);
        oneLinkedList.addByOrder(hero4);
        oneLinkedList.addByOrder(hero2);
        oneLinkedList.addByOrder(hero3);
        oneLinkedList.list();
        //显示
//        oneLinkedList.list();

        //测试修改结点的代码
//        HeroNode newHeroNode = new HeroNode(2, "小卢", "小尾巴");
//        oneLinkedList.update(newHeroNode);
//
//        oneLinkedList.list();

        System.out.println("_____________________");
        oneLinkedList.deleteNode(1);
        oneLinkedList.list();
    }

}

//定义一个SingleLinkedList管理我们的英雄
class oneLinkedList{
    //先初始化一个头节点 不存放具体的数据
    private HeroNode head = new HeroNode(0,"","");
    //添加节点到单向链表
    //思路:当不考虑编号的顺序时,
    //1、找到当前链表的最后节点
    //2、将最后这个节点的next域指向新的节点
    public void add(HeroNode heroNode){
        //因为head节点不能动,因此我们需要一个辅助变量,temp相当于目前的链表
        HeroNode temp = head;
        while (true) {
            //找到链表最后
            if (temp.next == null){
                break;
            }
            //如果没有找到,就将temp后移
            temp = temp.next;
        }
        //当退出while循环时,temp就指向链表的最后,则将新增的节点连上上个节点的next
        temp.next = heroNode;
    }

    //第二种方式添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名的话,提示排名已经存在)
    public void addByOrder(HeroNode heroNode){

        //因为头节点不能动,因此仍然通过一个辅助变量来帮助找到添加的位置
        //因为是单链表,因为我们找的是temp,是位于添加位置的前一个结点,否则插入不了
        HeroNode temp = head;
        //标识添加的编号是否存在,默认为false
        Boolean flag = false;

        while (true) {
            //说明temp已经再链表最后
            if (temp.next == null){
                break;
            }

            //位置找到了,就在temp的后面插入
            if (temp.next.no > heroNode.no){

                break;
            } else if (temp.next.no == heroNode.no) {  //说明希望添加的heroNode的编号已然存在

                flag = true;//说明编号已经存在
                break;
            }

            temp = temp.next;  //后移,遍历当前链表
        }

        //判断flag的值
        if (flag){  //不能添加,编号已经存在
            System.out.printf("准备加入的英雄的编号%d已经存在,不能加入\n",heroNode.no);
        } else {
            //插入到链表temp的后面
            //***这里说明先是后一个结点赋值,因为如果前抑恶结点赋值,那么temp的下一个位置就先变成了heroNode,
            //***heroNode.next又指向了自己

            //后一个结点
            heroNode.next = temp.next;

            //前一个结点
            temp.next = heroNode;


        }
    }

    //修改结点的信息,根据no编号来修改,即no编号不能改,
    //根据newHeroNode的no来修改即可
    public void update(HeroNode newHeroNode){
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }

        //找到需要修改的结点,根据no编号
        //先定义一个辅助变量
        HeroNode temp = head.next;
        boolean flag = false;   //表示是否找到该结点
        while (true) {
            if (temp == null){
                break;    //已经遍历完链表了
            }

            if (temp.no == newHeroNode.no){
                //说明已经找到了
                flag = true;
                break;
            }
            temp = temp.next;
        }

        //根据flag,判断是否找到要修改的结点
        if (flag){
            temp.name = newHeroNode.name;
            temp.nickName = newHeroNode.nickName;
            //这里newHeroNode.next传的是null
//            temp.next = newHeroNode.next;
        } else {  //说明没找到
            System.out.printf("没有找到编号%d的结点,不能修改\n",newHeroNode.no);
        }
    }

    //删除结点,通过编号删除
    public void deleteNode(int no){

        if (head.next == null){
            System.out.println("空链表");
            return;
        }

        HeroNode temp = head;
        Boolean flag = false;
        while (true) {
            if (temp == null){
                break;
            }

            if (temp.next.no == no){

                flag = true;
                break;
            }

            temp = temp.next;
        }

        if (flag) {
            temp.next = temp.next.next;
        } else {
            System.out.println("链表为空");
        }
    }

    //显示链表[遍历]
    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 = temp.next;
        }
    }
}

//先定义一个Hero,每个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;
    }

    //为了显示方便,重写toString();
    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +

                '}';
    }
}

 

posted @ 2020-11-14 14:19  suke_123  阅读(306)  评论(0编辑  收藏  举报