JAVA基礎之數組

數組的概念:
同一種數據類型的集合就叫數組。


它的第一種格式:


元素類型 [] 數組名 =new 元素類型[元素個數或數組長度];


new是數組裏面的關鍵字,在這裏可以翻譯成新建的意思。


比如: */
int [] arr = new int [8];


/*這個數組的意思就是說,新建了一個int類型,名字叫arr的數組,裏面可以存放8個數據。
在數組中,默認是給裏面存儲的數據進行編號的,從0開始。
中括號[]裏面的數字叫角標,專業名詞叫索引。
假如我們要輸出裏面的數值,打印在控制檯上,可以這樣。*/
System.out.println(arr[6]);//意思就是我們要打印新建數組裏面5號角標的數據。


/*因爲暫時還沒有給新建的數組賦值,所以裏面所有角標的默認數值是0
這是java底層的默認設置
而且因爲編號是從0開始的,我們新建數組裏面可以存放8個數據,所以最大的編號是7。


假如我們要給新建的數組裏的某個角標賦值,應該是這樣。*/
arr[7]=45;
System.out.println(arr[7]);


/*JAVA虛擬機在內存中的劃分
1.寄存器
2.本地方法區
3.方法區
4.棧內存
存儲的都是局部變量(函數內的變量都叫局部變量,包括循環結構中的變量)
而且變量所屬的作用域一旦結束,該變量自動釋放。
5.堆內存
存儲的是數組和對象(其實數組就是對象)
意思就是說凡是new都建立在堆中。
每一個變量都有默認初始化值,根據類型的不同而不同。
int 是0,小數是0.0或0.0f,boolean是false,char是'\u0000'
每一個實體存儲都有對應的首地址值。
垃圾不定時自動回收機制。

數組的第二種定義格式:
元素類型 [] 數組名 =new 元素類型[]{元素,元素,元素......}
比如: */
int [] add=new int []{23,2,45,56,54};
System.out.println(add[0]);
/*上面這種格式就是創建數組的同時,給每個角標同時賦值,數據的先後順序會被默認從0開始編號。
這種創建格式中括號[]裏面就不能填角標了,是語法錯誤,編譯會失敗。

這第二種格式還可將右邊的new關鍵詞和數據類型以及中括號[]直接省略,只將大括號裏的內容保留
就是這樣。*/
int [] aee={23,2,45,56,54};
System.out.println(aee[3]);
/*這樣也是可行的,不算語法錯誤。

如果要將數組裏面所有的值都打印出來,我們可以用循環的方法。
就是這樣: */
for (int a=0;a<aee.length ;a++ )//定義數組角標變量,從0開始,每次自增,則打印一次。
{
System.out.println("aee ["+a+"] ="+aee[a]);//aee.length是數組角標長度的意思。
//長度減一就是編號最大值。
}




System.out.println("-----------------");
/*這種將數組內的所有數據輸出查看的方式叫做 遍歷.


最值:獲取數組中的最大值或最小值。

練習:
獲取aee數組中的最大的值。

既然獲取最大值,就得進行比較,數組中的數據很多,就要進行多次比較。
所以我們可以用循環來進行操作。*/




int a=aee[0];//我們從數組的第一個編號開始,依次進行比較。
//這裏a的初始化值千萬別寫成0,雖然這道題寫0也可以,但是意義不同。
//賦值0就相當於重新找的第三方數據進行比較,而不是在數組中進行比較。




//如果非要賦值爲0.那這個0就不是具體的數據了
//而是數組的角標
for (int b=1;b<aee.length ;b++ )//這裏是遍歷aee數組中的數值。角標設定爲變量,依次自增。
{
if (aee[b]>a)//如果某個角標大於0角標。
{
a=aee[b];//就將這個大於的值賦給a,不大於則不賦值。
}
}
System.out.println("a="+a);//所以最後剩下的角標必定就是數組中最大的數。
//我們還可以用函數的方法來找出這個值。
System.out.println("-----------------");


int c=getMax(aee);//在調用函數的時候要注意,括號後面只需要寫數組名就可以了。
System.out.println("c="+c);


System.out.println("-----------------");



System.out.print("排列前的數組順序是aee[");
for (int b=0;b<aee.length ;b++ )
{
System.out.print(aee[b]+",");
}
System.out.print("]");
System.out.println();
/* //上面是排序前的數組遍歷輸出
//下面是排序後的數組遍歷輸出。
//這兩者遍歷是一回事,我們同樣可以給兩個遍歷編寫一個函數功能,以提高代碼複用性。
System.out.print("排列後的數組順序是aee[");
tangYi(aee);//這裏是調用函數內已經排列好的數組。因爲下面寫了遍歷函數,所以只能註釋掉。
for (int ew=0;ew<aee.length ;ew++ )
{
System.out.print(aee[ew]+",");
//這裏是遍歷數組裏的值。
}
System.out.println("]");*/
System.out.println("-----------------");
//下面就是調用遍歷功能函數的語句。 選擇排序
bianLi(aee);
// tangYi(aee);//這句是調用排序功能,下面開始後排序就完成了。
bianLi(aee);


