数据结构-双向链表

数据结构-双向链表

为什么要有双向链表?

单向链表的缺点分析:

1) 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。

2) 单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除,所以前面我们单链表删除 时节点,总是找到 temp,temp 是待删除节点的前一个节点(认真体会). 

 

 分析 双向链表的遍历,添加,修改,删除的操作思路===》代码实现

1) 遍历 方和 单链表一样,只是可以向前,也可以向后查找

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

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

  (2)temp.next=newHeroNode

  (3)newHeroNode.pre=temp;

3) 修改 思路和 原来的单向链表一样.

4) 删除

  (1) 因为是双向链表,因此,我们可以实现自我删除某个节点

  (2) 直接找到要删除的这个节点,比如 temp

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

   (4)temp.next.pre=temp.pre; //这里需要判断temp.next != null

 

添加节点

(1)直接添加到链尾

 

(2)按照顺序插入

 

删除节点

源码

package com.orz.LinkList;

/**
 * @author orz
 * @create 2020-10-24 22:11
 */
public class DoubleLinkedListTest {
    public static void main(String[] args) {
        DoubleLinkedList link=new DoubleLinkedList();
        HeroSingleNode node1=new HeroSingleNode(1,"宋江","及时雨");
        HeroSingleNode node2=new HeroSingleNode(2,"吴用","智多星");
        HeroSingleNode node3=new HeroSingleNode(3,"林冲","豹子头");
        HeroSingleNode node4=new HeroSingleNode(4,"李逵","黑旋风");
        DoubleLinkedList link2=new DoubleLinkedList();
        //不按顺序添加测试
        link2.add(node4);
        link2.add(node2);
        link2.add(node1);
        link2.add(node3);
        System.out.println("直接添加到链尾");
        DoubleLinkedList.showHeroLink(link2);
        System.out.println("-------------------------------------------------------");
        //按顺序添加测试
        link.addHeroNodeOrderById(node3);
        link.addHeroNodeOrderById(node2);
        link.addHeroNodeOrderById(node1);
        link.addHeroNodeOrderById(node4);
        System.out.println("按顺序添加");
        DoubleLinkedList.showHeroLink(link);
        System.out.println("-------------------------------------------------------");


        HeroSingleNode newnode4=new HeroSingleNode(4,"李xx","黑xx");
        link.updateHeroNode(newnode4);
        System.out.println("修改节点信息");
        DoubleLinkedList.showHeroLink(link);
        System.out.println("-------------------------------------------------------");

        link.deleteHeroNodeById(1);
        System.out.println("删除节点1");
        DoubleLinkedList.showHeroLink(link);
        System.out.println("-------------------------------------------------------");
    }
}

class DoubleLinkedList{
    private HeroSingleNode head=new HeroSingleNode(0,null,null);

    public HeroSingleNode getHead() {
        return head;
    }

    //遍历双向链表,跟单链表一样
    public static void showHeroLink(DoubleLinkedList link) {
        if (link.head.next == null) {
            System.out.println("链表为空!!!");
            return;
        }
        HeroSingleNode temp = link.head.next;
        while (temp != null) {
            System.out.println(temp);
            temp = temp.next;
        }
    }

    //添加节点
    //第一种,默认添加到链尾
    public void add(HeroSingleNode node)
    {
        //因为head不能动,所以需要一个辅助节点变量
        HeroSingleNode temp = head;
        //标记待添加的节点是否已经存在
        boolean flag = false;
        //遍历链表,找到最后
        while (true) {
            //如果节点的next为空说明该节点就是最后一个节点
            if (temp.next == null) {
                break;
            }
            if (temp.next.id == node.id) {
                flag = true;
                break;
            }
            //否则指针下移
            temp = temp.next;
        }

        if (flag) {
            System.out.println("添加失败,需要添加id为"+node.id+"的节点已经存在了!!!");
            return;
        }
        //加入新节点,双向建立联系
        temp.next = node;
        node.pre=temp;
    }
    /**
     * 添加节点信息,第二种:根据排名将英雄插入到指定位置,按照id从小到大排序
     */
    public void addHeroNodeOrderById(HeroSingleNode node) {
        //如果还没有任何一个节点,直接插入到head后面
        if (head.next == null) {
            //建立双向联系
            head.next = node;
            node.pre=head;
            return;
        }
        //因为头节点不能动,所以我们仍然通过一个辅助指针(变量)来帮助找到添加的位置
        HeroSingleNode temp = head;
        //标记待添加的节点是否已经存在
        boolean flag = false;

        while (true) {
            //说明 temp 已经在链表的最后一个了
            if (temp.next == null) {
                break;
            }
            //节点已经存在
            if (temp.next.id == node.id) {
                flag = true;
                break;
            }
            //位置找到,就在 temp 的后面插入
            if (temp.next.id > node.id) {
                break;
            }

            temp = temp.next;
        }

        if (flag) {
            System.out.println("添加失败,需要添加id为" + node.id + "的节点已经存在了!!!");
        }
        else {
            //插入的节点与temp的下一个节点建立联系
            if (temp.next != null) {
                temp.next.pre=node;
            }
            node.next=temp.next;
            //插入的节点与temp建立联系
            node.pre=temp;
            temp.next=node;
        }

    }

    /**
     * 修改链表节点数据,id不要动,跟单链表一样
     */
    public void updateHeroNode(HeroSingleNode node)
    {
        if(head.next==null)
        {
            System.out.println("链表为空");
            return;
        }
        HeroSingleNode temp=head.next;
        boolean flag=false;
        while (true)
        {
            if(temp==null)
            {
                break;
            }
            if(temp.id==node.id)
            {
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if (flag)
        {
            temp.heroName=node.heroName;
            temp.nikeName=node.nikeName;
        }
        else
        {
            System.out.println("id为"+node.id+"的节点不存在!!!");
        }
    }

    /**
     * 删除节点
     * //1.head 不能动,因此我们需要一个 temp 辅助节点找到待删除节点的
     * //2. 说明我们在比较时,是 temp.id 和 需要删除的节点的 id 比较
     */
    public void deleteHeroNodeById(int id)
    {
        if(head.next==null)
        {
            System.out.println("链表为空");
            return;
        }
        HeroSingleNode temp=head.next;
        // 标志是否找到待删除节点的
        boolean flag=false;
        while (true)
        {
            //已经到了链表最后一个的next
            if(temp==null)
            {
                break;
            }
            if(temp.id==id)
            {
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if(flag)
        {
            //temp的前一个节点和后一个节点建立联系
            temp.pre.next=temp.next;
            //这里可能有问题,如果删除最后一个节点
            if (temp.next!=null) {
                temp.next.pre=temp.pre;
            }
        }
        else
        {
            System.out.println("链表中没有id为"+id+"的节点数据");
        }
    }

}
class HeroSingleNode{
    public int id;
    //英雄名
    public String heroName;
    //英雄昵称
    public String nikeName;

    //next域
    public HeroSingleNode next;
    //指向前一个节点
    public HeroSingleNode pre;

    public HeroSingleNode() {
    }

    public HeroSingleNode(int id, String heroName, String nikeName) {
        this.id = id;
        this.heroName = heroName;
        this.nikeName = nikeName;
    }

    @Override
    public String toString() {
        return "HeroSingleNode{" +
                "id=" + id +
                ", heroName='" + heroName + '\'' +
                ", nikeName='" + nikeName + '\'' +
                '}';
    }
}
View Code

 

posted @ 2020-10-25 09:46  orz江小鱼  阅读(212)  评论(0编辑  收藏  举报