数据结构——线性表的顺序存储结构(GIF图解)

一、数组基础

数组就是把数据码成一排进行存放。
Java中,数组的每个元素类型必须相同,可以都为int类型,string类型,甚至是自定义类型。
数组的命名要语义化,例如,如果数组用来存放学生的成绩,那么命名为scores就比较合适。
索引(index)是数组中的一个重要概念,它是我们给数组中的每个元素分配的编号,从0开始,依次递增。如果数组中存放了n个元素,第一个元素的索引是0,最后一个元素的索引是n-1。
通过索引,我们可以对数组中的元素进行快速访问,例如,我们访问索引为2的元素也就是数组中的第3个元素,就可以通过scores[2]这种形式。

1、在Java中声明一个简单的数组:

/*
创建线性表List的顺序存储结构实现类ArrayList
*/
public class ArrayList<E> implements List<E>{
    //创建E类型的一维数组
    private E[] data;
    //维护元素个数
    private int size;
    //默认最大容量为10
    private static int DEFAULT_CAPACITY=10;

    //创建一个默认大小的顺序表
    public ArrayList(){
        this(DEFAULT_CAPACITY);
    }

    //创建一个容量由用户指定的顺序表
    public ArrayList(int capacity){
        if(capacity<=0){
            throw new IllegalArgumentException("容量>0:"+capacity);
        }
        data=(E[])(new Object[capacity]);
        size=0;
    }

    //用户传入一个数组 将该数组封装成一个顺序表
    public ArrayList(E[] data){
        if(data==null){
            throw new IllegalArgumentException("数组不能为空");
        }
        this.data=(E[])(new Object[data.length]);
        for (int i = 0; i <data.length ; i++) {
            this.data[i]=data[i];
        }
        size=data.length;
    }

2、实现自定义数组类Array所包含的基本方法

首先,写一个接口包含ArrayList的基本方法(如下)

public interface List<E> extends Iterable<E>{
    //获取线性表中元素的有效个数
    int getSize();
    
    //判断线性表是否为空表
    boolean isEmpty();
    
    //在线性表指定的index角标处插入元素e
    void add(int index,E e);
    
    //在线性表的表头处插入元素e
    void addFirst(E e);
    
    //在线性表的表尾处插入元素e
    void addLast(E e);

    //获取线性表中指定角标index处的元素
    E get(int index);

    //获取表头元素
    E getFirst();

    //获取表尾元素
    E getLast();

    //修改线性表中指定角标index处的元素为新元素e
    void set(int index,E e);

    //判断线性表中是否包含元素e
    boolean contains(E e);

    //查找元素e的角标(从左到又默认第一个出现的元素角标)
    int find(E e);

    //删除并返回线性表中指定角标index处的元素
    E remove(int index);

    //删除并返回表头元素
    E removeFirst();

    //删除并返回表尾元素
    E removeLast();

    //删除指定元素e
    void removeElement(E e);

    //清空线性表
    void clear();

3、实现接口的功能

获取有效个数和判空
   @Override
    public int getSize() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size==0;
    }
在指定位置插入元素

在这里插入图片描述

    //指定位置添加元素
    @Override
    public void add(int index, E e) {
        if(index<0||index>size){
            throw new IllegalArgumentException("角标越界");
        }
        if(size==data.length){
            //扩容
            resize(data.length*2);
        }
        for (int i = size; i >index ; i--) {
            data[i]=data[i-1];
        }
        data[index]=e;
        size++;
    }
	//扩容、缩容
    private void resize(int newLength) {
        E[] newData=(E[])(new Object[newLength]);
        for (int i = 0; i < size; i++) {
            newData[i]=data[i];
        }
        data=newData;
    }
	//头插入
    @Override
    public void addFirst(E e) {
        add(0,e);
    }
	//尾插入
    @Override
    public void addLast(E e) {
        add(size,e);
    }
获取线性表中指定角标index处的元素
//获取线性表中指定角标index处的元素
    @Override
    public E get(int index) {
        if(isEmpty()){
            throw new IllegalArgumentException("线性表为空");
        }
        if(index<0||index>=size){
            throw new IllegalArgumentException("角标越界");
        }
        return data[index];
    }
//获取表头元素
    @Override
    public E getFirst() {
        return get(0);
    }
 //获取表尾元素
    @Override
    public E getLast() {
        return get(size-1);
    }

修改指定角标处元素
 @Override
    public void set(int index, E e) {
        if(isEmpty()){
            throw new IllegalArgumentException("线性表为空");
        }
        if(index<0||index>=size){
            throw new IllegalArgumentException("角标越界");
        }
        data[index]=e;
    }
判断线性表中是否包含元素e

    @Override
    public boolean contains(E e) {
        return find(e)!=-1;
    }
查找元素
    @Override
    public int find(E e) {
        if(isEmpty()){
            throw new IllegalArgumentException("线性表为空");
        }
        for (int i = 0; i < size; i++) {
            if(data[i].equals(e)){
                return i;
            }
        }
        return -1;
    }

删除元素

在这里插入图片描述

//删除并返回线性表中指定角标index处的元素
    @Override
    public E remove(int index) {
        if(isEmpty()){
            throw new IllegalArgumentException("线性表为空");
        }
        if(index<0||index>=size){
            throw new IllegalArgumentException("角标越界");
        }
        E ret=data[index];
        for(int i=index+1;i<size;i++){
            data[i-1]=data[i];
        }
        size--;
        if(size<=data.length/4&&data.length/2>=10){
            resize(data.length/2);
        }
        return ret;
    }
    //删除并返回表头元素
    @Override
    public E removeFirst() {
        return remove(0);
    }
    //删除并返回表尾元素
    @Override
    public E removeLast() {
        return remove(size-1);
    }
    //删除指定元素e
    @Override
    public void removeElement(E e) {
        int index=find(e);
        if(index!=-1){
            remove(index);
        }else{
            throw new IllegalArgumentException("元素不存在");
        }
    }

清空顺序表和获取容量
//清空
    @Override
    public void clear() {
        size=0;
        data=(E[])(new Object[DEFAULT_CAPACITY]);
    }
//获取容量
    public int getCapacity(){
        return data.length;
    }

实现自定义打印数组格式
    @Override
    public String toString() {
        StringBuilder sb=new StringBuilder();
        sb.append(String.format("ArrayList: %d/%d \n",size,data.length));
        sb.append('[');
        if(isEmpty()){
            sb.append(']');
        }else{
            for (int i = 0; i < size; i++) {
                sb.append(data[i]);
                if(i == size - 1){
                    sb.append(']');
                }else{
                    sb.append(',');
                }
            }
        }
        return sb.toString();
    }

返回当前数据结构的一个迭代器对象
//迭代器用于在没有角标支持的环境下遍历元素
    @Override
    public Iterator<E> iterator() {
        return new ArrayListIterator();
    }
    private class ArrayListIterator implements Iterator{
        private int index=-1;
        @Override
        public boolean hasNext() {
            return index<size-1;
        }

        @Override
        public E next() {
            index++;
            return data[index];
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值