假期结束,接着来吧!双向链表

我与影子孤独终老i 提交于 2020-01-02 16:23:19

双向链表

双向链表与单向链表的比较

  1. 单向链表查找方向只能是一个方向,双向链表的可以向前也可以向后
  2. 单向链表是不可以自我删除的,需要靠辅助节点,并且总要找到待删除节点的前一个结点,双向链表是可以自我删除的

常规操作

双向链表的尾部添加

思路分析
  1. 找到双向链表的最后节点,同单向链表的遍历方式
  2. temp.next = new node
  3. new node.pre = temp;
  4. 尾节点的后继指针后指,新节点的前继指针前指
代码实现

我的代码:

package linkedlist;

public class DoubleLinkedKist {
    public static void main(String[] args) {
        DLL d1 = new DLL();
        Hero h1 = new Hero(1,"旁边的","打字砸键盘");
        Hero h2 = new Hero(2,"peach","canyouhear");
        Hero h3 = new Hero(3,"fulck","bi1qusi1");
        Hero h4 = new Hero(4,"haona1","zhenwuyua");
        d1.add(h1);
        d1.add(h2);
        d1.add(h3);
        d1.add(h4);
        d1.show();
    }
}
class DLL{
    private Hero head = new Hero(1,"","");
    public void add(Hero hero){
        Hero temp = head;
        while (true){
            if(temp.next == null){
                break;
            }
            //在这里注意,尾节点的判定,不是本身是空的
            //而是看他的next是否为空,show方法输出的时候可以直接判定本身是否为空
            temp = temp.next;
        }
        temp.next = hero;
        hero.pre = temp;
    }
    public void show(){
        if(head.next == null){
            System.out.println("链表为空");
        }
        Hero temp = head.next;
        while (temp != null){
            System.out.println(temp);
            temp = temp.next;
        }

    }
}
class Hero{
    private int no;
    private String name;
    private String nickName;
    Hero pre;
    Hero next;

    @Override
    public String toString() {
        return "Hero{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }

    public Hero(int no, String name, String nickName) {
        this.no = no;
        this.name = name;
        this.nickName = nickName;

    }
}

双向链表的删除

思路分析
  1. 自我删除,无需找到待删除结点的前一个结点
  2. 直接找到待删除结点
  3. temp.pre.next = temp.next
  4. temp.next.pre = temp.pre
代码实现:

我的代码:

  public int getLength(){
        int size = 0;
        Hero temp = head.next;
        while (temp != null){
            size ++;
            temp = temp.next;
        }
        return size;
    }
    public void delete(int no){
        Hero temp = head;
        if(temp.next == null){
            System.out.println("链表为空");
        }
        int size = getLength();
        if(no <= 0 || no > size){
            System.out.println("输入的索引无效");
        }
        boolean isFlag = false;
        while (true){
            if(temp == null){
                isFlag = true;
                break;
            }
            if(temp.no == no){
                break;
            }
            temp = temp.next;
        }
        if(isFlag){
            System.out.println("你要删除的节点不存在");
        }else{
            temp.pre.next = temp.next;
            temp.next.pre = temp.pre;
        }

    }

修改:

if(isFlag){
            System.out.println("你要删除的节点不存在");
        }else{
            temp.pre.next = temp.next;
            temp.next.pre = temp.pre;
        }

如果删除的是最后一个节点,会出现空指针异常,所以应该加一个判断语句,判断是否为最后一个节点

if(isFlag){
            System.out.println("你要删除的节点不存在");
        }else{
            temp.pre.next = temp.next;
            if(temp.next != null){
                 temp.next.pre = temp.pre;
            }
        }
总结
  1. 作为链表本身就带有的方法,我们在调用其本身的方法时,没必要在传入头指针
  2. 链表操作自身,作为已知元素,也是没必要判定是否为空链表的
  3. 代码太过冗余和麻烦
  4. 没码一个代码块,想清楚每一个代码块的要素,while循环语句,初始条件,循环体,迭代条件,终止条件,每一次都会漏
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!