zoukankan      html  css  js  c++  java
  • [数据结构]

    1、Java数组介绍

      在Java中,数组是用来存放同一种数据类型的集合,注意只能存放同一种数据类型(Object类型数组除外)。

    • 在内存中,数组是一块连续的区域。 拿上面的看电影来说,这几个人在电影院必须坐在一起。

    • 数组需要预留空间,在使用前要先申请占内存的大小,可能会浪费内存空间。 比如看电影时,为了保证10个人能坐在一起,必须提前订好10个连续的位置。这样的好处就是能保证10个人可以在一起。但是这样的缺点是,如果来的人不够10个,那么剩下的位置就浪费了。如果临时有多来了个人,那么10个就不够用了,这时可能需要将第11个位置上的人挪走,或者是他们11个人重新去找一个11连坐的位置,效率都很低。如果没有找到符合要求的作为,那么就没法坐了。

    • 插入数据和删除数据效率低,插入数据时,这个位置后面的数据在内存中都要向后移。删除数据时,这个数据后面的数据都要往前移动。 比如原来去了5个人,然后后来又去了一个人要坐在第三个位置上,那么第三个到第五个都要往后移动一个位子,将第三个位置留给新来的人。 当这个人走了的时候,因为他们要连在一起的,所以他后面几个人要往前移动一个位置,把这个空位补上。

    • 随机读取效率很高。因为数组是连续的,知道每一个数据的内存地址,可以直接找到给地址的数据。

    • 并且不利于扩展,数组定义的空间不够时要重新定义数组。一种解决办法是封装一次数组,数组元素超过75%时候就动态扩容,新申请一个1.5倍的数组,把原来的数组全部拷贝过去。

    ①、数组的声明

    第一种方式:

    数据类型 []  数组名称 = new 数据类型[数组长度];
    

    这里 [] 可以放在数组名称的前面,也可以放在数组名称的后面,我们推荐放在数组名称的前面,这样看上去 数据类型 [] 表示的很明显是一个数组类型,而放在数组名称后面,则不是那么直观。

    第二种方式:

    数据类型 [] 数组名称 = {数组元素1,数组元素2,......}
    

     这种方式声明数组的同时直接给定了数组的元素,数组的大小由给定的数组元素个数决定。

    //声明数组1,声明一个长度为3,只能存放int类型的数据
    int [] myArray = new int[3];
    //声明数组2,声明一个数组元素为 1,2,3的int类型数组
    int [] myArray2 = {1,2,3};
    

    ②、访问数组元素以及给数组元素赋值

      数组是存在下标索引的,通过下标可以获取指定位置的元素,数组小标是从0开始的,也就是说下标0对应的就是数组中第1个元素,可以很方便的对数组中的元素进行存取操作。

      前面数组的声明第二种方式,我们在声明数组的同时,也进行了初始化赋值。
      
     

    //声明数组,声明一个长度为3,只能存放int类型的数据
    int [] myArray = new int[3];
    //给myArray第一个元素赋值1
    myArray[0] = 1;
    //访问myArray的第一个元素
    System.out.println(myArray[0]);
    

    上面的myArray 数组,我们只能赋值三个元素,也就是下标从0到2,如果你访问 myArray[3] ,那么会报数组下标越界异常。

    ③、数组遍历

      数组有个 length 属性,是记录数组的长度的,我们可以利用length属性来遍历数组。
      

    //声明数组2,声明一个数组元素为 1,2,3的int类型数组
    int [] myArray2 = {1,2,3};
    for(int i = 0 ; i < myArray2.length ; i++){
        System.out.println(myArray2[i]);
    }
    

    2、简单封装一个动态数组

    package me.liangtian.array;
     
    public class Array<E> {
    	/**
    	 * 存放数据的数组
    	 */
    	private E[] data;
    	/**
    	 * 数组中现有数据量
    	 */
    	private int size;
    	
    	public Array(int capacity) {
    		data = (E[])new Object[capacity];
    		size = 0;
    	}
    	/**
    	 * 默认数组长度10
    	 */
    	public Array() {
    		new Array<>(10);
    	}
    	/**
    	 * 得到数组长度
    	 */
    	public int getCapacity() {
    		return data.length;
    	}
    	/**
    	 * 已有数组大小
    	 */
    	public int getSize() {
    		return size;
    	}
    	/**
    	 * 判断数组是否为空
    	 */
    	public boolean isEmpty() {
    		return size == 0;
    	}
    	/**
    	 * 索引index处添加一个元素
    	 * 1.判断索引是否有效
    	 * 2.判断数组是否已经满了,若满了那么扩容
    	 * 3.从后往前,index处的元素后移一个位置
    	 * 4.index索引处元素赋值
    	 * 5.size++
    	 */
    	public void add(int index, E e) {
    		if(index < 0 || index > size) {
    			throw new IllegalArgumentException("add failed, index must between 0 and size");
    		}
    		if(index == size) {
    			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);
    	}
    	
    	/**
    	 * 是否包含否个元素
    	 */
    	public boolean contains(E e) {
    		for (E e1 : data) {
    			if(e1.equals(e)) {
    				return true;
    			}
    		}
    		return false;
    	} 
    	
    	/**
    	 * 动态扩容
    	 * 1.新建一个容器,大小为指定大小newCapacity
    	 * 2.将之前的容器的元素按原有顺序放到新的容器中
    	 * 3.将原指针指向新容器
    	 */
    	private void resize(int newCapacity) {
    		E[] newDate = (E[]) new Object[newCapacity];
    		for(int i = 0; i < size; i++) {
    			newDate[i] = data[i];
    		}
    		data = newDate;
    	}
    	/**
    	 * 查找元素E在数组中的索引
    	 * 1.遍历所有的数组,若匹配到(equals非==)那么返回索引,否则返回-1
    	 */
    	private int find(E e) {
    		for (int i = 0; i < data.length; i++) {
    			if(data[i].equals(e)) {
    				return i;
    			}
    		}
    		return -1;
    	}
    	
    	/**
    	 * 删除元素并返回删除之前的位置
    	 * 若不存在则返回-1
    	 */
    	public int removeElement(E e) {
    		int index = find(e);
    		if(index != -1) {
    			remove(index);
    		}
    		return index;
    	}
    	/**
    	 * 根据索引删除元素,并返回删除元素
    	 * 1.判断索引是否有效
    	 * 2.将索引处的元素保存到单独一个变量,用于返回
    	 * 3.将所有元素左移,索引从小到大
    	 * 4.将size索引处的元素清空,并且size-1
    	 * 5.均摊算法复杂度。为防止算法复杂度振荡,只有size <= data.leng/4 那么重新调整数组大小为原大小二分之一
    	 *   注意数组容器大小不能为0
    	 */
    	private E remove(int index) {
    		if(index < 0 || index >= size) {
    			throw new IllegalArgumentException("index must between 0 and size -1");
    		}
    		E removeData = data[index];
    		for(int i = index + 1; i < size; i++) {
    			data[i-1] = data[i];
    		}
    		data[index] = null;
    		size--;
    		if(size <= data.length/4 && data.length /2 != 0) {
    			resize(data.length /2);
    		}
    		return removeData;
    	}
    }
    
    
  • 相关阅读:
    mysql的length与char_length的区别
    case when 多个条件 以及case when 权重排序
    ogitor下载地址
    简单单例模式
    求切线和次法线
    Alpha混合物体的深度排序
    C++对齐问题
    Computing Tangent Space Basis Vectors for an Arbitrary Mesh
    .NET三层架构简析
    DaGridView导出Excel
  • 原文地址:https://www.cnblogs.com/gwyy/p/10265820.html
Copyright © 2011-2022 走看看