數組是應用最廣泛的一種數據結構,常常被植入到編程語言中,作爲基本數據類型使用,因此,在一些教材中,數組並沒有被當做一種數據結構單獨拿出來講解(其實數組就是一段連續的內存,即使在物理內存中不是連續的,在邏輯上肯定是連續的)。其實沒必要在概念上做糾纏,數組可以當做學習數據結構的敲門磚,以此爲基礎,瞭解數據結構的基本概念以及構建方法
數據結構不僅是數據的容器,還要提供對數據的操作方法,比如檢索、插入、刪除、排序等。
無序數組(假設數組中,沒有重複的值)
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之間,下一輪要在前半段中檢索
有序數組的特點:採用二分查找,查找速度很快(以及優化版二分查找)
有序數組的缺點:刪除慢,插入慢