System.out.println("-----------------");
//冒泡排序。
bianLi(aee);
// tangShan(aee);//這句是調用排序功能,下面開始後排序就完成了。
bianLi(aee);
System.out.println("-----------------");
int jiaoBiao=getOut(aee,54);//這是調用查找函數的語句。
System.out.println("jiaoBiao="+jiaoBiao);//輸出對應的角標值。
System.out.println("-----------------");


int[] black={11,14,24,34,45,47,56,67,89,90};
int zheban=language(black,50);
System.out.println("這個值的角標是:"+zheban);


}
public static void bianLi(int [] aee)
{//這個函數就是遍歷功能的函數。沒有返回值,故寫作void
System.out.print("[");//第一個中括號只能先輸出,因爲在循環裏的話會輸出很多次。
for (int b=0;b<aee.length ;b++ )
{//數組角標設爲變量,依次遍歷。
if (b!=aee.length-1)
{//如果角標不是最大角標值,就輸出當前角標對應的數值,並在後面輸出逗號。
System.out.print(aee[b]+",");
}
else//如果角標是最大角標值,證明遍歷結束,輸出當前角標對應的數值,並在後面輸出第二個中括號。
{
System.out.println(aee[b]+"]");
}
}
}




public static int getMax(int []aee)
{
int c=aee[0];
for (int b=1;b<aee.length ;b++ )
{
if (aee[b]>c)
{
c=aee[b];
}
}
return c;
}
/*數組的選擇排序
將數組中的數值按照從小到大的順序依次排列。
選擇排序的思想是將某一個角標依次和所有角標進行比較,確定最值後賦值給相應的角標。

int [] aee={23,2,45,56,54};

比如上面的aee數組,裏面的數值順序是雜亂的,我們要通過代碼將裏面的數值重新排序。
要排序的話,就得知道數值之間的大小,就得需要進行比較,
數組裏面所有的數值都得比較就得需要遍歷數組裏的數據。
而且排序本身還涉及到數值互換的問題。

從0角標開始,依次比較,將最小的值賦給0角標。
從1角標開始,依次比較,將第二小的值賦給1角標。
在每個角標進行比較的時候,上一個角標是不用在比較的,因爲已經比較過,已經確定了位置。

既然如此,代碼就應該寫成這樣*/
public static void tangYi(int [] aee)
{//我們將這種排序方法定義在函數裏面。我們只是將數組裏數值的順序打亂而已,所以不需要返回數組,
//所以用void
for (int a=0;a<aee.length-1 ;a++ )//外循環是要比較的角標,最後一個角標無需比較,因爲沒有
{//角標可以跟它比較,而角標自己比較又是毫無意義的。
for (int b=a+1;b<aee.length ;b++ )//內循環是被比較的角標,同一個角標無需比較,所以
{//我們將外角標的數值加上1就是它要依次比較的角標。
if (aee[a]>aee[b])//判定,如果a角標大於要比較的b角標,則將他們位置互換,
{//達到從小到大依次排列的目的。
int c=aee[a];
aee[a]=aee[b];
aee[b]=c;
/*上面三行語句就是前面學過的數值互換的方法,用定義第三方變量的方法來實現。
先將大的值賦值給臨時第三方變量,再將小的值賦給原先大的值進行數值覆蓋
最後將臨時變量裏的值賦給原先較小的值,數值互換就完成了。*/
}
}
}
}
/*冒泡排序,這是另一種排序思想。
也是將數組中的數值按從小到大的順序排列。
和選擇排序的區別就是,它是相鄰兩個角標進行比較,
比如0角標和1角標比較,1角標和2角標比較,2角標和3角標比較,以此類推...、
他的代碼寫法是這樣:*/
public static void tangShan(int [] aee)
{
for (int a=0;a<aee.length-1 ;a++ )
{//外循環和選擇排序是一樣的,最後一個角標無需比較,因爲沒有跟他要進行比較的角標。
for (int b=0;b<aee.length-1-a ;b++ )
{//因爲冒泡排序是相鄰比較,也就是aee[b]與aee[b+1]相比較
//當b的角標值爲數組中最大角標aee.length-1時,aee[b+1]就會越界,而且也沒有比較的必要。
//因爲那時就只剩下aee.length-1這一個角標了,所以這裏要減一。
//我們只需要aee.length-2和aee.length-1(也就是aee[b+1])比較就足夠了。
//減a的原因是每次循環比較後,就有一個最值確定,就沒有比較的必要。
//隨着循環比較次數的增加,最值的確定也在增加,這個增加的幅度剛好和外循環的a是一樣的
//所以我們要減a。
if (aee[b]>aee[b+1])
{//冒泡排序是相鄰的,所以我們用aee[b]和aee[b+1]相比較。
int c=aee[b];
aee[b]=aee[b+1];
aee[b+1]=c;
//執行語句是用第三方變量的方式進行位置互換,這個好理解。
}
}
}
}
/*以上兩個排序我們發現,if語句裏面的執行語句都是在進行互換,我們也可以用互換做一個函數功能。*/
public static void swap(int [] aee,int a,int b)
{//因爲我們是在數組中替換兩個數值的位置,所以我們得把數組的變量提取出來,這裏就是三個變量。
int c=aee[a];
aee[a]=aee[b];
aee[b]=c;
}
//下面是選擇排序的執行語句調用
/* public static void tangYi(int [] aee)
{
for (int a=0;a<aee.length-1 ;a++ )
{
for (int b=a+1;b<aee.length ;b++ )
{
if (aee[a]>aee[b])
{
swap(aee,a,b);

}
}
}
}
//下面是冒泡排序。
public static void tangShan(int [] aee)
{
for (int a=0;a<aee.length-1 ;a++ )
{
for (int b=0;b<aee.length-1-a ;b++ )
{
if (aee[b]>aee[b+1])
{
swap(aee,b,b+1);
}
}
}
}*/
/*選擇排序和冒泡排序還有互換函數,還有調用函數的正確寫法,都要重點掌握。


數組的常見功能,查找。
查找某個數值在數組裏的角標位置。*/
public static int getOut(int [] aee,int key)
{//key就是具體的數值。
for (int a=0;a<aee.length ;a++ )
{//遍歷數組。
if (aee[a]==key)
{//如果某個角標裏的數值與我們需要找的數值相等,那麼就返回這個數值的角標值。
return a;
}
}
return -1;//如果沒找到,就返回-1,因爲角標是從0開始排序的,返回-1就能代表沒有找到這個數值。
}
/*以上的角標查找方法是基於無序排列的數組的,而對於有些有序排列的數組,我們還有另外一種
查找方法,就是折半查找,也叫做二分查找。

有序排列的意思就是從小到大,或從大到小的排列。
我們要尋找其中某一個數值的角標,想要快速的找到其角標的話,最好的方法就是將其角標長度一分爲二,
以縮小最佳範圍。這種方法我們需要知道角標頭,角標尾和中間角標。
角標頭我們用min來表示 中間角標用mid來表示 角標尾我們用max來表示。
比如下面這個數組:
11  14  24  34  45  47  56  67  89  90

0   1   2   3   4   5   6   7   8   9
 
min             mid                    max
這就是這個數組中各項數據的指標和具體位置。我們知道,中間角標的位置其實就是角標頭和角標尾相加再除以2
所得到的結果,在java中,整數做運算之後還是整數,如果有小數的部分就直接捨棄掉.
上面數組角標頭和角標尾相加除以2之後的結果是4,所以4是中間角標。
 
比如我們想要知道56這個數值在數組中的角標位置,首先就是確定中間角標的位置縮小範圍,
如果比中間角標裏的數值小我們就將目標放到左邊去進一步縮小範圍,反之就是右邊。
很明顯,56這個值在4角標的後面,所以我們還得看向右邊。
然後重複第一步,把右邊這一段看成一個整體,再一分爲二,取其中間角標再來進行判斷。
所以我們首先要確定好下一段,這個下一段肯定就是中間角標值的下一個角標值爲角標頭,角標尾不變。
這裏要注意,是不可能用中間角標值作爲下一段的角標頭的,因爲中間角標是用來說縮短範圍的,數值不是比它裏面的數值大就是小,如果是等於的話我們就不用再進行判斷了。
中間角標值的下一個角標值作爲角標頭,然後又是這個角標加上角標尾,再除以2確定中間角標值用於判斷縮小範圍如此循環,因此,我們的代碼就可以這樣寫。*/
public static int language(int[]black,int key)
{//定義折半查找功能函數。
int min,mid,max;//定義角標頭,尾,中間三個角標值的變量。
min=0;//頭爲min
max=black.length-1;//尾爲max,這裏先定義max再定義mid是因爲java是從上往下執行的,而max的值我們還沒
//確定,如果先定義mid的話,會找不到max,會報錯。
mid=(min+max)/2;//中間爲mid

while (black[mid]!=key)//進入多次循環
{
if (key>black[mid])//如果查找的值大於中間角標,則向右。
{
min=mid+1;//角標頭就爲中間值加1.
}
else if (key<black[mid])//如果小於,則向左。
{
max=mid-1;//角標尾就爲中間值減1。
}
if (max<min)//如果角標尾比角標頭大,說明沒有這個值。
{
return min;//就返回-1,循環就此結束。
}
mid=(min+max)/2;//首輪查找完後,min或max都改變了位置,所以我們要重新計算mid的值。
}
return mid;//如果循環結束不是因爲返回-1,說明就查找到了這個數,返回我們找到的這個數的角標
//也就是中間值,就可以了。
}
/*折半查找練習
這是一道面試題。
 
在一個有序的數組中插入一個數值,不改變數組有序排列的基礎下,求這個數值應該放在哪個角標位置。
 
這是一道思想上的問題,我們要想到,只要是有序查找,最快的方法都是折半查找。我們要尋找這個數的角標位置
在查找的時候首先可以肯定是找不到的,程序會返回-1,這個時候我們就知道,在返回-1這個結果時,
相當於max跑到了左邊,而min卻要跑到右邊,,剛好要動時,程序就返回了,停止循環了,
所以我們在這個時候,只要返回的是min就能確定他的角標值。
發佈了47 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章