LinkedBox package (linked list)

  • Main function
package com.uncle.linkedbox.src.test;
import com.uncle.linkedbox.src.util.ArrayBox;
import com.uncle.linkedbox.src.util.LinkedBox;

/**
 * 设计一个类    LinkedBox    链表 链式  火车   联络网   小A<-->小B<-->小C<-->小D
 * 		长度看似可以改变
 * 		解决了插入和删除效率低的问题   不适合遍历
 * 	接口-----定义规则
 * 	多态
 */
public class TestMain {
    
    
    public static void main(String[] args){
    
    
        ArrayBox ab = new ArrayBox();
        ab.add(10);
        ab.remove(0);
        ab.get(0);
        ab.size();

        LinkedBox lb = new LinkedBox();
        lb.add(10);
        lb.remove(0);
        lb.get(0);
        lb.size();
    }
}

  • Interface-----define rules
package com.uncle.linkedbox.src.util;

public interface Box {
    
    

    public boolean add(int element);
    public int get(int index);
    public int remove(int index);
    public int size();

}

  • Exception class-----custom exception
package com.uncle.linkedbox.src.util;

public class BoxIndexOutOfBoundsException extends RuntimeException{
    
    

    public BoxIndexOutOfBoundsException(){
    
    }
    public BoxIndexOutOfBoundsException(String msg){
    
    
        super(msg);
    }
}

  • ArrayBox
package com.uncle.linkedbox.src.util;

public class ArrayBox implements Box{
    
    

    //设计一个静态常量 用来存储数组的默认长度
    private static final int DEFAULT_CAPACITY = 10;
    //设计一个自己的属性  用来存放真实数据的  []
    private int[] elementDate;
    //设计一个自己的属性  用来记录数组内存储的有效元素个数
    private int size = 0;

    //构造方法重载
    public ArrayBox(){
    
    
        elementDate = new int[DEFAULT_CAPACITY];
    }
    public ArrayBox(int capacity){
    
    
        elementDate = new int[capacity];
    }


    //小A同学 负责确保数组内部的容量
    private void ensureCapacityInternal(int minCapacity){
    
    
        //判断如果你需要的最小容量比原数组的长度还要大
        if(minCapacity - elementDate.length > 0){
    
    
            //需要进行数组的扩容 找别人计算扩容的大小
            this.grow(minCapacity);
        }
    }
    //小B同学 负责计算扩容大小
    private void grow(int minCapacity){
    
    
        //获取原数组的长度
        int oldCapacity = elementDate.length;
        //小B同学帮我做了一个计算  在原数组之上增加1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //比较计算后的长度与所需的长度
        if(newCapacity - minCapacity < 0){
    
    
            //那么直接按照所需的长度作为新数组的长度
            newCapacity = minCapacity;
        }
        //调用小C同学 让他创建新数组  将原数组中的所有元素移入新数组中
        elementDate = this.copyOf(elementDate,newCapacity);
    }
    //小C同学 负责将原数组中的元素移入新数组中
    private int[] copyOf(int[] oldArray,int newCapacity){
    
    
        //按照提供的长度创建一个新数组
        int[] newArray = new int[newCapacity];
        //将原数组中的元素按照位置移入新数组中
        for(int i=0;i<oldArray.length;i++){
    
    
            newArray[i] = oldArray[i];
        }
        //将新数组返回
        return newArray;
    }
    //小D同学 检测给定index是否合法
    private void rangeCheck(int index){
    
    
        if(index<0 || index>=size){
    
    
            //自定义一个异常 来说明问题
            throw new BoxIndexOutOfBoundsException("Index:"+index+",Size:"+size);
        }
    }

    //------------------------------------------------------------
    //用来将用户给定的element存起来  参数是需要存起来的元素  返回值是否存储成功
    public boolean add(int element){
    
    
        //找一个别人 做事 确保数组的内部容量够用
        this.ensureCapacityInternal(size+1);
        //上述一行代码可以执行完毕 证明elementDate的数组肯定够用
        //直接将新来的element元素存入数组中 并且让size多记录一个
        elementDate[size++] = element;
        //返回true告知用户存储元素成功
        return true;
    }
    //用来获取给定位置的元素  参数是索引位置  返回值是取得的元素
    public int get(int index){
    
    
        //找一个小弟 检测给定的index是否合法
        this.rangeCheck(index);
        //上述代码可以执行  证明index是合法的
        //则找到index对应位置的元素 将其返回
        return elementDate[index];
    }
    //用来删除给定位置的元素  参数是索引位置  返回值是删除掉的那个元素
    public int remove(int index){
    
    
        //调用小D同学 检测index
        this.rangeCheck(index);
        //上述代码可以执行 index是合法的
        //找到index位置的元素 保留起来 留给用户
        int oldValue = elementDate[index];
        //1 2 3 4 5 6   size==6个
        //1 2 4 5 6 0   elementDate[5]=0   size-1
        //从index位置开始至size-1结束 后面元素依次前移覆盖
        for(int i=index;i<size-1;i++){
    
    
            elementDate[i] = elementDate[i+1];
        }
        //手动将最后的元素删除  让size减少一个记录
        elementDate[--size] = 0;
        //将旧数据返回
        return oldValue;
    }
    //设计一个方法 用来获取size有效的个数  没有设置 可以保护size的安全
    public int size(){
    
    
        return size;
    }

}

  • LinkedBox
