(八)數組以及排序和查找
JavaSE(八)
--數組以及排序和查找
一、數組的定義
三種定義方法:
int b[]=new int[5];
Int []b=new int[5];
int[] a=new int[5]; (建議使用這種定義方法) //必須規定數組長度,因為在編譯的時候就要分配內存。
我們也可以在定義的時候就初始化數組
Int[] a={1,2,3,3,5};
這默認了數組a的長度是5.
分配內存詳情如下:
開辟一塊內存,有5個小塊,a指向數組的首地址。
int[][] b=new int[5][]; //至少確定第一維的個數(即數組行數)才不會提示有錯。第二維的個數可以暫時不固定。
int[][][] b=new int[5][][]; 同理三維數組長度也至少確定第一維的個數才不會提示有錯。也可以確定一二維的個數,
二、數組的遍歷。
①只有確定了所有維數去遍歷一個數組才不會報錯。
②數組下標從0開始,到n-1結束(n為該維長度)。比如int[] s=new int[3]。這個數組長度為3,s[0],s[1],s[2]就是這三個值,訪問s[3]是會報錯的,報數組越界異常java.lang.ArrayIndexOutOfBoundsException。
為什麽是0開始呢?跟外國人建房子習慣有關,因為外國人建房子都會建地下室,地下室不就是0層了(地下一層也叫地上0層,因為在地上一層的下一層
③沒有初始化的時候,int數組所有元素值為0,float、double所有元素值為0.0,String所有元素值為null。Char所有元素都是一個空格(而不是什麽都沒有)。
④ char[] c=new char[a]; //a為已知常數
遍歷方式一(for循環,用int變量控制):
for(int i=0;i<a;i++){
System.out.println(c[i]);
}
遍歷方式二(for循環):
for(char p:c){
System.out.println(p);
}
char[][] c=new char[a][b]; //a,b為已知常數
遍歷方式一(for循環,用
for(int i=0;i<a;i++){
for(int j=0;j<b;j++){
System.out.println(c[i][j]);
}
}
遍歷方式二(for循環):
for(char i[]: c){
for(char j:i){
System.out.println(j);
}
}
三、排序
1.排序法種類:
內部排序: 指將需要處理的所有數據都加載到內部存儲器中進行排序。(包括交換式排序法、選擇式排序法、插入式排序法)
外部排序: 數據量過大,無法全部加載到內存中,需要借助外部存儲進行排序。(包括合並排序法和直接合並排序法)
交換式排序法,數據比較後,依判斷規則對數據位置進行交換,以達到排序的目的。
①冒泡排序法(Bubble sort)
②快速排序法(Quick sort)
選擇式排序法,是從欲排序的數據中,按指定的規則選出某一元素,經過和其他元素重整,再依原則交換位置後達到排序的目的。
①選擇排序法(Select sort)
②堆排序法(Heap Sort)
插入式排序法,是對欲排序的元素以插入的方式找尋該元素的適當位置,以達到排序的目的。
①插入排序法(Insertion sort)
②希爾排序法(Shell sort)
③二叉樹排序法(Binary-tree sort)
其它排序法。
①選堆排序法
②合並排序法
2.冒泡排序法
public static int[] bubble(int[] array){
int temp=0;
for(int i=0;i<array.length;i++){ //外層循環,決定一共走幾趟
for(int j=0;j<array.length-1-i;j++){ //內層循環,開始逐個比較,發現前一個數比後一個數大則交換
if(array[j]>array[j+1]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
// array[j]=array[j]+array[j+1];
// array[j+1]=array[j]-array[j+1];
// array[j]=array[j]-array[j+1];
}
}
}
return array;
}
3.選擇排序法:
public static int[] select(int[] array){
int temp=0;
for(int j=0;j<array.length;j++){
//我認為第一個數就是最小的
int min=array[j];
//記錄最小數的下標
int minIndex=j;
for(int k=j+1;k<array.length;k++){
if(min>array[k]){
//修改最小
min=array[k];
minIndex=k;
}
}
temp=array[j];
array[j]=array[minIndex];
array[minIndex]=temp;
}
return array;
}
4.插入排序法:
public static int[] insert(int[] array){
for(int i=1;i<array.length;i++){
int insertVal=array[i];
//insertval準備和前一個數比較
int index=i-1;
while(index>=0&&insertVal<array[index]){
//把array[index]向後移動
array[index+1]=array[index];
//讓index向前移動
index--;
}
//將insertVal插入到適當位置
array[index+1]=insertVal;
}
return array;
}
5.快速排序法(交換式排序法):
public static int[] quick(int[] array){
int left=0;
int right=array.length-1;
return px(left, right, array);
}
public static int[] px(int left,int right,int[] array){
int l=left,r=right;
int privot=array[(l+r)/2];
int temp=0;
while(l<r){
while(array[l]<privot) l++;
while(array[r]>privot) r--;
if(l>=r) break;
temp=array[l];
array[l]=array[r];
array[r]=temp;
if(array[l]==privot) --r;
if(array[r]==privot) ++l;
}
if(l==r){
l++;
r--;
}
if(left<r) px(left,r,array);
if(right>l) px(l, right, array);
return array;
}
5.幾種排序方法運行時間的比較:
隨機生成十萬個1~10000的數並存放到數組中。
int[] array=new int[100000];
for(int i=0;i<array.length;i++){
array[i]=(int)(Math.random()*10000);
}
排序前打印系統時間,排序後打印系統時間。
Calendar calendar=Calendar.getInstance();
System.out.println("排序前:"+calendar.getTime());
bubble(array);
calendar=Calendar.getInstance();
System.out.println("排序後:"+calendar.getTime());
發現排序時間大約是16秒
換成選擇排序法:
Calendar calendar=Calendar.getInstance();
System.out.println("排序前:"+calendar.getTime());
select(array);
calendar=Calendar.getInstance();
System.out.println("排序後:"+calendar.getTime());
大約4秒鐘
換成插入排序法:
Calendar calendar=Calendar.getInstance();
System.out.println("排序前:"+calendar.getTime());
insert(array);
calendar=Calendar.getInstance();
System.out.println("排序後:"+calendar.getTime());
大約3秒鐘
換成快速排序法:
Calendar calendar=Calendar.getInstance();
System.out.println("排序前:"+calendar.getTime());
quick(array);
calendar=Calendar.getInstance();
System.out.println("排序後:"+calendar.getTime());
幾乎沒有排序時間。
6.淺測快速排序法
剛剛測試十萬個數發現幾乎沒有排序時間。
我又測試了一百萬個,發現還是沒什麽排序時間。
直到測試了一千萬個:
發現僅有1s的排序時間。
那是不是快速排序法就是最好的呢?
不是,快速排序法在運行的時候對cpu和內存的占用是非常大的,其他排序法並不像快速排序法占用這麽多。
四、查找
在java中我們常用的查找有兩種
①順序查找(最簡單,效率最低的查找方法,一個一個找)
②二分查找(先排序,再擇中查找,效率高)
public static void find(int val,int[] array){
int leftIndex=0;
int rightIndex=array.length-1;
f(leftIndex, rightIndex, val, array);
}
public static void f(int leftIndex,int rightIndex,int val,int array[]){
int midIndex=(rightIndex+leftIndex)/2;
int midVal=array[midIndex];
if(rightIndex>=leftIndex){
if(midVal>val){
f(leftIndex, midIndex-1, val, array);
}else if(midVal<val){
f(midIndex+1, rightIndex, val, array);
}else if(midVal==val){
System.out.println("找到此數,下標為"+midIndex);
}
}
}
二分查找要求數組已經是排好序(從小到大)的數組,所以我們一般先排序再使用二分查找。
(八)數組以及排序和查找