java 双向不带头不循环链表

本链表值实现基本的增删查改功能,可以在符合逻辑情况下增加其他方法

一.接口的实现

可以将链表的代码放在接口中,便于阅读链表方法和随时增删查改部分功能,而且只要实现了该接口可以对方法进行重写实现

public interface SingleLinkedList {
//------------------------------------增-----------------------------
    //头插
    void addFirst(int value);
    //尾插
    void addEnd(int value);
    //中插
    void addIndex(int pos,int value);
//------------------------------------删-----------------------------
    //删除遇到的第一个该元素
    void remove(int value);
    //删除全部该元素
    void removeAll(int value);

//------------------------------------查-----------------------------
    //查找某个元素是否存在
    boolean contains(int key);
//------------------------------------改-----------------------------
    //将某个元素改值
    void set(int key,int value);
//------------------------------------其他-----------------------------
    //统计链表长度
    int size();
    //清空链表
    void clear();
    //打印链表
    void display();
}

二.代码实现

内部类:

         当⼀个事物的内部,还有⼀个部分需要⼀个完整的结构进⾏描述,⽽这个内部的完整的结构⼜只为外部事物提供服务,那么这个内部的完整结构最好使⽤内部类
而这里链表的实现需要结点,而结点是个完整的结构又为链表提供服务,可以定义内部类

public class MyDLinkedList implements DLinkedList {
    static class DListNode {
        public int value;
        //存储前一个结点的引用
        public DListNode prev;
        public DListNode next;

        public DListNode(int value) {
            this.value = value;
        }
    }

    //存储第一个结点 左后一个结点的引用
    public DListNode pHead;
    public DListNode pLast;
//---------------------------------------------增---------------
    @Override
    public void addFirst(int value) {
        DListNode dListNode = new DListNode(value);
        if(pHead == null){
            pHead = pLast = dListNode;
            return;
        }
        dListNode.next = pHead;
        pHead.prev = dListNode;
        pHead = pHead.prev;
    }

