数组是应用最广泛的一种数据结构,常常被植入到编程语言中,作为基本数据类型使用,因此,在一些教材中,数组并没有被当做一种数据结构单独拿出来讲解(其实数组就是一段连续的内存,即使在物理内存中不是连续的,在逻辑上肯定是连续的)。其实没必要在概念上做纠缠,数组可以当做学习数据结构的敲门砖,以此为基础,了解数据结构的基本概念以及构建方法
数据结构不仅是数据的容器,还要提供对数据的操作方法,比如检索、插入、删除、排序等。
无序数组(假设数组中,没有重复的值)
package www.panda.array;
/**
* @Author: panda
* @Data: 2018/12/2 21:19
* @Version: 1.0
* @remark 没有实现数组扩容,想要实现,各位同学自己拓展
*/
public class DisorderlyArray<E> {
private String[] stringsArray;
private static int size = 0;
private static final int ERROEINDEX = -1;
public DisorderlyArray(int capacity){
if(capacity <= 0) throw new IllegalArgumentException("数组的长度不能小于或等于0");
stringsArray = new String[capacity];
}
//新增
public void insertElem(String value){
stringsArray[size++] = value;
}
//查看是否包含元素
public int containsElem(String value){
for(int i=0;i<stringsArray.length;i++){
if(stringsArray[i].equals(value)){
return i;
}
}
return ERROEINDEX;
}
//通过下标得到元素
public String getElem(int index){
if(index <= 0) throw new IllegalArgumentException("没有此下表元素");
return stringsArray[index];
}
//通过值删除元素
public Boolean deleteElem(String value){
int index = -1;
if((index = containsElem(value)) != -1){
for(int i=index;i<size;i++){
stringsArray[i]=stringsArray[i+1];
}
size--;
return true;
}else{
return false;
}
}
//通过下标修改值
public void updateElemByIndex(int index,String value){
stringsArray[index] = value;
}
//遍历所有元素
public void display(){
for(int i=0;i<size;i++){
System.out.print(stringsArray[i]+"\n");
}
}
//返回数组的长度
public int getSize(){
return size;
}
public static void main(String[] args){
DisorderlyArray disorderlyArray = new DisorderlyArray(10);
disorderlyArray.insertElem("张三");
disorderlyArray.insertElem("李四");
disorderlyArray.insertElem("王五");
disorderlyArray.insertElem("赵六");
String elem = disorderlyArray.getElem(1);
System.out.print(elem);
disorderlyArray.updateElemByIndex(1,"猴八");
disorderlyArray.deleteElem("赵六");
disorderlyArray.display();
System.out.print(disorderlyArray.getSize());
}
}
无序数组的特点:插入快,假设知道下标,可以很快获取到元素
无序数组的缺点:删除慢,查找慢
有序数组(假设数组中是没有重复值的,数据是从小到大的顺序排列的)
package www.panda.array;
/**
* @Author: panda
* @Data: 2018/12/2 22:10
* @Version: 1.0
* @remark 当前是1.1 新增二分查找,以及二分查找优化
*/
public class OrderlyArray<E> {
private int[] intArray;
private int size = 0;
private static final int ERRORVALUE = -1;
public OrderlyArray(int capacity){
if(capacity <= 0) throw new IllegalArgumentException("数组的长度不能小于或等于0");
this.intArray = new int[capacity];
}
//增加元素
public void insertElem(int elem){
int index = 0;
for(;index<size;index++){
if(intArray[index] > elem){//如果当前元素大于,目标元素,结束循环
break;
}
}
for(int i=size;i>index;i--){
intArray[i] = intArray[i - 1];//前一位赋值给后一位
}
intArray[index] = elem;
size++;
}
//通过要查找的值,得到数组的下标
public int getIndex(int value){
for(int i=0;i<size;i++){
if(intArray[i] == value){
return i;
}
}
return ERRORVALUE;
}
/**
* 简单版的二分查找
* @param array
* @param value
* @return
*/
public int easyBinarySearch(int[] array,int value){
int lower = 0,upper = array.length-1,center = 0;
if(center < intArray[lower] || center> intArray[upper] || lower > upper){
return ERRORVALUE;
}
while(lower <= upper){
center = (lower+upper)/2;
if(array[center] == value){
return center;
}else if(value > array[center]){
lower = center + 1;
}else if(value < array[center]){
upper = center - 1;
}
}
return ERRORVALUE;
}
/**
* 对二分查找进行了优化,性能提高了30% 到 80%
* @param array
* @param value
* @return
*/
public static int optimizeBinarySearch(int[] array,int value){
int lower = 0,upper = array.length-1,center = 0;
while(lower + 1 != upper){
center = (upper + lower)/2;
if(array[center] < value)
lower = center;
else
upper =center;
}
if(upper >= array.length || array[upper] != value)
upper = ERRORVALUE;
return upper;
}
//通过下标获取到元素
public int getElem(int index){
if(index <= 0) throw new IllegalArgumentException("没有此下表元素");
if(index>size-1) throw new ArrayIndexOutOfBoundsException("数组下标越界了");
return intArray[index];
}
//删除数组中的元素
public void deleteElem(int elem){
int index = -1;
for(int i=0;i<size;i++){
if(intArray[i] == elem){
index = i;
break;
}
}
if(index >= 0){
for(int i=index;i<size-1;i++){
intArray[i] = intArray[i + 1];
}
size--;
}else{
//这里不自定义异常了,各位同学可以自己拓展
System.out.println("没有找到你想要删除的值");
}
}
//查询所有的元素
public void display(){
for(int i=0;i<size;i++){
System.out.print(intArray[i]+"\n");
}
}
//得到整个数组的长度
public int getSize(){
return size;
}
public static void main(String[] args){
int[] intArray ={1,2,3,4,5,6};
int i = OrderlyArray.optimizeBinarySearch(intArray,4);
System.out.println(i);
OrderlyArray<Object> objectOrderlyArray = new OrderlyArray<>(10);
int i1 = objectOrderlyArray.easyBinarySearch(intArray, 2);
System.out.println(i1);
objectOrderlyArray.insertElem(1);
objectOrderlyArray.insertElem(2);
objectOrderlyArray.insertElem(3);
objectOrderlyArray.insertElem(4);
objectOrderlyArray.deleteElem(5);
int size1 = objectOrderlyArray.getSize();
objectOrderlyArray.display();
}
}
lower和upper指向数组的第一个和最后一个非空数据项。通过设置这些变量可以确定查找的范围。然后再while循环中,当前的下标center被设置为这个范围的中间值
如果center就是我们要找的数据项,则返回下标,如果不是,就要分两种情况来考虑:如果center指向的数据项比我们要找的数据小,则证明该元素只可能在center和upper之间,即数组后一半中(数组是从小到大排列的),下轮要从后半段检索;如果center指向的数据项比我们要找的数据大,则证明该元素只可能在lower和center之间,下一轮要在前半段中检索
有序数组的特点:采用二分查找,查找速度很快(以及优化版二分查找)
有序数组的缺点:删除慢,插入慢