zoukankan      html  css  js  c++  java
  • 双向链表原理及应用举例

    双向链表

    双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

    图示1:

     图示2:

    分析:

     1.遍历与修改实现方式与单链表一致

     2.添加(默认添加到双向链表最后)

      (1)先找到双向链表的最后一个节点

      (2)temp.next=HeroNode2; //对本例的条件

      (3)HeroNode2.pre=temp;

     3.删除

      (1)因为是双向链表,我们可以实现自我删除某个节点,直接找到我们要删除的节点,比如temp

      (2)temp.pre.next=temp.next; //对本例的条件

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

    应用举例

    使用带head头节点的双向链表实现水浒英雄排行榜

    代码

    package com.atxihua;
    
    public class DoubleLinkedListDemo {
        public static void main(String[] args) {
            System.out.println("双向链表测试");
            //创建节点
            HeroNode2 hero4=new HeroNode2(4,"林冲","豹子头");
            HeroNode2 hero3=new HeroNode2(3,"吴用","智多星");
            HeroNode2 hero2=new HeroNode2(2,"卢俊义","玉麒麟");
            HeroNode2 hero1=new HeroNode2(1,"宋江","及时雨");
            //创建一个双向链表
            DoubleLinkedList doubleLinkedList=new DoubleLinkedList();
            doubleLinkedList.add(hero1);
            doubleLinkedList.add(hero2);
            doubleLinkedList.add(hero3);
            doubleLinkedList.add(hero4);
            doubleLinkedList.list();
    
            //修改
            HeroNode2 newHeroNode=new HeroNode2(4,"公孙胜","入云龙");
            doubleLinkedList.update(newHeroNode);
            System.out.println("修改后的双向链表");
            doubleLinkedList.list();
    
            //删除
            doubleLinkedList.del(3);
            System.out.println("链表删除后的情况");
            doubleLinkedList.list();
    
        }
    }
    class HeroNode2{
        public int no;
        public String name;
        public String nickname;
        public HeroNode2 next;//指向下一个节点,默认为null
        public HeroNode2 pre;//指向前一个节点,默认为null
        //构造器
    
        public HeroNode2(int no, String name, String nickname) {
            this.no = no;
            this.name = name;
            this.nickname = nickname;
        }
        //为了显示方便,重新toString
    
        @Override
        public String toString() {
            return "HeroNode2{" +
                    "no=" + no +
                    ", name='" + name + '\'' +
                    ", nickname='" + nickname + '\'' +
                    '}';
        }
    }
    //创建一个双向链表的类
    class DoubleLinkedList{
        //先初始化一个头节点,头节点不要动,不存放具体的数据
        private  HeroNode2 head=new HeroNode2(0,"","");
    
        //返回头节点
        public HeroNode2 getHead() {
            return head;
        }
        //遍历双向链表
        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=temp.next;
            }
        }
        //添加一个节点到双向链表最后
        public  void  add(HeroNode2 HeroNode2){
            //因为头节点不能动,因此我们需要一个辅助变量来遍历
            HeroNode2 temp=head;
            while (true){
                //判断是否到链表最后
                if(temp.next==null){
                    break;
                }
                //如果未找到将temp后移
                temp=temp.next;
            }
            //当退出while循环时,temp就指向了链表的最后
            //形成了一个双向链表
            temp.next=HeroNode2;
            HeroNode2.pre=temp;
        }
        //修改一个节点的内容,与单链表修改相同
        public void update(HeroNode2 newHeroNode2){
            //判空
            if(head.next==null){
                System.out.println("链表为空");
                return;
            }
            //定义一个辅助节点
            HeroNode2 temp=head.next;
            boolean flag=false;//表示是否找到该节点
            while (true){
                if(temp==null){
                    break;//已经遍历完链表
                }
                if(temp.no==newHeroNode2.no){
                    //找到该节点
                    flag=true;
                    break;
                }
                //未找到,后移
                temp=temp.next;
            }
            if(flag){
                temp.name= newHeroNode2.name;
                temp.nickname= newHeroNode2.nickname;
            }else{
                System.err.println("该英雄不存在!!!请检查输入排名是否正确");
            }
        }
    
        /*
        从双向链表中删除一个节点
        * 说明
        * 1.对于双向链表,我们可以直接找到要删除的这个节点
        * 2.找到后,自我删除即可
        * */
        public void del(int no){
            //判空
            if(head.next==null){
                System.out.println("链表为空,无法删除");
                return;
            }
            HeroNode2 temp=head.next;//辅助变量
            boolean flag=false;//标志是否找到删除的节点
            while (true){
                if(temp==null){
                    //已到链表的最后
                    break;
                }
                if(temp.no==no){
                    flag=true;
                    break;
                }
                temp=temp.next;//temp后移,遍历
            }
            if(flag){
                temp.pre.next=temp.next;
                //如果是最后一个节点,就不需要执行下面这句话,否则会出现空指针
                if(temp.next!=null){
                    temp.next.pre=temp.pre;
                }
            }else{
                System.out.println("要删除的节点并不存在");
            }
        }
    }

    运行结果:

    为了更好的看到双向链表的数据结构,我们直接来看新增之后doubleLinkedList里的数据

     可以看到数据结构与双向链表图示1完全一致。

  • 相关阅读:
    深究递归和迭代的区别、联系、优缺点及实例对比
    提高Python运行效率的六个窍门
    C++设计模式——单例模式
    使用Python的turtle库实现七段数码管绘制
    Python 死循环和嵌套循环
    Python 随机数 random
    更改 pandas dataframe 中两列的位置
    Pandas中DataFrame修改列名
    MM 算法与 EM算法概述
    机器学习中的训练集、验证集和测试集
  • 原文地址:https://www.cnblogs.com/ftx3q/p/15702893.html
Copyright © 2011-2022 走看看