1.数据结构--数组
数组是一种最简单的数据结构,它占据一块连续的内存并且顺序存储数据,所以我们需要首先指定数组的大小;
public class Main { public static void main(String[] args) { int[] arr = new int[10]; for(int i = 0; i < arr.length; i++) arr[i] = i; int[] scores = new int[]{100,99,66}; for(int i = 0; i < scores.length; i++) System.out.println(scores[i]); //100 99 66 for(int score: scores) System.out.println(score); //100 99 66 scores[0] = 98; for(int score: scores) System.out.println(score); //98 99 66 }
}
1.自定义数组操作方法
public class Array { private int data; private int size; //构造函数,传入数组的容量capacity构造Array public Array(int capacity){ data = new int[capacity]; size = 0; } //无参数的构造函数 public Array(){ this(10); } //获取数组中元素的个数 public int getSize(){ return size; } //获取数组的容量 public int ggetCapacity(){ return data.length; } //返回数组是否为空 public boolean isEmpty(){ return size == 0; } //向所有元素后添加一个新元素 public void addLast(int e){ //if(size == data.length) // throw new IllegalArgumentException("AddLast failed,Array is full"); //data[size] = e; //size ++; 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("AddLast failed,Array is full"); if(index < 0 || index > size) throw new IllegalArgumentException("AddLast failed,Require index >=0 and index <=size"); for(int i = size -1;i >= index;i --) data[i + 1] = data[i]; data[index] = e; size ++; } @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(); } //获取index索引位置的元素 public int get(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Get Failed,Index is illegal"); return data[index]; }
//获取最后一个位置的元素
public int getLast(){
return get(size - 1);
}
//获取第一个位置的元素
public int getFirst(){
return get(0);
}
//修改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); } }
调用自定义的数组方法
//把数组码成一排进行存放 public class Main { public static void main(String[] args) { Array arr = new Array(20); for(int i = 0;i < 10; i ++) arr.addLast(i); System.out.println(arr); //Array:size= 10, capacity = 20 //[0,1,2,3,4,5,6,7,8,9] arr.add(1,100); System.out.println(arr); //Array:size= 10, capacity = 20 //[0,100,1,2,3,4,5,6,7,8,9] arr.addFirst(-1); System.out.println(arr); //Array:size= 10, capacity = 20 //[-1,0,100,1,2,3,4,5,6,7,8,9] arr.remove(2); System.out.println(arr); //[-1,0,1,2,3,4,5,6,7,8,9] arr.removeElement(4); System.out.println(arr); //[-1,0,1,2,3,5,6,7,8,9] arr.removeFirst(); System.out.println(arr); //[0,1,2,3,5,6,7,8,9] } }
2.数组使用泛型
public class Array<E> { private E[] data; private int size; //构造函数,传入数组的容量capacity构造Array public Array(int capacity){ data = (E[])new Object[capacity]; size = 0; } //无参数的构造函数 public Array(){ this(10); } //获取数组中元素的个数 public int getSize(){ return size; } //获取数组的容量 public int ggetCapacity(){ return data.length; } //返回数组是否为空 public boolean isEmpty(){ return size == 0; } //向所有元素后添加一个新元素 public void addLast(E e){ //if(size == data.length) // throw new IllegalArgumentException("AddLast failed,Array is full"); //data[size] = e; //size ++; add(size, e); } //向所有元素头添加一个新元素 public void addFirst(E e){ add(0, e); } //在第index个位置插入一个新元素e public void add(int index,E e){ if(size == data.length) throw new IllegalArgumentException("AddLast failed,Array is full"); if(index < 0 || index > size) throw new IllegalArgumentException("AddLast failed,Require index >=0 and index <=size"); for(int i = size -1;i >= index;i --) data[i + 1] = data[i]; data[index] = e; size ++; } @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(); } //获取index索引位置的元素 public E get(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Get Failed,Index is illegal"); return data[index]; }
//获取最后一个位置的元素
public E getLast(){
return get(size - 1);
}
//获取第一个位置的元素
public E getFirst(){
return get(0);
}
//修改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 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); } }
调用自定义的使用泛型后的数组方法
public class Main { public static void main(String[] args) { Array<Integer> arr = new Array<>(20); for(int i = 0;i < 10; i ++) arr.addLast(i); System.out.println(arr); //Array:size= 10, capacity = 20 //[0,1,2,3,4,5,6,7,8,9] arr.add(1,100); System.out.println(arr); //Array:size= 10, capacity = 20 //[0,100,1,2,3,4,5,6,7,8,9] arr.addFirst(-1); System.out.println(arr); //Array:size= 10, capacity = 20 //[-1,0,100,1,2,3,4,5,6,7,8,9] arr.remove(2); System.out.println(arr); //[-1,0,1,2,3,4,5,6,7,8,9] arr.removeElement(4); System.out.println(arr); //[-1,0,1,2,3,5,6,7,8,9] arr.removeFirst(); System.out.println(arr); //[0,1,2,3,5,6,7,8,9] } }
数组泛型实例
public class Student { private String name; private int score; public Student(String studentName,int studentScore){ name = studentName; score = studentScore; } @Override public String toString(){ return String.format("Student(name: %s, score: %d)",name,score); } public static void main(String[] args){ Array<Student> arr = new Array<>(); arr.addLast(new Student("Alice",100)); arr.addLast(new Student("Bob",66)); arr.addLast(new Student("Charlie",88)); System.out.println(arr); //Array:size= 3, capacity = 10 //[Student(name: Alice, score: 100),Student(name: Bob, score: 66),Student(name: Charlie, score: 88)] } }
3.动态数组--解决数组空间效率不高的问题
设计了多种动态数组,比如c++中的vector,先为数组分配一个小的存储空间,将数据存储到这个空间中,当空间不够用,超出了数组的容纳极限,我们就从新分配一个空间,将原来的数据复制到这个空间中去,然后将原来定的数据空间释放,以免造成数据空间的浪费。这样的操作会导致时间复杂度的提高,所以我们应该尽量少的改变数组容量的操作。
public class Array<E> { private E[] data; private int size; //构造函数,传入数组的容量capacity构造Array public Array(int capacity){ data = (E[])new Object[capacity]; size = 0; } //无参数的构造函数 public Array(){ this(10); } //获取数组中元素的个数 public int getSize(){ return size; } //获取数组的容量 public int ggetCapacity(){ return data.length; } //返回数组是否为空 public boolean isEmpty(){ return size == 0; } //向所有元素后添加一个新元素 public void addLast(E e){ //if(size == data.length) // throw new IllegalArgumentException("AddLast failed,Array is full"); //data[size] = e; //size ++; add(size, e); } //向所有元素头添加一个新元素 public void addFirst(E e){ add(0, e); } //在第index个位置插入一个新元素e public void add(int index,E e){ if(index < 0 || index > size) throw new IllegalArgumentException("AddLast 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 ++; } @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(); } //获取index索引位置的元素 public E get(int index){ if(index < 0 || index >= size) throw new IllegalArgumentException("Get Failed,Index is illegal"); return data[index]; }
//获取最后一个位置的元素
public E getLast(){
return get(size - 1);
}
//获取第一个位置的元素
public E getFirst(){
return get(0);
}
//修改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 //动态减少容量 if(size == data.length / 2) 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); }
//重置数组容量 private void resize(int newCapacity){ E[] newData = (E[])new Object[newCapacity]; for(int i = 0;i < size;i ++) newData[i] = data[i]; data = newData; } }
调用自定义的动态数组方法
//把数组码成一排进行存放 public class Main { public static void main(String[] args) { Array<Integer> arr = new Array<>(); for(int i = 0;i < 10; i ++) arr.addLast(i); System.out.println(arr); //Array:size= 10, capacity = 10 //[0,1,2,3,4,5,6,7,8,9] arr.add(1,100); System.out.println(arr); //Array:size= 11, capacity = 20 //[0,100,1,2,3,4,5,6,7,8,9] arr.addFirst(-1); System.out.println(arr); //Array:size= 12, capacity = 20 //[-1,0,100,1,2,3,4,5,6,7,8,9] arr.remove(2); System.out.println(arr); //Array:size= 11, capacity = 20 //[-1,0,1,2,3,4,5,6,7,8,9] arr.removeElement(4); System.out.println(arr); //Array:size= 10, capacity = 10 //[-1,0,1,2,3,5,6,7,8,9] arr.removeFirst(); System.out.println(arr); //Array:size= 9, capacity = 10 //[0,1,2,3,5,6,7,8,9] } }
4.时间复杂度分析
分析动态数组的时间复杂度
5. resize复杂度分析
复杂度震荡
修改前面的代码,解决复杂度震荡的问题
//从数字组中删除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 //动态减少容量 if(size == data.length / 4 && data.length / 2 !=0) resize(data.length / 2); return ret; }