完整双向链表

前言

单向链表:只能按照一个方向,从前到后
双向链表:既可以从前走也可以从后走


一、双向链表

package seqlist.doublelink;

/**
 * 双链表类
 */
public class DoubleLinkedList {
    //当前链表中有效的元素个数
    private int size;
    //头节点
    private Node head;
    //尾节点
    private Node tail;
}

/**
 * 双链表的节点类
 */
class  Node{
    Node prev;
    int val;
    Node next;

    //构造方法
    public Node(int val){
        this.val=val;
    }

    public Node (Node prev,int val,Node next) {
        this.prev=prev;
        this.val=val;
        this.next=next;
    }
}

①.插入

1.头插法

 public void addFist(int val){
        Node node =new Node(null,val,head);
        //链表为空
        if (head==null){

            tail=node;
        }else {
            head.prev = node;
        }
        head=node;
        size++;
    }

2.尾插法

 //尾插法
    public void addLast(int val){
        Node node=new Node(tail,val,null);
        if(tail==null){
            head=node;
        }else {
            tail.next=node;
        }
        tail=node;
        size++;
    }

3.※找到前驱节点

/**
     * 找到index索引对应的节点
     * @param index
     * @return index对应的节点Node
     */
    private Node node(int index) {
        Node ret=null;
        //index<size的一半(从头找)
        if (index<(size>>1)){
            ret=head;
            for (int i = 0; i < index; i++) {
                ret=ret.next;
            }
        }else {
            //从后向前找
            ret=tail;
            for (int i = size-1; i > index; i--) {
                ret= tail.prev;
            }
        }
        return ret;
    }

4.输出

 @Override
    public String toString() {
       String ret="";
       Node node=head;
       while (node!=null){
           ret+=node.val+"->";
           node=node.next;
       }
       ret+="NULL";
       return ret;
    }

5.中间插

  public void addIndex(int index,int val){
        if (index<0||index>size){
            System.err.println("add index illegal!");
            return;
        }else if (index==0) addFist(val);
        else if (index==size) addLast(val);
        else {
            //在中间位置插入要找到前驱节点
            //找到节点CURD全都要用,抽象成一个方法,快捷键CTRL+enter
            Node prev=node(index-1);
            //连接四根线
            Node newNode=new Node(prev,val,prev.next);
            prev.next.prev=newNode;
            prev.next=newNode;
            size++;
        }
    }

②.查询

1.判断合法性

public boolean rangeIndex(int index){
        if (index<0||index>=size){
             return false;
        }
        return true;
    }

2. get(int index)

 public int get(int index) {
        //合法性
        if (rangeIndex(index)) {
            return node(index).val;
        } else {
            System.err.println("get index illegal");
        }
        return -1;
    }

3.contains(int val)

 public boolean contains(int val){
        for (Node x=head;x!=null;x=x.next){
            if (x.val==val){
                return true;
            }
        }
        return false;
    }

③.修改

1.set(int index,int newVal)

/**
     * 根据index修改之前的元素
     * @param index
     * @param newVal
     * @return 修改前的值
     */
    public int set(int index,int newVal){
        if (rangeIndex(index)){
            Node node =node(index);
            int oldVal= node.val;;
            node.val=newVal;
            return oldVal;
        }else{
            System.err.println("set index illegal!");
            return -1;
        }

③.删除

删除具体节点//将node节点从当前双向链表中删除
private void unlink(Node node) { } ;

1.※unlink(Node node):分治思想

 /**
     * 删除链表中指定的节点
     * @param node
     */
    private void unlink(Node node) {
        //分治思想
        Node prev=node.prev;
        Node next=node.next;
        //先处理前驱节点
        if (prev==null){
            //此时是个头节点
            head=next;
        }else {
            prev.next=next;
            node.prev=null;
        }
        //此时处理后继节点
        if (next==null){
            //此时要删除的是个尾节点
            tail=prev;
        }else{
            next.prev=prev;
            node.next=null;
        }
        size--;
    }

2.removeIndex(int index)等

 public void removeIndex(int index){
        if (rangeIndex(index)){
            Node node =node(index);
            unlink(node);
        }else{
            System.err.println("remove index illegal!");
        }
    }
    
    public void removeFirst(){
        removeIndex(0);
    }
    
    public  void removeLast(){
        removeIndex(size-1);
    }

3.removeValueOnce(int val)

public void removeValueOnce(int val){
        for (Node x=head;x!=null;x=x.next){
            if (x.val==val){
                unlink(x);
                break;
            }
        }
    }

4.※removeValueAll(int val)

  public void removeValueAll(int val){
        //注意,因为上面写的删除方法指向空
        //因此,删除之前需要暂存一下下一个节点的地址
        for (Node x=head;x!=null;x=x.next){
            if (x.val==val){
                Node next =x.next;
                //删除之后,x.next=x.prev=null
                unlink(x);
                x=next;
            }else {
                x=x.next;
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值