数据结构----数组(java实现代码)

最近打算将常用的数据结构通过java实现一遍,也是对数据结构学习的巩固,如有错误也请多多指正。

数组的主要操作

数组是一段连续存放数据的一种数据结构,主要是用java实现一个简单的数组的增删改查的操作。

其中需要说明的是动态数组的实现是当增加数组元素后,size值等于数组长度时,自动扩充到原来数组长度的2倍(java中的数组是1.5倍),扩充方法是新建一个长度为2倍的新数组,将原来的数组值复制到新数组中,原来的数组再指向这个新数组;同理当删除元素后,size值等于数组长度的一半时,自动扩充到原来数组长度的一半。平均每次addLast操作执行2次resize,平摊下来o(1),这个叫均摊复杂度
但是这样会造成震荡复杂度的问题,即如果原始数组中的假如有10个元素当添加一个元素后扩充为容量为20的数组,当再删除一个数组时,又会缩减成容量为10的数组,每进行一次动态更新操作复杂度为o(n)。所以改进方法为,在删除元素时不要着急缩减容量,即可以设置当元素减少到原来数组的1/4时,再将数组减少到原来的一半。

Array.java代码实现:

package com.lxr.array0330;
public class Array<E> {
	/**
	 * 增:o(n)
	 * 删:o(n)
	 * (增和删如果只对最后一个元素操作依然是o(n),是因为使用了resize.
	 * 但是并不是每次都出发resize,平均每次addLast操作执行2次resize,平摊下来o(1),这个叫均摊复杂度。
	 * 当数组元素已满时,添加一个元素,再删掉这个元素,再添加一个元素。。。数组容积不断扩充缩减,这种叫复杂度震荡。
	 * 出现原因:当删除最后一个元素时过于着急减少数组容量
	 * 解决方案:当删除最后一个元素时不要着急减少数组容量,等减少一部分后再进行缩减)
	 * 改:已知索引o(1),未知索引o(n)
	 * 查:已知索引o(1),未知索引o(n)
	 */
	
	private E[] data;
	private int size;
	
	public Array(int capacity) {
		data=(E[])new Object[capacity];
		size=0;
	}
	
	//初始容量为10
	public Array() {
		this(10);
	}
	
	//获取数组元素的个数
	public int getsize() {
		return size;
	}
	
	//获取容量
	public int getCapacity() {
		return data.length;
	}
	
	//是否为空
	public boolean isEmpty() {
		return size==0;
	}
	
//动态数组实现扩充,将元素复制到新数组,然后在指向这个新数组
	private void resize(int newcapacity) {
		E[] newdata =(E[])new Object[newcapacity];
		for(int i=0;i<size;i++) {
			newdata[i]=data[i];
		}
		data=newdata;
		
	}
	
	/**
	 * 数组index位置插入元素value。时间复杂度与index的取值有关,每一个index的概率相同取平均o(n/2)=o(n)
	 * @param index 插入位置
 	 * @param value 插入元素值
	 */
	public void insertElement(int index,E value) {
//		if(size==data.length)
//			throw new IllegalArgumentException("数组已满");
		if(index<0||index>size)
			throw new IllegalArgumentException("越界");
		
		//动态数组,java的arraylist选用的是扩充1.5倍
		if(size==data.length)
			resize(2*data.length);
		
		for(int i=size;i>index;i--) {
			data[i]=data[i-1];
		}
		data[index]=value;
		size++;
	}
	
	/**
	 * 向数组中添加新元素。时间复杂度o(1)
	 * @param a 插入元素值
	 */
	public void addElement(E a) {
//		if(size==data.length)
//			throw new IllegalArgumentException("数组已满");
//		data[size]=a;
//		size++;
		insertElement(size, a);
	}
	
	/**
	 * 数组头插入元素。时间复杂度o(n)
	 * @param e 插入的头元素
	 */
	public void addFirst(E e) {
		insertElement(0, e);
	}
	
	/**
	 * 获取index位置的值。时间复杂度o(1)
	 * @param index
	 * @return
	 */
	public E get(int index) {
		if(index<0||index>=size)
			throw new IllegalArgumentException("获取失败");
		return data[index];
	}
	
	/**
	 * 数组index位置更新元素value。时间复杂度o(1)
	 * @param index 更新元素位置
 	 * @param value 更新元素值元素值
	 */
	public void set(int index,E value) {
		if(index<0||index>=size)
			throw new IllegalArgumentException("获取失败");
		data[index]=value;
	}
	
	//查找数组中是否存在元素e。时间复杂度o(n)
	public boolean contains(E e) {
		for(int i=0;i<size;i++) {
			if(data[i].equals(e))
				return true;
		}
		return false;
	}
	
	//查找数组中元素e的索引;不存在返回-1。时间复杂度o(n)
	public int find(E e) {
		for(int i=0;i<size;i++) {
			if(data[i].equals(e))
				return i;
		}
		return -1;
	}
	
	//查找数组中元素e的所有索引,索引存入数组中,若不存在则数组第一个元素为-1;
	public int[] findAll(E e) {
		int[] a=new int[size];
		if(find(e)==-1) {
			a[0]=-1;
		}
		int in=0;
		for(int i=0;i<size;i++) {
			if(data[i].equals(e)) {
				a[in]=i;
				in++;
			}
		}
		return a;
	}
	
	//从数组中删除index的元素,返回删除元素。时间复杂度o(n/2)=o(n)
	public E delate(int index) {
		if(index<0||index>=size)
			throw new IllegalArgumentException("删除失败1");
		
		E a=data[index];
		for(int i=index;i<size-1;i++) {
			data[i]=data[i+1];
		}
		size--;
		data[size]=null;//loitering object !=memory leak  (垃圾回收机制,这样可以被回收)
		//当数组减少到数组长度的一半时,动态减少数组的长度的一半
		//当数组减少到数组长度的1/4时,动态减少数组的长度的一半(防止震荡复杂度)
		if(size==data.length/4&&data.length/2!=0) {
			resize(data.length/2);
		}
		return a;
	}
	//从数组中删除第一个元素,返回删除元素。时间复杂度o(n)
	public E delateFrist() {
		return delate(0);
	}
	//从数组中删除最后一个元素,返回删除元素。时间复杂度o(1)
	public E delateLast() {
		return delate(size-1);
	}
	
	//从数组中删除元素e
	public void deleteElement(E e) {
		int index=find(e);
		if(index!=-1)
			delate(index);
	}
	
	//从数组中删除所有元素e
	public void deleteAllElement(E e) {
		int []a=findAll(e);
		for(int i=a.length-1;i>0;i--) {
			if(a[i]!=0) {
				System.out.println(a[i]);
				delate(a[i]);
			}
		}
		if(a[0]!=-1) {
			delate(a[0]);
		}
	}
	
	public E getFirst() {
		return get(0);
	}
	
	public E getLast() {
		return get(size-1);
	}
	
	/**
	 * 继承的父类,功能是自定义打印输出的格式
	 */
	@Override
	public String toString() {
		StringBuilder reStringBuilder =new StringBuilder();
		reStringBuilder.append(String.format("Array:size=%d,capacity=%d\n",size,data.length));
		reStringBuilder.append('[');
		for(int i=0;i<size;i++) {
		    reStringBuilder.append(data[i]);
		    if(i!=size-1)
		    	reStringBuilder.append(", ");
		}
		reStringBuilder.append(']');
		
		return reStringBuilder.toString();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值