Lista enlazada bidireccional de estructura de datos y algoritmo

Lista enlazada bidireccional de estructura de datos y algoritmo

Para listas con enlaces individuales, consulte mi otra publicación de blog
https://blog.csdn.net/hcyxsh/article/details/114101200

1. Análisis operativo y realización de lista doblemente enlazada

Utilice una lista doblemente enlazada con cabeza para lograr la clasificación de héroe de margen de agua

Análisis de las desventajas de administrar listas enlazadas individualmente:

  1. En el caso de listas con enlaces simples, la dirección de búsqueda solo puede ser una dirección, mientras que las listas con enlaces dobles se pueden buscar hacia adelante o hacia atrás.

  2. Una lista enlazada individualmente no se puede eliminar por sí misma y necesita depender de un nodo auxiliar, mientras que una lista enlazada doble se puede borrar por sí misma, por lo que cuando eliminamos una lista enlazada individualmente, siempre encontramos temp, que es el nodo anterior de la lista. nodo que se eliminará (comprenda con cuidado).

  3. Se analizó cómo completar el recorrido, agregar, modificar y eliminar la lista doblemente enlazada
    Inserte la descripción de la imagen aquí
    . Explicación de la figura anterior:

Analice el recorrido, agregue, modifique y elimine las ideas de operación de la lista doblemente vinculada === "implementación de código

  1. La parte transversal es la misma que la lista enlazada individualmente, excepto que se puede buscar hacia adelante o hacia atrás.

Agregue uno (el valor predeterminado se agrega al final de la lista doblemente vinculada)

(1) Primero busque el último nodo de la lista doblemente enlazada

(2) temp.next = newHeroNode

(3) newHeroNode.pre = temp;
agregar dos: agregar ordenadamente
(1) encontrar el siguiente nodo agregado
(2) determinar la relación de tamaño del número de serie

heroNode.next = temp.next;
if (temp.next! = null) {// El primero y el último, habrá una excepción de puntero nulo
temp.next.pre = heroNode;
}
temp.next = heroNode;
heroNode. pre = temp;

  1. La idea de modificación es la misma que la lista original enlazada individualmente.

  2. Eliminar

(1) Debido a que es una lista doblemente vinculada, podemos eliminar un nodo por nosotros mismos

(2) Busque el nodo que se eliminará directamente, como temp

(3) temp.pre.next = temp.next

(4) temp.next.pre = temp.pre;

2. Implementación del código de lista doblemente enlazada

package com.datastrucate.linkedlist;

/**
 * ClassName:SingleLinkedList
 * Package:com.datastrucate.linkedlist
 * Description:
 * 用水浒传英雄模拟单链表的CRUD
 *
 * @Date:2021/2/25 17:01
 * @Author:hm
 */
public class DoubleLinkedListDemo {
    
    

    public static void main(String[] args) {
    
    

        //先创建节点

        HeroNode2 hero1 = new HeroNode2(1, "宋江", "及时雨");

        HeroNode2 hero2 = new HeroNode2(2, "卢俊义", "玉麒麟");

        HeroNode2 hero3 = new HeroNode2(3, "吴用", "智多星");

        HeroNode2 hero4 = new HeroNode2(4, "林冲", "豹子头");

        //创建链表
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();

//     	doubleLinkedList.add(hero1);
//
//        doubleLinkedList.add(hero4);
//
//        doubleLinkedList.add(hero2);
//
//    	doubleLinkedList.add(hero3);

        doubleLinkedList.addOrder(hero1);

        doubleLinkedList.addOrder(hero4);
//
        doubleLinkedList.addOrder(hero2);

        doubleLinkedList.addOrder(hero3);

    	//显示链表
        doubleLinkedList.list();

//        doubleLinkedList.update(new HeroNode2(1,"宋小江","及时雨"));
//        System.out.println("更新后");
//        doubleLinkedList.list();
//
//        doubleLinkedList.delete(1);
//        System.out.println("删除后");
//        doubleLinkedList.list();


    }

}

//单链表类
class DoubleLinkedList{
    
    

    private HeroNode2 head = new HeroNode2(0,"","");//头结点,不带数据,不可移动

    //获取头结点
    public HeroNode2 getHead() {
    
    
        return head;
    }

