JAVA初阶必学-线性表

JAVA初阶必学-线性表

线性表
概念:
线性表是n个具有相同特性的数据元素的有限序列。线性表表示一种广泛应用在实际中的数据结构,线性表中数据元素的关系的一对一的关系,大多数线性表除了第一个和最后一个数据元素之外,其他数据元素都是首尾相接的。
常见的线性表有顺序表,链表,栈,队列,字符串。
线性表在逻辑上是线性结构,也就是说是一条直线,但是在物理上并不以一定是连续的,线性表在物理上存储时,通常以数组和链表结构的形式存储。

顺序表
顺序表的概念及结构
顺序表是用一段物理地址连续的存储单元依次存储数据元素的数据结构,一般情况下采用数组存储。在数组上完成数据的增删改查。
顺序表一般可分为
静态顺序表:使用定长数组存储。
动态顺序表:使用动态开辟的数组存储。
静态顺序表适用于知道需要存储多少数据的场景。(开多了浪费,开少了不够用)

实现动态顺序表

MyArrayList

 

 
/*
对象具备的一致性问题(前提)
1,size<=array.length
2,真正有用的元素下标[0,size)做删除操作size处不进行操作,因左闭右开,size处无有效值
3,可以插入元素的位置[0,size] size处也可插入,因有容量
4,[size,array.length)设置为无效的元素long.MIN_VALUE,便于观察
 */
/*
时间复杂度
当尾插,尾删时(暂不考虑扩容),时间复杂度为O(1)
根据下标插入删除时(包括头插),时间复杂度是O(n)
get(index)/set(index,e) 时间复杂度是O(1),顺序表支持随机访问
查找:indexOf,contains时间复杂度是O(n)
 */
 
import java.util.Arrays;
 
public class MyArrayList {
//两个需要的属性
    private long[] array;//存放数据的空间即空间的容量
    private int size;//有效元素的个数
 
    public MyArrayList() {
//将属性初始化,此时未插入有效元素,故将数组中全部填充为无效值Long.MIN_VALUE
        array = new long[2];
        size = 0;
        Arrays.fill(array, Long.MIN_VALUE);
    }
 
    /*
    放入元素
    1,指定位置放入
    2,在最后放入元素,即尾插操作
     */
    public long get(int index) {
//用来得到对应下标的值,便于检查操作的正确性
        //检查下标合法性
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException(index + ":" + size);
        }
        return array[index];
    }
 
    public int size() {
        return size;
    }
//尾插操作,即在末端插入值
    public void add(long e) {
        ensureCapacity();//调用方法确保容量足够
//  1,将元素放在size下标处
        array[size] = e;
//    2,size++
        size++;
    }
 
//确保容量足够的方法
    private void ensureCapacity() {
        if (size < array.length) {
            return;
        }
        //放不下了,进行扩容
        //建立新数组
        int newLength = array.length * 2;
        long[] newArray = new long[newLength];
        //复制内容到新数组
        for (int i = 0; i < size; i++) {
            newArray[i] = array[i];
        }
        Arrays.fill(newArray, size, newArray.length, Long.MIN_VALUE);//把[size,length]填充为无效值
        this.array = newArray;
    }
 
    //检查对象的正确性
    //如果对象不正确,抛异常
    public void check() {
        if (array == null) {
            throw new RuntimeException();
        }
        if (array.length == 0) {
            throw new RuntimeException();
        }
        if (size < 0) {
            throw new RuntimeException();
        }
        if (size > array.length) {
            throw new RuntimeException();
        }
        //[0,size)是有效元素
        for (int i = 0; i < size; i++) {
            if (array[i] == Long.MIN_VALUE) {
                throw new RuntimeException();
            }
        }
        //[size,array.length-1)是无效值
        for (int i = size; i < array.length; i++) {
            if (array[i] != Long.MIN_VALUE) {
                throw new RuntimeException();
            }
        }
 
    }
//指定下标进行插入
    public void add(int index, long e) {
        if (index < 0 || index > size) {
            throw new ArrayIndexOutOfBoundsException(index + ":" + size);
        }
        ensureCapacity();
        //TODO
        for (int i = size; i > index; i--) {
            array[i] = array[i - 1];
        }
        array[index] = e;
        size++;
    }
//指定下标进行删除
    public void delete(int index) {
        if (index < 0 || index >= size) {
            throw new ArrayIndexOutOfBoundsException(index + ":" + size);
        }
        for (int i = index + 1; i < size; i++) {
            array[i - 1] = array[i];
        }
        size--;
        array[size] = Long.MIN_VALUE;
    }
//指定元素进行删除,从前往后遍历,只删一个
    public void removeFromHead(long e) {
        int index;
        for (index = 0; index < size; index++) {
            if (array[index] == e) {
               break;
                }
            }
        if (index == size) {
            return;
        }
        for (int i = index + 1; i < size; i++) {
            array[i - 1] = array[i];
        }
        size--;
        array[size] = Long.MIN_VALUE;
 
    }
//指定元素进行删除,从后往前遍历,只删一个
    public void removeFromLast(long e) {
        int index;
        for ( index = size-1; index >=0; index--) {
            if (array[index] == e) {
                break;
            }
        }
        if (index <0) {
            return;
        }
        for (int i = index + 1; i < size; i++) {
            array[i - 1] = array[i];
        }
        size--;
        array[size] = Long.MIN_VALUE;
 
 
    }
//下边三种均为删除顺序表中值为e的方法,性能略有不同
//初级解法,性能较差
    public void removeAll(long e) {
       int index=0;
        while(true){
            if(array[index]==e){
                for (int i = index + 1; i < size; i++) {
                    array[i - 1] = array[i];
                }
                size--;
                array[size] = Long.MIN_VALUE;
            }
            else{
                index++;
            }
            if(index==size){
                break;
            }
        }
    }
//开辟新数组,稍有优化
    public void removeAllNEW(long e) {
        //把不是e的元素搬到新的数组中,时间复杂度为O(n)
        int newLength=array.length;
        long[]newArray=new long[newLength];
        int j=0;
        for (int i = 0; i <size ; i++) {
            if (array[i]!=e){
                newArray[j]=array[i];
                j++;
            }
            else{
 
            }
        }
        size=j;
        Arrays.fill(newArray,j,newLength,Long.MIN_VALUE);
        this.array=newArray;
    }
//优化版,在原有的数组中完成任务
    public void removeAllNEWNEW(long e) {
        int from=0;
        int to=0;
        for (int i = 0; i <size ; i++) {
            if (array[i]!=e){
                array[to]=array[from];
                from++;
                to++;
            }
            else{
                from++;
            }
        }
        size=to;
        Arrays.fill(array,to,array.length,Long.MIN_VALUE);
    }
}
hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » JAVA初阶必学-线性表