数据结构 (一) ----- 数据结构基本概念&基于数组实现线性表

相关文章:

  1. 《数据结构 (一) ----- 数据结构基本概念&基于数组实现线性表》



数据结构基本概念

一、逻辑结构
  1. 集合:元素罗列在一起
  2. 线性结构:元素前后相继一一对应
  3. 树形结构:元素存在一对多的关系
  4. 图结构或网状结构:元素之间存在多对多的关系
二、存储结构
  1. 顺序存储:地址连续,用数组
  2. 链式存储:地址不连续,用指针
三、数据结构定义
  • 数据结构:为了某种特殊的需求而专门设计的存储方式
四、数据结构的通用的几个操作
  • 插入 (add, insert)
  • 删除 (delete)
  • 修改 (update)
  • 查找 (get, indexOf)
  • 遍历
  • 排序 (sort)


数组实现线性表

一、基本概念

底层是数组,实际上就是Java中的ArrayList。

二、接口
public interface MyList {
    // 新增一个元素
    void add(Object element);

    // 删除一个元素
    boolean delete(Object element);

    // 根据索引删除一个元素
    boolean delete(int index);

    // 将指定位置元素更新为新元素
    boolean update(int index, Object newElement);

    // 当前列表中是否含有target这个元素
    boolean contains(Object target);

    // 返回指定索引的元素
    Object get(int index);

    // 返回列表大小
    int size();

    // 查找指定元素下标
    int indexOf(Object element);
}
三、功能实现
public class MyArrayList implements MyList {
    // 列表底层结构
    private Object[] elements;
    // 列表中已经存储的元素个数
    private int size = 0;
    // 列表的容量大小, 默认为10
    private int capacity = 10;

    // 自定义容量创建列表
    public MyArrayList(int capacity) {
        this.capacity = capacity;
        elements = new Object[capacity];
    }

    // 默认构造函数
    public MyArrayList() {
        elements = new Object[capacity];
    }

    @Override
    public void add(Object element) {
        // 扩容:把原来的小容量数组拷贝到新的大容量数组,丢弃小容量数组
        if (size >= capacity) {
            capacity *= 2;
            Object[] newArr = new Object[capacity];
            System.arraycopy(elements, 0, newArr, 0, elements.length);
            elements = newArr;
        }

        // 这里的size既表示列表中已经存储的元素个数,也表示列表中的下一个存放元素的下标
        // 即size指向elements中第一个为null的元素
        elements[size++] = element;
    }

    @Override
    public boolean delete(Object element) {
        return indexOf(element) >= 0 && delete(indexOf(element));
    }

    @Override
    public boolean delete(int index) {
        if (index > size - 1) return false;
        // 进行元素位移覆盖

        System.arraycopy(elements, index + 1, elements, index, size - index);
        size--;
        return true;
    }

    @Override
    public boolean update(int index, Object newElement) {
        if (index > size - 1) return false;
        elements[index] = newElement;
        return true;
    }

    @Override
    public boolean contains(Object target) {
        return indexOf(target) >= 0;
    }

    @Override
    public Object get(int index) {
        return elements[index];
    }

    public int size() {
        return size;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < size; i++) {
            sb.append(elements[i] + (i == size - 1 ? "" : ", "));
        }
        sb.append("]");
        return sb.toString();
    }

    @Override
    public int indexOf(Object element) {
        for (int i = 0; i < size; i++) {
            if (elements[i].equals(element)) return i;
        }
        return -1;
    }
}
四、几个关键的地方
  1. 对于列表的size属性的理解
    (1) size值的是列表中已经存储的元素个数
    (2) 也可以把size理解成指向底层数组中的第一个为null的元素的指针

  2. void add(Object element)功能实现

    public void add(Object element) {
        // 扩容:把原来的小容量数组拷贝到新的大容量数组,丢弃小容量数组
        if (size >= capacity) {
            capacity *= 2;
            Object[] newArr = new Object[capacity];
            System.arraycopy(elements, 0, newArr, 0, elements.length);
            elements = newArr;
        }
    
        // 这里的size既表示列表中已经存储的元素个数,也表示列表中的下一个存放元素的下标
        // 即size指向elements中第一个为null的元素
        elements[size++] = element;
    }
    

    注意

    1. 数组的扩容:由于线性表的底层是数组,当线性表存储的元素大于了其容量时,必须进行数组的扩容,扩容的思路为把原来存满的数组拷贝到新的扩容后数组中,丢弃原来的数组,使用现在新的大容量数组。
    2. 数组的扩容效率很低,所以使用线性表的时候最好预估即将存储的元素数量,为线性表指定capacity。
  3. boolean delete(int index)功能实现

    public boolean delete(int index) {
        if (index > size - 1) return false;
        // 进行元素位移覆盖
    
        System.arraycopy(elements, index + 1, elements, index, size - index);
        size--;
        return true;
    }
    

    注意

    1. 数组的位移:将指定下标右边的那部分元素(包括最后一个元素右边的null)向左位移覆盖。
    2. 数组的位移效率很低,所以最好不要使用线性表进行中间元素的增删。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值