5
5-1.1 陣列的意義 變數是指程式中可以用來儲存資料空間的名稱,使用
者可以用它來存放任何數值、文字……等資料,如同每個人有一個名字一樣,當程式中需要使用某變數時,可以用此名稱來稱呼它。
若程式中需要一系列具有相同型態的多項資料時,如果一個一個加以設定成變數的話,對於量小的資料,可能還好,但對於量大的資料,可能吃不消,光是定義變數名稱,就得想好幾個。這時如果使用陣列來代表這一系列的多項資料,便輕鬆多了!
其實,可以將陣列想成電腦中一塊連續的記憶體,這塊連續記憶體被分成許多相同大小的小空間,每個小空間會依照順序從 0 開始給予一個編號,日後若需要某個小空間的資料,就可以用編號來存取該小空間的資料。
6
一維陣列:
依照排列的方式,陣列分為一維陣列和多維陣列。
一維陣列是指這些小空間是以直線的方式排列,而且每個小空間都依序編號來區別,此順序編號稱為索引值( Index ),而陣列中每一個小空間所存放的資料稱為元素( Element )。
9
5-1.2 一維陣列的宣告
在程式中想要使用陣列儲存資料時,必須先為陣列命名,以便在程式中呼叫。
陣列命名的原則與變數都是一樣的,而且資料型別也與變數相同,所以如果對變數的命名方式與變數資料型別都了解的話,可以直接應用在陣列中。
在 Java 中,只要在陣列名稱前面加上資料型別的名稱(資料的型別與變數的型別一樣,有位元組、短整數、整數、長整數、浮點數、倍精度浮點數、布林、字元等),就達到宣告的動作。
10
以下是宣告一維陣列的語法:
在宣告陣列時,如果不指定初始值,就要利用關鍵字 new 配置記憶體空間給該陣列,其語法如下:
上述語法中的陣列名稱只要依照變數的命名規則命名即可,比較特別的是,利用 new 配置記憶體空間時,必須在資料型別後面加上 [] ,並在 [] 中填上此陣列的大小( Size ),例如: int X[]=new int[7] ,就表示陣列名稱為 X ,而有 7 個整數元素的陣列。
11
以下是宣告不同資料型別的一維陣列,其程式碼如下:
指定陣列的資料型別後,陣列內各元素都是相同的資料型別,例如: short b[]=new short[11] ,表示系統連續分配了 11 個單位的短整數空間給 b 陣列,若一個短整數佔用 2 Bytes ,則 short b[]=new short[11] 就是分配了 22 Bytes 。
12
以下是同樣資料型別的陣列一起放在資料型別的後面,宣告的程式碼如下:除了將多個陣列一行一行分別宣告以外,也可以將多個同樣資料型別的陣列一起放在資料型別的後面,並以逗號 , 分隔;但若是不同資料型別的陣列要在同一行宣告,則要以分號 ; 分隔,例如:
13
5-1.3 一維陣列初始值的設定
當宣告一維陣列名稱 X 後,就可以一一表示陣列內的各元素,第 1 個元素以 X[0] 表示,第 2個元素以 X[1] 表示,第 3 個元素以 X[2] 表示,第 4 個元素以 X[3] 表示,第 5 個元素以 X[4]表示,第 6 個元素以 X[5] 表示,第 7 個元素以 X[6] 表示。
14
下圖是宣告內含 7 個元素的一維陣列後,陣列內各元素表示的示意圖:
跟變數一樣,宣告陣列以後,也可以指定陣列的初始值,在尚未指定初始值前,每個陣列元素的初始值皆預設為 0 或 false (布林)。
與變數最大的不同是,變數只是代表一個資料,所以其初始值只要指定一個就可以了,但陣列是代表一系列具有相同型態的多項資料,所以要指定陣列的初始值時,要一一指定陣列內各元素的初始值。
15
指定陣列初始值的語法如下:
不過如果這樣一行一行寫,實在是太麻煩了,所以通常會在陣列名稱後面加上 ={} ,在 {} 內依序寫上各元素的初始值,並以逗號 , 分隔每個元素即可;此時可以省略陣列大小的設定,編譯程式會根據初始值的個數自動判斷陣列的大小,其語法如下:
17
宣告陣列後,可能會使用到下列的功能:
取得陣列的大小:利用陣列的 length函式可以取得陣列的大小,也就是陣列的元素個數,其語法如下:
改變陣列的大小:在 Java 中只要重新配置記憶體位置,即可動態修改陣列的大小,而修改陣列的大小後,陣列中的元素內容會被清空,預設為 0 或 false (布林),例如下面的程式碼將陣列大小 5修改為 8 :
20
上述的程式碼分析如下:1. 第 4 行宣告整數陣列 x ,並設定初始值,所以不需要利用關鍵字 new 就
可以自動配置記憶體,而第 5 行利用 x.length 取得陣列大小時,總共有 5個陣列元素。
2. 第 7~9 行利用迴圈顯示陣列 x 中的每個元素內容,因為陣列的第一個索引值為 0 ,陣列大小為 x.length ,所以第 7 行指定計次變數 i 的初始值為0 ,並設定條件表示式為 i< x.length 。
3. 第 10 行利用關鍵字 new修改陣列 x 的大小為 3 ,就是只能儲存 3 個元素,所以第 4 行設定的陣列初始值已經被清空了!
4. 第 13~17 行的迴圈是用來反覆要求使用者輸入整數。5. 第 14 行是反覆要求使用者輸入整數,此敘述內含計次變數 i ,所以第 1次執行迴圈時,會顯示“請輸入第 1 個整數”;第 2次執行迴圈時,會顯示“請輸入第 2 個整數”……。第 16 行是反覆將使用者輸入的數指定給 x[i] ,所以第 1次執行迴圈時,會將所輸入的整數指定給 x[0] ;第 2次執行迴圈時,會將所輸入的整數指定給 x[1] ,以此類推。
6. 第 18~19 行的迴圈是用來反覆顯示使用者輸入的整數,第 18 行是指定計次變數 i 的初始值和條件表示式,而第 19 行是迴圈內要反覆執行的敘述,意即反覆顯示各元素的值,也就是 x[0] 、 x[1] 、 x[2]…… 等值。
26
5-1.4 二維陣列的宣告
在 5-1.2 和 5-1.3節中介紹的陣列都只是一維的,事實上,陣列可以是多維( Multi-Dimension )的,例如:二維、三維、四維、……,甚至多達數十維,比較常見的是二維陣列。
27
何時需要使用二維陣列來表示資料呢?
簡單的說,如果資料可以以表格方式來呈現的話,就可以使用二維陣列來表示表格內的所有資料,例如:有一學生成績表格,內含 5 個學生的成績資料,每位學生有學號、國文、英文、數學、自然、社會等資料,可以整理成如下的表格:
28
以下是宣告二維陣列的語法:
如果利用一維陣列來儲存這些資料的話,可能需要 6個陣列,例如: id[] 、 chinese[] 、 english[] 、 math[] 、nature[] 、 society[] ,而只需 1 個二維陣列就可以將所有的資料儲存起來。
宣告二維陣列時,只要在二維陣列名稱前面加上資料型別名稱,就達到宣告的動作,資料型別有位元組、短整數、整數、長整數、浮點數、倍精度浮點數、布林、字元等。
二維陣列與一維陣列相同,如果不指定初始值,就要利用關鍵字 new 配置記憶體空間給該陣列,其語法如下:
29
利用關鍵字 new 配置記憶體空間時,須在資料型別後面加上 [][] :上述語法中的陣列名稱只要依照變數命名規則來命名即可,比較特別的是,利用 new 配置記憶體空間時,必須在資料型別後面加上 [][] ,並在 [][] 中分別填上列數和行數。
30
以上述表格為例,可以宣告二維陣列如下:
宣告此 grade 陣列後,可得知第一個(可以想成列)索引值範圍為 0~4 ,第二個(可以想成行)索引值範圍為 0~5 ,此陣列內含 5*6 個元素的資料。
33
下面舉例,宣告二維陣列名稱 grade ,可分別指定陣列內元素的值: 若以下列成績表格為例,當宣告二維陣列名稱 grade
後,就可以分別指定陣列內元素的值,例如: grade[0][0]=10001 , grade[0][1]=94 , grade[0][2]=61 , grade[0][3]=61 , grade[0][4]=98 , grade[0][5]=68 , grade[1][0]=10002 , grade[1][1]=85 , grade[1][2]=92 ,……。
37
二維陣列與一維陣列相似,可能會使用到下列幾項功能: 取得陣列的列數:利用 length函式可以取得陣列的列
數,其語法如下:
取得某列的元素個數:利用 length函式可以取得二維陣列中某列的元素個數,其語法如下:
改變陣列的大小:利用關鍵字 new 可以修改陣列的大小,而陣列中的元素內容會被清空,預設為 0 或 false(布林),例如下面的程式碼將 5 列 6 行的陣列修改為 8 列 8 行的陣列:
38
以下範例應用二維陣列,將三次成績的總平均計算出來,其程式碼如下:以下這個範例就是應用二維陣列,讓使用者依序輸入 4 個學生的學號、第一次月考成績、第二次月考成績和期末考成績的資料,然後將三次成績的總平均計算出來,以二維陣列儲存並顯示這個成績表,其程式碼如下:
41
上述應用二維陣列計算三次總平均的程式碼分析如下 -1 :1. 第 5 行宣告二維陣列變數,因為有 4 個學生,每個學生將記錄 5種
資料(包含總平均),所以可以宣告 int grade[][]=new int[4][5]; 。2. 第 8~23 行的迴圈是用來反覆要求使用者輸入資料,第 8 行指定計次變數 i 的初始值和條件表示式(有四個學生,所以可以設定初始值從 0 到 grade.length ),而第 9~22 行是迴圈內要反覆執行的敘述。
3. 第 9~22 行會反覆要求使用者輸入資料,第 1次執行迴圈時, i=0 ,所以會將使用者輸入的資料(也就是第 0+1 個學生的資料)依序指定給 grade[0][0] 、 grade[0][1] 、 grade[0][2] 和 grade[0][3] ,並將計算出此學生成績的總平均指定給 grade[0][4] ;第 2次執行迴圈時, i=1 ,所以會將使用者輸入的資料(也就是第 1+1 個學生的資料)依序指定給 grade[1][0] 、 grade[1][1] 、 grade[1][2] 和 grade[1][3] ,並將計算出此學生成績的總平均指定給 grade[1][4] ,以此類推。
4. 第 24 行是顯示成績表的標題列,利用 "\t" 可以在顯示的資料後面產生一個水平定位點,以便與成績等資料對齊。
42
上述應用二維陣列計算三次總平均的程式碼分析如下 -2 :5. 第 26~32 行的迴圈會顯示使用者輸入的資料,以及計算總平均的
資料。6. 第 26 行的 grade.length 表示 grade 陣列中有幾列資料,而第 28 行
的 grade[i].length 則表示 grade 陣列第 i 列中有幾個元素。7. 第 28~30 行為內層迴圈,當第 26 行外層迴圈的計次變數等於 0 ,
內層迴圈第一次執行時,計次變數 j=0 ,會顯示 grade[0][0] 元素的資料;內層迴圈第二次執行時,計次變數 j=1 ,會顯示 grade[0][1] 元素的資料,以此類推。當外層迴圈第二次執行時, i=1 ,內層迴圈第一次執行時,計次變數 j=0 ,會顯示 grade[1][0] 元素的資料,以此類推。
8. 第 29 行敘述內含 "\t" ,可以在顯示的資料後面產生一個水平定位點,以便與其他各列資料對齊。
47
5-2.1 排序 排序( Sort )是將資料由小到大或由大到小依序排列,
由小到大依序排列者稱為遞增排序,由大到小依序排列者稱為遞減排序。
何謂大?何謂小?如果是數值資料,則數值越大者越大;如果是字串資料,則中文字 > 小寫英文字母 > 大寫英文字母 > 數字,而中文字又以編碼越多者越大。
在 Java 中可以利用迴圈和條件判斷等技巧,撰寫程式來排序資料,也可使用內建的函式來排序。
依據不同特性的資料,分別有許多排序演算方法,較知名的排序方法如選擇排序法( Selection Sort )、交換排序法( Exchange Sort )、插入排序法( Insertion Sort )等。
48
使用選擇排序法排序:
選擇排序法其基本想法是指在有 n 個元素的陣列中,選擇出關鍵值最小的元素,然後在剩下的 n-1 個元素中再選出關鍵值最小的元素,重複這種程序,直到第 n-1 個回合,就可完成排序作業。
49
選擇排序法有多種排序策略,下面就是選擇排序法策略的一種:1. 第一回合:將第 1 位置的資料和其他位置的所有資料做比較。
當第 1 位置的資料大(小)於其他資料時,則兩個資料交換位置,使第 1 位置的資料永遠保持比較小(大)。
交換位置後,再將交換位置後的第 1 位置的資料與其他位置的資料相比較,直到所有的資料比較完。
第一回合比較完時,最小(大)的資料一定會出現在第 1 位置。2. 第二回合:因第 1 位置的資料已經是最小(大)的,所以將第 2
位置的資料與第 3 、 4 、……等位置的資料相比較。 當第 2 位置的資料比其他位置的資料大(小)時,就交換位置。 以此規則一直進行比較的動作。
3. 當此範圍內有 N 個資料時,需進行 N-1 個回合,才能將所有的資料由小到大(由大到小)依序排列完成。
50
下面範例利用選擇排序法的排序策略,將以下十個數字由小排到大,程式碼如下:
下面這個範例將用選擇排序法的排序策略,將60 、 100 、 80 、 30 、 90 、 70 、 20 、 50 、10 、 40 等十個數字由小排到大,其程式碼如下:
51
上述利用選擇排序法的排序策略的程式碼分析如下 -1 :
1.第 3 行利用一維陣列存放要比較的 10 個數。2.第 4 行宣告 4 個變數,其中 i 、 j 、 k 三個變
數都與次數有關,將應用在迴圈敘述內,而變數 temp 比較特別,用以暫存數值資料之用。
3.第 5~18 行是巢狀迴圈,外層迴圈設定計次變數 i 從 0 到 8 ,所以第一次執行時, i=0 ,此時內層迴圈計次變數 j 會從 i+1 到 9 ,也就是從 1 到 9 ,而內層迴圈所要反覆執行的敘述是第 7~10 行。
52
上述利用選擇排序法的排序策略的程式碼分析如下 -2 :4. 第 7~10 行程式碼是將資料做比較,如果比較後,索引值小的元
素資料大於索引值大的元素資料,就將索引值小的元素資料(比較大)先指定給 temp 變數,然後將索引值大的元素資料(比較小)指定給索引值小的元素,再將暫存在 temp 變數中原索引值小的元素資料指定給索引值大的元素,形成兩個資料交換位置。
53
上述利用選擇排序法的排序策略的程式碼分析如下 -3 :
5. 如果將第 7 行的 x[i]>x[j] 改成 x[i]<x[j] ,則會將資料遞減排序。
6. 現將第一回合和第二回合實際比較的流程說明如下:
55
上述利用選擇排序法的排序策略的程式碼分析如下 -5 :
7. 第 13~17 行是內層巢狀迴圈後的敘述,用以將每一回合比較後的結果顯示出來。而此敘述又內含迴圈,以 k 為計次變數,反覆將陣列 x 中的各元素的資料顯示出來。請注意,此處必須使用不同於第 5 行和第 6 行的計次變數,否則會產生錯誤的訊息。
57
使用氣泡排序法排序:
氣泡排序法是交換排序法的一種,其原理是逐一把陣列中兩兩相鄰的資料做比較,並將比較後的結果依大小順序排序,直到所有資料皆不需要交換位置即可。
前面所介紹之選擇排序法的排序策略每次都是固定以某個數與其他數做比較;而氣泡排序法則是兩個兩個做比較,第 1 位置與第 2 位置做比較,第 2 位置與第 3 位置做比較,第 3 位置與第 4 位置做比較……。
58
氣泡排序法的排序策略說明如下:1. 第一回合:
將第 1 位置的資料與第 2 位置的資料做比較,若第 1 位置的資料大(小)於第 2 位置的資料時,兩個資料交換位置。
再將第 2 位置的資料與第 3 位置的資料做比較,若第 2 位置的資料大(小)於第 3 位置的資料時,兩個資料交換位置。
以此方法繼續,直到所有的資料比較完。 第一回合比較完成時,最大(小)的資料一定會往最右邊移動。
2. 第二回合: 同樣將第 1 位置的資料與第 2 位置的資料做比較,若第 1 位置的資料大
(小)於第 2 位置的資料時,兩個資料交換位置。 接著再將第 2 位置的資料與第 3 位置的資料做比較,若第 2 位置的資料
大(小)於第 3 位置的資料時,兩個資料交換位置。 以此方法繼續,直到第 N-1 個資料比較完(因第一回合,已經將最大
(小)的資料放到最右邊了,所以第二回合時,不需要比較最右邊的資料),一直以此規則進行比較的動作。
3. 當此範圍內有 N 個資料時,需進行 N-1 個回合,才能將所有的資料由小到大(由大到小)依序排序完成。
59
下面範例利用氣泡排序法,將以下 7 個數字由小排到大,其程式碼如下: 下面這個範例將利用氣泡排序法,將 60 、 100 、 80 、
30 、 90 、 70 、 20 等七個數字由小排到大,其程式碼如下:
62
內建排序函式— sort 排序
前面所介紹的選擇排序法和氣泡排序法對很多初學者來說,剛開始是難了點,沒關係, Java提供了一種 sort函式,只要呼叫這個函式,就可以將指定陣列內的元素由小到大遞增排序。
使用 sort函式前必須以 java.util.Arrays載入 Arrays類別,而 sort函式使用語法如下:
64
上述程式碼分析如下:
1. 第 1 行必須載入 Arrays類別才可以使用 sort函式。
2. 第 12 行利用 sort函式對 x 陣列由小到大排序。3. 第 7~9 與 14~16 行分別將排序前與排序後的
資料顯示出來。
68
5-2.2 最大值和最小值
要如何知道一群資料的最大值和最小值?如果資料未經排序,則可以利用兩兩比較的方法,來求得最大和最小值;如果已經將資料排序,則第一個元素的資料和最後一個元素的資料就是該群資料的最小或最大值。
69
下面範例是利用 sort函式,取得某群資料中的最小值和最大值,其程式碼如下: 下面將利用 sort函式將資料排序,以取得某群資料中
的最小值和最大值,利用 sort函式排序後,第一筆資料就是最小值,而最後一筆資料則是最大值,其程式碼如下:
70
上述利用 sort函式,取得某群資料中的最小值和最大值的程式碼分析如下:
1. 第 8 行利用 sort函式將 x 陣列中的資料遞增(由小到大)排序。
2. 第 9 和 10 行利用 System.out.println顯示 x 陣列中的第一筆與最後一筆元素,也就是最小值與最大值。
75
5-2.3 搜尋
搜尋( Search )是從一群資料中找到符合條件的資料。
在資料結構的書中會介紹各式各樣的搜尋方法,常用的方法有循序搜尋法( Sequential Search )、二分搜尋法( Binary Search )、插補搜尋法( Interpolation Search )……等。
78
上述利用循序搜尋法搜尋的程式碼分析如下:1. 第 5 行宣告 i 為次數變數, seq 為使用者輸入要搜尋
的數字,一維陣列 x 存放要搜尋的原始資料。2. 第 9~14 行利用迴圈和判斷式來搜尋指定的資料— se
q 。3. 第 10~13 行是迴圈內的判斷式,用以判斷該資料是否為想要尋找的資料— seq ,若是,則執行第 11 和12 行,顯示出索引值,並強迫跳出迴圈;如果不是,則反覆執行迴圈,直到次數變數不符合時。
4. 第 15~17 行利用判斷式,設定當在陣列中循序搜尋資料都搜尋不到時,顯示欲搜尋的資料不在陣列中的訊息。
80
使用二分搜尋法搜尋:
二分搜尋法是指將資料先依序排好,然後放在 x 陣列中,接著將最大索引值 max 和最小索引值 min 相加除以 2 ,取得中間索引值 mid ,將 x[mid] 與搜尋的資料seq做比較:1. 當 x[mid]==seq 時,表示找到資料。2. 當 x[mid] 的資料大於 seq 時,表示資料落在比較小的那半部,所以將 max 設定成 mid-1 ,然後再取小的那半部之中間索引值的資料與 seq做比較,直到找到為止。
3. 當 x[mid] 的資料小於 seq 時,表示資料落在比較大的那半部,所以將 min 設定成 mid+1 ,然後再取大的那半部之中間索引值的資料與 seq做比較,直到找到為止。
81
下面範例利用二分搜尋法搜尋,其程式碼如下: 下面這個範例使用二分搜尋法的方式,先將原本的陣
列由小到大排列,然後讓使用者輸入想要搜尋的數字,再顯示該數字在已排序之數字陣列中的索引值,其程式碼如下:
84
上述利用二分搜尋法搜尋的程式碼分析如下:1. 第 7 行利用 sort函式讓資料由小到大排序。2. 第 17~27 行是條件迴圈,第 18 行利用 min 和 max 值
取得陣列索引值的中間值。3. 第 19~22 行是迴圈內的判斷式,用以判斷中間索引
值的元素資料是否等於所要搜尋的資料,若是,則執行第 20 和 21 行,顯示出索引值,並強迫跳出迴圈。
4. 第 23~26 行利用 mid 來修改 max 和 min 值,調整陣列索引值的最小值和最大值,設定搜尋的範圍。
5. 第 28~30 行利用判斷式,設定當在陣列中搜尋不到資料時,顯示欲搜尋的資料不在陣列中的訊息。
90
一維字元陣列:
字元陣列通常可以用來儲存字串,例如下面的程式碼:
以 char a[] = {'g', 'r', 'a', 'p', 'e'} 宣告字元陣列後,字元陣列在記憶體存放的位置如下圖所示:
93
上述利用一維字元陣列的程式碼分析如下:
1. 第 3 與 4 行宣告 a 與 b 兩個字元陣列,並在第 5 行顯示 a 陣列的內容。
2. 第 7~10 行的 for迴圈指定 b 陣列的元素分別為 ASCII 碼 65~69 的英文字母,也就是 A 、B 、 C 、 D 、 E ,並且顯示出來。
98
上述應用字元陣列的程式碼分析如下:
1. 第 6 行宣告一個字元二維陣列 color ,並設定初始值。
2. 第 7~11 行利用迴圈讓使用者依序輸入 5 個顏色,並儲存到 color 陣列。
3. 第 13 行利用 color[i] 存取第 i+1 列的字元內容。
104
上述的程式碼分析如下:
1. 第 5 行宣告一維字串陣列 data ,並且配置記憶體空間。2. 第 7~9 行宣告二維字串陣列 s ,並且設定初始值,也
就是說 s[0][0] 的內容為“奇摩網站”, s[0][1] 的內容為“ http://www.kimo.com.tw” ,以此類推。
3. 第 10~15 行讓使用者輸入資料,並儲存到一維字串陣列 data 中。
4. 第 17~19 行顯示 data 陣列中的資料。5. 第 20~24 行利用巢狀迴圈顯示 s 陣列中的資料,第 20
行的 s.length 表示 s 陣列總共有幾列資料,第 21 行的 s[i].length 表示 s 陣列的第 i 列中總共有幾個資料項目。
Top Related