    /**
     * 添加方法一:不带顺序的添加,添加到末尾
     */
    public void add(HeroNode2 heroNode){
    
    

        HeroNode2 temp = head;//临时节点,用于避免移动头结点
        //遍历到节点末尾
        while(true){
    
    

            if (temp.next == null){
    
    //空链表,可以添加
                break;
            }
            //没找到,指针后移
            temp = temp.next;
        }
        //退出循环代表,此时temp指针在最后面
        //添加新节点到最后面
        temp.next = heroNode;
        heroNode.pre = temp;

    }

    /**
     * 第二种添加:
     * 带顺序添加
     */
    public void addOrder(HeroNode2 heroNode){
    
    

        //temp  是位于 添加位置的前一个节点
        HeroNode2 temp = head;//临时节点,用于避免移动头结点
        boolean flag = true ;//用于标记可以添加
        //遍历
        while (true){
    
    
            if (temp.next == null){
    
    //空链表
                break;
            }
            if (temp.next.no > heroNode.no){
    
    //序号在temp下一个节点前,能添加

                break;
            }else if (temp.next.no == heroNode.no){
    
    //序号存在,不能添加
                flag = false;
                break;
            }
            //指针后移
            temp = temp.next;
        }
        //判断flag
        if (flag){
    
    //可以添加


            //以第一节点为例:temp.next=null
            heroNode.next = temp.next;
            if (temp.next != null){
    
    //第一个和最后一个,会出现空指针异常

                temp.next.pre = heroNode;
            }
            temp.next = heroNode;
            heroNode.pre = temp;

        }else {
    
    //不能添加

            System.out.println("链表已经存在该英雄,不能添加");
        }

    }

    /**
     * 更新节点
     *
     */
    public void update(HeroNode2 heroNode){
    
    

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

        HeroNode2 temp = head.next;//头节点的后一节点
        boolean flag = false;//用于标记是否更新
        //遍历
        while (true){
    
    

            if (temp == null){
    
    //空链表
                break;
            }
            if (temp.no == heroNode.no){
    
    //更新
                flag = true;
                break;
            }

            //指针后移
            temp = temp.next;
        }
        //更新
        if (flag){
    
    

            temp.name = heroNode.name;
            temp.nickname = heroNode.nickname;
        }else {
    
    
            System.out.println("没有找到编号为"+heroNode.no+"的英雄");
        }
    }

    /**
     * 删除节点
     * 思路
     * 1. head 不能动,因此我们需要一个 temp 辅助节点找到待删除节点
     * 2. 说明我们在比较时,是 temp.no 和 需要删除的节点的 no 比较
     * 注意:删除最后一个节点的空指针问题
     */
    public void delete(int no){
    
    

        if (head.next == null){
    
    
            System.out.println("链表为空");
        }
        HeroNode2 temp = head.next;
        Boolean flag = false;//用于判断是否可删除
        while(true){
    
    
            if (temp == null){
    
    
                break;
            }
            if (temp.no == no ){
    
    
                flag = true;
                break;
            }
            //节点指针后移
            temp = temp.next;
        }
        //删除
        if (flag){
    
    

            temp.pre.next = temp.next;
            if (temp.next != null){
    
    //最后一个节点temp.next=null,避免出现空指针异常

                temp.next.pre = temp.pre;
            }

        }else {
    
    
            System.out.println("不存在该节点,不能删除");
        }
    }


    /**
     * 显示所有节点信息
     */
    public void list(){
    
    

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

        HeroNode2 temp = head.next;//临时节点,用于记录头结点后一节点

        //遍历显示
        while(true){
    
    

            if (temp == null){
    
    //链表为空
                break;
            }

            System.out.println("链表信息为:"+ temp);

            //后移指针
            temp = temp.next;
        }

    }
}

//实体类
class HeroNode2{
    
    
    public int no;//英雄编号
    public String name;//姓名
    public String nickname;//昵称
    public HeroNode2 next;//指向下一节点的指针
    public HeroNode2 pre;//指向前一节点

    public HeroNode2(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 + '\'' +
                '}';
    }
}

Supongo que te gusta

Origin blog.csdn.net/hcyxsh/article/details/114143241
Recomendado
Clasificación