数据结构01——“小小数组”,不可小觑
数组的概念很简单,就是把数据码成一排进行存放。在数组中其重要的内容就是“索引”,对于数组的这个“索引”是可以有语意,也可以是没有语意的,而数组最大的优点,是在于其能快速的查询,例如我们调用arra[2],就能得到这个下标‘2’位置元素的值。因此数组最好应用于“索引”有语意的情况下,可并非所有有语意的索引都适用于数组,例如身份证号码,当我们索引一个人的身份信息时,这个身份证号肯定是最好的一个索引方式,但是由于这个身份证号的数据太大,因此这种场景下它不适用于数组。
说了这么多,我们开始来学习一下数组,这里会制作属于我们自己的数组类,那我们就开始来基于java的数组来进行二次封装一个属于我们自己的数组类,这里我们所设计的数组将是一个动态的数组,以及包括增、删、改、查这样一个基本的功能。
一.首先创建一个基本的数组类
public class Array { private int[] data; private int size; //构造函数,传入数组的容量capacity构造Array数组 public Array(int capacity) { data = new int[capacity]; size = 0; } //无参数构造函数,默认数组的容量capacity=10 public Array() { this(10); } //获取数组中的元素个数 public int getSize() { return size; } //获取数组的容量 public int getCapacity() { return data.length; } //返回数组是否为空 public boolean isEmpty() { return size == 0; } }
二.向数组中添加元素的方法
//向所有元素后添加一个新元素 public void addLast(int e){ add(size, e); } //在所有元素前添加一个新元素 public void addFirst(int e){ add(0, e); } //在index索引的位置插入一个新元素e public void add(int index, int e){ if(size == data.length) throw new IllegalArgumentException("Add failed. Array is full."); if(index < 0 || index > size) throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size."); //把当前索引及其后面的值向后挪 for(int i = size - 1; i >= index ; i --) data[i + 1] = data[i]; data[index] = e; size ++; }
三.添加删、改、查的方法
//获取index索引位置的元素 public int get(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Get failed. Index is illegal."); return data[index]; } //修改index索引位置的元素为e public void set(int index, int e){ if(index < 0 || index >= size) throw new IllegalArgumentException("Set failed. Index is illegal."); data[index] = e; } //查找数组中是否有元素e public boolean contains(int e){ for(int i = 0 ; i < size ; i ++){ if(data[i] == e) return true; } return false; } //查找数组中元素e所在的索引,如果不存在元素e,则返回-1 public int find(int e){ for(int i = 0 ; i < size ; i ++){ if(data[i] == e) return i; } return -1; } //从数组中删除index位置的元素, 返回删除的元素 public int remove(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Remove failed. Index is illegal."); int ret = data[index]; //把删除索引后面的元素值向前移动 for(int i = index + 1 ; i < size ; i ++) data[i - 1] = data[i]; size --; return ret; } //从数组中删除第一个元素, 返回删除的元素 public int removeFirst(){ return remove(0); } //从数组中删除最后一个元素, 返回删除的元素 public int removeLast(){ return remove(size - 1); } //从数组中删除元素e public void removeElement(int e){ int index = find(e); if(index != -1) remove(index); } @Override public String toString(){ StringBuilder res = new StringBuilder(); res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length)); res.append('['); for(int i = 0 ; i < size ; i ++){ res.append(data[i]); if(i != size - 1) res.append(", "); } res.append(']'); return res.toString(); }
四.修改基本数组为泛型数组
这样的修改,是为了让当前的数组类能够适用于更多的数据类型。
public class Array<E> { private E[] data; private int size; // 构造函数,传入数组的容量capacity构造Array public Array(int capacity){ data = (E[])new Object[capacity]; size = 0; } // 无参数的构造函数,默认数组的容量capacity=10 public Array(){ this(10); } // 获取数组的容量 public int getCapacity(){ return data.length; } // 获取数组中的元素个数 public int getSize(){ return size; } // 返回数组是否为空 public boolean isEmpty(){ return size == 0; } // 在index索引的位置插入一个新元素e public void add(int index, E e){ if(size == data.length) throw new IllegalArgumentException("Add failed. Array is full."); if(index < 0 || index > size) throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size."); //把当前索引及其后面的值向后挪 for(int i = size - 1; i >= index ; i --) data[i + 1] = data[i]; data[index] = e; size ++; } // 向所有元素后添加一个新元素 public void addLast(E e){ add(size, e); } // 在所有元素前添加一个新元素 public void addFirst(E e){ add(0, e); } // 获取index索引位置的元素 public E get(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Get failed. Index is illegal."); return data[index]; } // 修改index索引位置的元素为e public void set(int index, E e){ if(index < 0 || index >= size) throw new IllegalArgumentException("Set failed. Index is illegal."); data[index] = e; } // 查找数组中是否有元素e public boolean contains(E e){ for(int i = 0 ; i < size ; i ++){ if(data[i].equals(e)) return true; } return false; } // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1 public int find(E e){ for(int i = 0 ; i < size ; i ++){ if(data[i].equals(e)) return i; } return -1; } // 从数组中删除index位置的元素, 返回删除的元素 public E remove(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Remove failed. Index is illegal."); E ret = data[index]; //把删除索引后面的元素值向前移动 for(int i = index + 1 ; i < size ; i ++) data[i - 1] = data[i]; size --; //把删除的索引位置置为null,方便Java垃圾回收 data[size] = null; // loitering objects != memory leak return ret; } // 从数组中删除第一个元素, 返回删除的元素 public E removeFirst(){ return remove(0); } // 从数组中删除最后一个元素, 返回删除的元素 public E removeLast(){ return remove(size - 1); } // 从数组中删除元素e public void removeElement(E e){ int index = find(e); if(index != -1) remove(index); } @Override public String toString(){ StringBuilder res = new StringBuilder(); res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length)); res.append('['); for(int i = 0 ; i < size ; i ++){ res.append(data[i]); if(i != size - 1) res.append(", "); } res.append(']'); return res.toString(); } }
五.将数组设置为动态数组
这样的设计是让数组可以动态进行扩容,缩容。
public class Array<E> { private E[] data; private int size; // 构造函数,传入数组的容量capacity构造Array public Array(int capacity){ data = (E[])new Object[capacity]; size = 0; } // 无参数的构造函数,默认数组的容量capacity=10 public Array(){ this(10); } // 获取数组的容量 public int getCapacity(){ return data.length; } // 获取数组中的元素个数 public int getSize(){ return size; } // 返回数组是否为空 public boolean isEmpty(){ return size == 0; } // 在index索引的位置插入一个新元素e public void add(int index, E e){ if(index < 0 || index > size) throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size."); if(size == data.length) resize(2 * data.length); //把当前索引及其后面的值向后挪 for(int i = size - 1; i >= index ; i --) data[i + 1] = data[i]; data[index] = e; size ++; } // 向所有元素后添加一个新元素 public void addLast(E e){ add(size, e); } // 在所有元素前添加一个新元素 public void addFirst(E e){ add(0, e); } // 获取index索引位置的元素 public E get(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Get failed. Index is illegal."); return data[index]; } // 修改index索引位置的元素为e public void set(int index, E e){ if(index < 0 || index >= size) throw new IllegalArgumentException("Set failed. Index is illegal."); data[index] = e; } // 查找数组中是否有元素e public boolean contains(E e){ for(int i = 0 ; i < size ; i ++){ if(data[i].equals(e)) return true; } return false; } // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1 public int find(E e){ for(int i = 0 ; i < size ; i ++){ if(data[i].equals(e)) return i; } return -1; } // 从数组中删除index位置的元素, 返回删除的元素 public E remove(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Remove failed. Index is illegal."); E ret = data[index]; //把删除索引后面的元素值向前移动 for(int i = index + 1 ; i < size ; i ++) data[i - 1] = data[i]; size --; data[size] = null; // loitering objects != memory leak //这里设置为四分之一之一是为了让数组在删除至size为length的四分之一时才进行缩容,为的是解决Lazy if(size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2); return ret; } // 从数组中删除第一个元素, 返回删除的元素 public E removeFirst(){ return remove(0); } // 从数组中删除最后一个元素, 返回删除的元素 public E removeLast(){ return remove(size - 1); } // 从数组中删除元素e public void removeElement(E e){ int index = find(e); if(index != -1) remove(index); } @Override public String toString(){ StringBuilder res = new StringBuilder(); res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length)); res.append('['); for(int i = 0 ; i < size ; i ++){ res.append(data[i]); if(i != size - 1) res.append(", "); } res.append(']'); return res.toString(); } // 将数组空间的容量变成newCapacity大小 private void resize(int newCapacity){ E[] newData = (E[])new Object[newCapacity]; for(int i = 0 ; i < size ; i ++) newData[i] = data[i]; data = newData; } }
最后语:不积跬步,无以至千里;不积小流,无以成江海。代码之路乃是一步一个脚印走完的,希望自己也能坚持这份真知!
版权声明:尊重博主原创文章,转载请注明出处 https://www.cnblogs.com/hsdy