线性表的实现
线性表描述:线性表是n个类型相同数据元素的有限序列
线性表的逻辑结构
线性表是由n(n >= 0)个类型相同数据元素组成的有限序列记作(a1,a2,···,ai-1,ai,ai+1,···,an),即下图
List接口定义
既然线性结构可以由顺序存储结构和链式存储结构实现,那么将两者对线性结构共同的操作进行抽取,定义出线性结构的接口
//线性表接口定义 继承了迭代接口Iterable
// List<E> 定义List接口,数据类型为E(不确定数据类型)
public interface List<E> extends Iterable<E>{
public void add(E element); //默认在表尾添加一个元素
public void add(int index,E element); //默认在指定角标出添加一个元素
public void remove(E element); //删除指定元素
public E remove(int index); //删除指定角标出的元素 并返回原先的值
public E get(int index); //获取指定角标处的元素
public E set(int index,E element); //修改指定角标index处的值为element 并返回原先的值
public int size(); //获取线性表中元素的个数
public int indexOf(E element); //查看元素第一次出现的角标位置(从左到右)
public boolean contains(E element); //判断是否包含元素
public boolean isEmpty(); //判断线性表是否为空
public void clear(); //清空线性表
public void sort(Comparator<E> c); //按照比较器的内容进行排序
public List<E> subList(int fromIndex,int toIndex); //获取一个子线性表 在原线性表[fromIndex,toIndex)这个部分划分
ArrayList类定义
public class ArrayList<E> implements List<E> {
//线性表的默认容量
public static int DEFAULT_CAPACITY = 10;
//线性表存储的容器 data.length--容器的最大容量
public E[] data;
//线性表中元素的有效个数 也表示新来元素默认在尾部添加的角标
// size == data.length 表满
// size == 0 表空
public int size;
//默认创建一个容量为DEFAULT_CAPACITY的线性表
public ArrayList(){
// data =(E[]) new Object[DEFAULT_CAPACITY];
// size = 0;
this(DEFAULT_CAPACITY);
}
//创建一个由用户指定容量capacity的线性表
public ArrayList(int capacity){
if(capacity < 0){
throw new IllegalArgumentException("initial capacity must >=0");
}
DEFAULT_CAPACITY = capacity;
data =(E[]) new Object[capacity];
size = 0;
}
//指定数组的构造函数:传入一个数组 将该数组封装成一个线性表
public ArrayList(E[] arr){
if(arr == null){
throw new IllegalArgumentException("initial arr can not be null");
}
//1.data = (E[]) new Object[arr.length];
data = (E[]) new Object[DEFAULT_CAPACITY];
for(int i = 0;i < arr.length; i++){
//1.data[i] = arr[i];
add(arr[i]);
}
size = arr.length;
}
//在线性表的尾部添加一个元素element O(1)
@Override
public void add(E element) {
add(size,element);
}
//在线性表中指定的index角标处添加一个元素 O(n)
@Override
public void add(int index, E element) {
if(index < 0 || index > size){
throw new IndexOutOfBoundsException("add index out of bounds");
}
//判断线性表是否已经满了
if(size == data.length){
resize(data.length * 2);
}
//向后移动元素
for(int i = size - 1; i >= index; i--){
data[i + 1] = data[i];
}
//将新元素插入到指定元素
data[index] = element;
size++;
}
//数组扩容,缩容 重点在这个size身上 O(n)
private void resize(int newLength){
//1.先创建一个新数组
E[] newData =(E[]) new Object[newLength];
//2.将原数组data中的元素赋值到新数组newData中
for(int i = 0;i < size; i++){
newData[i] = data[i];
}
data = newData;
}
//删除线性表中指定的元素element O(n)
@Override
public void remove(E element) {
//1.获取该元素的位置
int index = indexOf(element); //O(n)
//2.判断元素的存在性 如果存在则根据角标删除该元素
if(index != -1){
remove(index); //O(n)
}
}
//删除线性表中指定角标处index的元素 并返回 O(n)
@Override
public E remove(int index) {
if(index < 0 || index > size){
throw new IndexOutOfBoundsException("remove index out of bounds");
}
E ret = data[index];
for(int i = index + 1;i < size; i++){
data[i - 1] = data[i];
}
size--;
//判断是否需要缩容,至少保证最小值DEFAULT_CAPACITY
//如果有效元素的个数是容量的1/4,且当前的数组长度是大于10的 则进行缩容
if(size == data.length / 4 && data.length > DEFAULT_CAPACITY){
resize(data.length / 2);
}
return ret;
}
//获取线性表中指定角标出index的元素 O(1) An=A1+(n-1)*d
@Override
public E get(int index) {
if(index < 0 || index >=size){
throw new IndexOutOfBoundsException("get index out of bounds");
}
return data[index];
}
//修改线性表中指定角标出index的元素的值为新的值element 并返回原先的值 O(1)
@Override
public E set(int index, E element) {
if(index < 0 || index >=size){
throw new IndexOutOfBoundsException("set index out of bounds");
}
E ret = data[index];
data[index] = element;
return ret;
}
//获取线性表中有效元素的个数 O(1)
@Override
public int size() {
return size;
}
//获取线性表中数组的容量 O(1)
public int getCapacity(){
return data.length;
}
//在线性表中查找指定元素element的角标 并返回
//从左到右第一次出现的位置 - lastIndexOf() O(n)
//如果元素不存在 则返回-1
@Override
public int indexOf(E element) {
for(int i = 0; i < size; i++){
if(element.equals(data[i])){
return i;
}
}
return -1;
}
//在线性表中判断是否包含指定元素element O(n)
@Override
public boolean contains(E element) {
return indexOf(element) != -1;
}
//判断线性表是否为空 O(1)
@Override
public boolean isEmpty() {
return size == 0;
}
//清空线性表 O(1)
@Override
public void clear() {
data = (E[])new Objects[DEFAULT_CAPACITY];
size = 0;
}
//根据比较器的规则 来对线性表的元素进行排序【插入排序(优化)】
@Override
public void sort(Comparator<E> c) {
if (c == null){
throw new IllegalArgumentException("comparator can not be null");
}
int j = 0;
E e = null;
//O(n)
for (int i = 1; i < size; i++){
e = data[i];
for (j = i; j > 0 && c.compare(data[j - 1],e) > 0; j--){
data[j] = data[j - 1];
}
data[j] = e;
}
}
//获取从fromIndex-toIndex区间的子线性表 [fromIndex,toIndex]
@Override
public List<E> subList(int fromIndex, int toIndex) {
if (fromIndex < 0){
throw new IndexOutOfBoundsException("fromIndex must >= 0");
}
if (toIndex >= size){
throw new IndexOutOfBoundsException("toIndex must < size");
}
if (fromIndex > toIndex){
throw new IndexOutOfBoundsException("fromIndex must <= toIndex");
}
ArrayList<E> subList = new ArrayList<>();
for (int i = fromIndex; i <= toIndex; i++){
subList.add(data[i]); //默认在表尾添加
}
return subList;
}
//比较两个线性表是否相等 长度相等且内容相同
public boolean equals(Object obj){
//1.是否比的是自己
if(this == obj){
return true;
}
//2.判断obj是否为空
if(obj == null){
return false;
}
//3.判类型
if (obj instanceof ArrayList) {
//4.按照自己的逻辑进行比较
ArrayList<E> other = (ArrayList<E>) obj;
//5.先比有效元素的个数
if (size != other.size) {
return false;
}
//6.有效元素个数相等的情况下 逐个比较元素
for (int i = 0; i < size; i++) {
if (!data[i].equals(other.data[i])) {
return false;
}
}
return true;
}
return false;
}
@Override
public String toString() {
//ArrayList:10/30[x,x,x,x,x]
StringBuilder sb = new StringBuilder(String.format("ArrayList:%d/%d[",size,data.length));
if(isEmpty()){
sb.append(']');//ArrayList:0/10 []
}else{ //ArrayList:5/10 [1,2,3,4,5]
for(int i = 0; i < size; i++){
sb.append(data[i]);
if(i != size - 1){
sb.append(',');
}else{
sb.append(']');
}
}
}
return sb.toString();
}
//获取ArrayList的迭代器;foreach遍历线性 it.hasNext() it.next()
@Override
public Iterator<E> iterator() {
return new ArrayListIterator();
}
class ArrayListIterator implements Iterator<E>{
private int cur = 0;
//判断之后是否有元素
@Override
public boolean hasNext(){
return cur < size;
}
//先把元素返回在后移
@Override
public E next(){
return data[cur++];
}
}
}
TestArrayList类
public class TestArrayList {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
System.out.println(list);
System.out.println("add元素");
for (int i = 1; i <= 12; i++) {
list.add(i);
}
System.out.println(list);
System.out.println("foreach遍历:");
for (int num : list) {
System.out.println(num);
}
System.out.println("Iterator迭代器:");
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
System.out.println(list);
System.out.println("remove元素");
System.out.println(list.remove(0));
System.out.println(list.remove(0));
System.out.println(list.remove(0));
System.out.println(list.remove(0));
System.out.println(list.remove(0));
System.out.println(list.remove(0));
System.out.println(list);
System.out.println(list.remove(0));
System.out.println(list.remove(0));
System.out.println(list);
System.out.println(list.remove(0));
System.out.println(list.remove(0));
System.out.println(list);
}
}