数据结构学习之数组

数组基础

关于数组,综合来讲就是增删改查!
8种基本数据类型:boolean、byte、char、short、int、long、float、double

  • int[] arr = new int[10]; //动态初始化数组
  • int[] a = { 1, 2, 3 };// 静态初始化基本类型数组;
  • Man[] mans = {new Man(1,1), new Man(2,2)};// 静态初始化引用类型数组;

代码实现

Array实现类

package cn.data.structure;

public class Array<E> {//声明泛型E
	public static void main(String[] args) {
		
	}
	
	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 getSize() {
		return size;
	}
	
	//获取数组的容量
	public int getCapacity() {
		return data.length;
	}
	
	//返回数组是否为空
	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索引位置的元素
	E get(int index) {
		if(index<0||index>size) {
			throw new IllegalArgumentException("Get failed.Index is illegal.");
		}
		return data[index];
	}
	
	//修改index索引位置的元素为e
	void set(int index,E e ) {
		if(index<0||index>size) {
			throw new IllegalArgumentException("Get 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/4 && data.length/2!=0) {//Lazy解决复杂度震荡,不选择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);
		}
	}
	
	@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();
	}
	
	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 Student {
	private String name;
	private int score;
	
	public Student(String studentName,int studentScore) {
		this.name = studentName;
		this.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);
	}
}
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);
			
		arr.add(1, 100);
		System.out.println(arr);
			
		arr.addFirst(-1);
		System.out.println(arr);
		//[-1,0,100,1,2,3,4,5,6,7,8,9]
		
		arr.remove(2);
		System.out.println(arr);
		
		arr.removeElement(4);
		System.out.println(arr);
		
		arr.removeFirst();
		System.out.println(arr);
	}

数组的一些操作

构造数组

//构造函数,传入数组的容量capacity构造Array

向数组中添加元素

//获取数组中的元素个数
//获取数组的容量
//返回数组是否为空
//向指定位置index添加元素add(index,e)—O(n/2)=O(n)
//向所有元素后添加一个新元素addLast—O(1)
//向所有元素前添加一个新元素addFirst—O(n)

数组中查询元素和修改元素

//获取index索引位置的元素 get(index)—O(1)
//修改index索引位置的元素为e set(index,e)—O(1)

数组中包含,搜索和删除

//查找数组中是否存在元素e contain(e)—O(n)
//查找数组中元素e所在的索引,如果不存在返回-1 find(e)—O(n)
//从数组中删除index未知的元素,返回删除的元素
//从数组中删除第一个元素,返回删除的元素addFirst—O(n)
//从数组中删除最后一个元素,返回删除的元素addLast—O(1)
//从数组中删除元素e add(index,e)—O(n/2)=O(n)

数组使用泛型

使用泛型可以让数据结构可以放置任意数据类型,使用泛型只能使用类对象
不可以是基本数据类型。每个基本数据类型都有对应的包装类Boolean、Byte、Char、Short、Integer、Long、Float、Double。
Array arr = new Array<>();

动态数组

对数组进行扩容、缩容
if(size==data.length) {
resize(2*data.length);
}
E[] newData = (E[])new Object[newCapacity];
for(int i=0;i<size;i++) {
newData[i] = data[i];
}
data = newData;

简单的时间复杂度分析

O(1)、O(n)、O(lgn)、O(nlgn)、O(n^2).大O描述的是算法的运行时间和输入数据之间的关系。N是nums中的元素个数,算法和n呈线性关系。

渐进时间复杂度,n趋向于正无穷大
增:O(n) resize情况
删:O(n) resize情况
改:已知索引O(1)、未知索引O(n)
查:已知索引O(1)、未知索引O(n)

均摊复杂度和防止复杂度的震荡

均摊复杂度:resize=O(n),addLast=O(1),removeLast=O(1)
复杂度震荡:removeLast时resize过于着急(Eager)
解决方案:Lazy。当size==capacity/4时,才将capacity减半。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值