当前位置:   article > 正文

数据结构——线性表的顺序存储结构(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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

3、实现接口的功能

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

    @Override
    public boolean isEmpty() {
        return size==0;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
在指定位置插入元素

在这里插入图片描述

    //指定位置添加元素
    @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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
获取线性表中指定角标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);
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
修改指定角标处元素
 @Override
    public void set(int index, E e) {
        if(isEmpty()){
            throw new IllegalArgumentException("线性表为空");
        }
        if(index<0||index>=size){
            throw new IllegalArgumentException("角标越界");
        }
        data[index]=e;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
判断线性表中是否包含元素e

    @Override
    public boolean contains(E e) {
        return find(e)!=-1;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
查找元素
    @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;
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
删除元素

在这里插入图片描述

//删除并返回线性表中指定角标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("元素不存在");
        }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
清空顺序表和获取容量
//清空
    @Override
    public void clear() {
        size=0;
        data=(E[])(new Object[DEFAULT_CAPACITY]);
    }
//获取容量
    public int getCapacity(){
        return data.length;
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
实现自定义打印数组格式
    @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();
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
返回当前数据结构的一个迭代器对象
//迭代器用于在没有角标支持的环境下遍历元素
    @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];
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/700681
推荐阅读
相关标签
  

闽ICP备14008679号