链表(双向链表)

链表(双向链表)

需求

单向链表:查找方向只能是一个方向,即通过next域去查找下一个节点,单向链表删除时,也不能自动删除,在前面单向链表中由于我们只能通过next域向后查找,所以在很多操作时需要借助辅助变量(节点)temp去找删除节点的前一个节点进行操作。

双向链表:可以向前或向后查找,提供两个方向的查找,双向链表也可以提供自动删除

思路分析

在节点中新增一个变量指向前一个节点,使得链表成为双向链表。

class Node3 {
    public int no;
    public String name;
    public Node3 next;//指向下一个节点,默认为null
    public Node3 pre;//指向上一个节点,默认为null
    //构造器
    public Node3(int no, String name){
        this.no=no;
        this.name=name;
    }

    @Override
    public String toString() {
        return "Node3{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';//不加next域,否则会把后面的节点打出
    }
}

链表的增,删,改,查

双向链表添加
(默认添加到链表最后)
同单向链表先找到双向链表最后一个节点temp

temp.next=newnode3;
newnode3.pre=temp;

代码实现(方法段)

public void addDLL(Node3 node3) {
        Node3 temp = head;//因为head节点不能动,所以另外定义一个变量,将head节点赋给它
        //进行遍历找到链表的最后一个节点
        boolean flag = false;//flag表示节点是否存在,默认为flase(加入节点是否与原有节点相同)
        while (true) {
            if (temp.next == null)
                break;
            if (temp.next.no > node3.no)//因为链表只能后接所以与要添加变量比较序号的是temp.next而不是temp
                break;
            else if (temp.next.no == node3.no) {
                flag = true;//序号存在
                break;
            }
            temp = temp.next;
        }
        //退出while循环时,temp就指向了链表最后
        temp.next=node3;
        node3.pre=temp;
        //实现链表的双向连接
        }

    }

双向链表修改
双向链表的修改与单向链表一样,依序号找到后修改即可

双向链表删除
因为是双向链表,因此可以实现自我删除某个节点,例找到待删除节点temp

temp.next.pre=temp.pre;
temp.pre.next=temp.next;

代码实现(方法段)

public void delete(int no){
        Node3 temp=head.next;
        boolean isFind=false;
        if(temp==null){
            System.out.println("链表为空,无法删除");
        }
        while (true){
            if(temp.next==null){
                break;
            }
            if (temp.no==no){
                isFind=true;
                break;
            }
            temp=temp.next;
        }
        if(isFind){
            temp.pre.next=temp.next;
            //注意当temp是最后一个节点时,temp.next.pre将会出现空指针异常
            //所以另一段删除部分需要一定的条件
            if (temp.next!=null){
                temp.pre.next=temp.next;
            }
        }else{
            System.out.println("未找到序号所对应的节点,删除失败");
        }
    }

(代码实现)整体部分

package datastructure;
//双向链表
public class linkedIist3 {
    public static void main(String[] args) {
        //双向链表的测试
        Node3 node1=new Node3(1,"一号") ;
        Node3 node2=new Node3(2,"二号") ;
        Node3 node3=new Node3(3,"三号") ;
        Node3 node4=new Node3(4,"四号") ;
        Node3 node5=new Node3(5,"五号") ;
        //创建链表
        Doublielinklist Dlink=new Doublielinklist();

        //所添加数据按照序号排列
        Dlink.addDLL(node1);
        Dlink.addDLL(node2);
        Dlink.addDLL(node3);
        Dlink.addDLL(node4);
        Dlink.addDLL(node5);

        //测试节点
        Node3 Tnode=new Node3(2,"贰号") ;
        Dlink.update(Tnode);
        Dlink.delete(4);

        //显示列表
        Dlink.show();

    }
}
class Doublielinklist{
    private Node3 head=new Node3(0,"");
    //返回头节点
    public Node3 getHead(){
        return head;
    }
    //展示链表
    public void show() {
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        //head节点不能动
        Node3 temp = head.next;
        while (true) {
            if (temp == null) {
                break;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }
    public void addDLL(Node3 node){
        Node3 temp=head;//因为head节点不能动,所以另外定义一个变量,将head节点赋给它
        //进行遍历找到链表的最后一个节点
        while(true){
            if(temp.next==null)
                break;
            temp=temp.next;
        }
        //将新节点接到原链表尾,新的节点代替了null
        temp.next=node;
        node.pre=temp;

    }
    public void update(Node3 newNode){
        Node3 temp=head.next;
        if (temp==null){
            System.out.println("链表为空");
        }
        //更新(修改)链表节点前先找到该节点
        boolean flag=false;//定义一个变量表示是否更新节点是否在链表内
        while (true){
            if (temp==null)
                break;
            if (temp.no==newNode.no){
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if (flag){
            temp.name=newNode.name;
        }else{//没有找到节点
            System.out.println("未找到该节点,无法修改");
        }
    }
    public void delete(int no){
        Node3 temp=head.next;
        boolean isFind=false;
        if(temp==null){
            System.out.println("链表为空,无法删除");
        }
        while (true){
            if(temp.next==null){
                break;
            }
            if (temp.no==no){
                isFind=true;
                break;
            }
            temp=temp.next;
        }
        if(isFind){
            temp.pre.next=temp.next;
            //注意当temp是最后一个节点时,temp.next.pre将会出现空指针异常
            //所以另一段删除部分需要一定的条件
            if (temp.next!=null){
                temp.pre.next=temp.next;
            }
        }else{
            System.out.println("未找到序号所对应的节点,删除失败");
        }
    }

    }
class Node3 {
    public int no;
    public String name;
    public Node3 next;//指向下一个节点,默认为null
    public Node3 pre;//指向上一个节点,默认为null
    //构造器
    public Node3(int no, String name){
        this.no=no;
        this.name=name;
    }

    @Override
    public String toString() {
        return "Node3{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';//不加next域,否则会把后面的节点打出
    }


}
上一篇:Git简单部署


下一篇:Hadoop完全分布模式的搭建