package com.uncle.linkedbox.src.util;

public class LinkedBox implements Box{
    
    

    //创建几个属性
    private Node first;//记录首节点
    private Node last;//记录尾节点
    private int size;//记录有效元素的个数
    
    //设计一个小A同学  负责将元素添加在新的node里 挂在链表的尾端
    private void linkLast(int element){
    
    
        //获取链表的尾节点
        Node l = last;
        //创建一个新的node对象 将新数据包装起来
        Node newNode = new Node(l,element,null);
        //将新节点对象设置为尾节点
        last = newNode;
        //严谨的判断
        if(l==null){
    
    //如果原来尾节点没有对象 证明这个链表没有使用过的
            first = newNode;
        }else{
    
    //原来用过 刚才已经将新的节点连接在last之后啦
            l.next = newNode;
        }
        //有效元素个数增加一个
        size++;
    }
    //设计一个小B同学 负责检测index
    private void rangeCheck(int index){
    
    
        if(index<0 || index>=size){
    
    
            throw new BoxIndexOutOfBoundsException("Index:"+index+",Size:"+size);
        }
    }
    //设计一个小C同学 负责找寻给定index位置的node对象
    private Node node(int index){
    
    
        Node targetNode;//用来存储找到的当前那个目标
        //判断index范围是在前半部分 还是在后半部分
        if(index < (size>>1)){
    
    //从前往后找寻比较快
            targetNode = first;
            for(int i=0;i<index;i++){
    
    
                targetNode = targetNode.next;
            }
        }else{
    
    //从后往前找
            targetNode = last;
            for(int i=size-1;i>index;i--){
    
    
                targetNode = targetNode.prev;
            }
        }
        return targetNode;
    }
    //设计一个方法 小D同学  负责将给定的node节点对象删除  并且保留数据
    private int unlink(Node targetNode){
    
    
        //获取当前node的item信息---
        int oldValue = targetNode.item;
        //当前node的前一个
        Node prev = targetNode.prev;
        //当前node的下一个
        Node next = targetNode.next;
        //删除节点对象
        if(prev==null){
    
    //当前node就是第一个
            first = next;
        }else{
    
    
            prev.next = next;
            targetNode.prev = null;
        }
        if(next==null){
    
    //当前node就是最后一个
            last = prev;
        }else{
    
    
            next.prev = prev;
            targetNode.next = null;
        }
        //让有效元素减少一个
        size--;
        return oldValue;
    }
    //-------------------------------------------------------
    //数据结构
    public boolean add(int element) {
    
    
        //将element存入一个新的Node对象里 添加至链表的尾端
        this.linkLast(element);
        //告知添加成功
        return true;
    }
    public int get(int index) {
    
    
        //检测index是否合法
        this.rangeCheck(index);
        //找寻index对应位置的那个node对象  将对象中的数据取出来
        Node targetNode = this.node(index);
        //返回找到的node对象内数据
        return targetNode.item;
    }
    public int remove(int index) {
    
    
        //检测范围是否合法
        this.rangeCheck(index);
        //找到index位置的那个node
        Node targetNode = this.node(index);
        //设计一个小D同学  负责删除当前的目标节点  让他帮我们返回oldValue
        int oldValue = this.unlink(targetNode);
        return oldValue;
    }
    public int size() {
    
    
        return size;
    }
}

  • Node------Custom node
package com.uncle.linkedbox.src.util;

public class Node {
    
    

    public Node prev;//previous  上一个node对象
    public int item;//当前的数据
    public Node next;//下一个node对象

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

  • Linked list structure
    Insert picture description here

Guess you like

Origin blog.csdn.net/m0_51945027/article/details/112798194