    @Override
    public void addEnd(int value) {
        DListNode dListNode = new DListNode(value);
        if(pHead == null){
            pHead = pLast = dListNode;
            return;
        }
        pLast.next = dListNode;
        dListNode.prev = pLast;
        pLast = pLast.next;
    }
    //检查pos位置是否合理(这里建议引异常)
    private void checkPosIllegality(int pos){
        if(pos < 0 || pos >this.size()){
            throw new PosIllegalityException("addIndex方法下标异常>:"+pos);
        }
    }
    // 寻找下标的位置
    private DListNode searchPosReturnNode(int pos){
        DListNode cur = pHead;
        while(pos != 0){
            cur = cur.next;
            pos--;
        }
        return cur;
    }
    @Override
    public void addIndex(int pos, int value) {
        DListNode dListNode = new DListNode(value);
        // 1.检查pos位置是否合理(这里建议引异常)
        checkPosIllegality(pos);
        if(pos == 0){
            this.addFirst(value);
            return;
        }
        // 2.寻找下标的位置
        DListNode posReturnNode = searchPosReturnNode(pos);
        //这里注意,双向链表当前位置能找到前一个元素,
        // 所以 posReturnNode 可能为null,此时 .prev就会出错
        // 3.判断
        if(posReturnNode == null){
            this.addEnd(value);
            return;
        }
        // 4.插入
        posReturnNode.prev.next = dListNode;
        dListNode.prev = posReturnNode.prev;
        dListNode.next = posReturnNode;
        posReturnNode.prev = dListNode;
    }
//---------------------------------------------删---------------
    //寻找元素
    private  DListNode searchElemReturnNode(int key){
        DListNode cur = pHead;
        while(cur != null){
            if(cur.value == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
    }
    @Override
    public void remove(int key) {
        if(pHead == null){
            System.out.println("链表为空");
            return;
        }
        DListNode cur = pHead;
        while(cur != null){
            // 判断是否相等
            if(cur.value == key){
                //判断是否为第一个结点
                if(cur == pHead){
                    // pHead 向后移
                    pHead = pHead.next;
                    //这里注意 链表 可能只有一个节点
                    //为 null 不管
                    //不为空  则把 Phead 的 prev置为 null
                    if(pHead != null){
                        pHead.prev = null;
                    }
                }else{
                    cur.prev.next = cur.next;
                    // 判断 是否为最后一个结点
                    if(cur.next == null){
                        pLast = pLast.prev;
//                        cur.prev.next = cur.next;
                    }else{
                        //否则 就是删除中间的结点
//                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }
                }
                //删除了就退出
                return;
            }
            cur = cur.next;
        }
    }

    @Override
    public void removeAll(int key) {
        if(pHead == null){
            System.out.println("链表为空");
            return;
        }
        DListNode cur = pHead;
        while(cur != null){
            // 判断是否相等
            if(cur.value == key){
                //开始删除
                //判断是否为第一个结点
                if(cur == pHead){
                    // pHead 向后移
                    pHead = pHead.next;
                    //这里注意 链表 可能只有一个节点
                    //为 null 不管
                    //不为空  则把 Phead 的 prev置为 null
                    if(pHead != null){
                        pHead.prev = null;
                    }
                }else{
                    cur.prev.next = cur.next;
                    // 判断 是否为最后一个结点
                    if(cur.next == null){
                        pLast = pLast.prev;
//                        cur.prev.next = cur.next;
                    }else{
                        //否则 就是删除中间的结点
//                        cur.prev.next = cur.next;
                        cur.next.prev = cur.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }
//---------------------------------------------查---------------
    @Override
    public boolean contains(int value) {
        if(pHead != null){
            return false;
        }
        DListNode cur = pHead;
        while(cur != cur){
            if(cur.value == value){
                return true;
            }
            cur = cur.next;
        }
        return false;
    }
//---------------------------------------------改---------------
    private  void checkSetPosIllegality(int pos){
        if(pos < 0 || pos >=this.size()){
            throw  new PosIllegalityException("set方法下标不合理"+pos);
        }
    }
    @Override
    public void set(int pos, int value) {
        // 判断下标异常
        checkSetPosIllegality(pos);
        // 找到下标的结点
        DListNode cur = pHead;
        while(pos != 0){
            cur = cur.next;
            pos--;
        }
        cur.value = value;
    }
//--------------------------------------------其他---------------
    @Override
    public int size() {
        int count = 0;
        DListNode cur = pHead;
        while(cur != null){
            count++;
            cur = cur.next;
        }
        return count;
    }

    @Override
    public void clear() {
        //仿照单链表的清除
        DListNode cur = pHead;
        while(cur != null){
            DListNode curN = cur.next;
            cur.value = 0;
            cur.prev = null;
            cur.next = null;
            cur = curN;
        }
        pHead = pLast = null;
    }

    @Override
    public void display() {
        DListNode cur = pHead;
        while(cur != null){
            System.out.print(cur.value+"-->");
            cur = cur.next;
        }
        System.out.print("null");
    }
}

这里检查下标pos的合法性,要引入异常:

public class SingListPosIllegality extends RuntimeException {
    public SingListPosIllegality() {
    }

    public SingListPosIllegality(String message) {
        super(message);
    }
}

三.运行

1.运行该代码
public class test {
    public static void main(String[] args) {
        MyDLinkedList myDLinkedList = new MyDLinkedList();
        //尾插
        myDLinkedList.addEnd(1);
        myDLinkedList.addEnd(2);
        myDLinkedList.addEnd(3);
        myDLinkedList.addEnd(4);
        myDLinkedList.addEnd(5);
        myDLinkedList.display();
        //头插
        myDLinkedList.addFirst(1);
        myDLinkedList.addFirst(2);
        myDLinkedList.addFirst(3);
        myDLinkedList.addFirst(4);
        myDLinkedList.addFirst(5);
        myDLinkedList.display();
        //中插
        System.out.println();
        myDLinkedList.addIndex(2,10086);
        myDLinkedList.display();
        //移除
        System.out.println();
        myDLinkedList.remove(4);
        myDLinkedList.display();

        //移除全部
        System.out.println();
        myDLinkedList.removeAll(4);
        myDLinkedList.display();

        //判断某个元素是否存在
        System.out.println();
        System.out.print(myDLinkedList.contains(6));

        //修改下标的值
        System.out.println();
        myDLinkedList.set(2,10000);
        myDLinkedList.display();

        myDLinkedList.clear();
    }
}
2.运行截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值