Ch07 陣列 JAVA程式設計入門(I)
大綱 一維陣列 二維陣列 多維陣列
何謂陣列 生活上的例子:一汽車旅館有六間房間,某天住宿的情形 0號房間有3個房客 1號房間有2個房客 2號房間有2個房客 3號房間有0個房客 我們可以記錄成: 以陣列表示成: 0號房間有3個房客 1號房間有2個房客 2號房間有2個房客 3號房間有0個房客 4號房間有4個房客 5號房間有1個房客
何謂陣列 陣列-「多個擁有相同名稱且同型別的變數集合」 陣列是一段連續的區域,裡面由數個相同型別的陣列元素組成 陣列元素有相同的名稱,為了區別每個陣列元素,它們有各自的位置編號 陣列元素以陣列名稱,後接一對中括弧“[]”,中括弧內放入位置編號。 位置編號一般也稱為索引,索引一律由0開始,接著是1、2、3…至元素個數減一。 陣列的索引必須是大於或等於0的整數,或結果為整數的運算式。
陣列的宣告與配置(I) 陣列的宣告方式: 同時宣告兩個int型別 配置陣列:(陣列初始化) 宣告與配置陣列的方法一: 資料型別 陣列名稱[]; 資料型別 [] 陣列名稱; 同時宣告兩個int型別 int[] arr1, arr2; 配置陣列:(陣列初始化) 陣列名稱 = new 資料型別[元素個數]; 宣告與配置陣列的方法一: char cArr[]; cArr = new char[3];
陣列的宣告與配置(II) 宣告並配置: 宣告與配置一陣列的方法二: char cArr[] = new char[3];
陣列的宣告與配置 陣列變數其實是一種參照變數(reference variable) 陣列名稱是指向陣列實體的一個參照變數 JVM中陣列的宣告與配置 陣列變數其實是一種參照變數(reference variable). 當宣告cArr陣列後, 其實只佔32bits(4bytes)用來存參照,由於沒有配置的關係所以不知道陣列有多大. 當cArr完成配置後(即作了cArr = new char[3]), cArr會參考到(refer, 指向)3個相連的char型別空間. 也就是說, 配置陣列時, JVM會配給一塊指定的記憶體空間,並使陣列變數(為參照變數)指向陣列實體. 所以,陣列名稱雖然代表陣列,實際上是指向陣列實體的一個參照變數
使用陣列元素 使用陣列元素的語法: 使用陣列的敘述: 取得陣列的長度 陣列名稱[索引] int iArr[] = new int[3]; //宣告並配置陣列 iArr[1] = 123; //設定第2個元素值為123 iArr[2] = 456; //設定第3個元素值為456 //將第2和第3個元素值相加後設定給第1個元素 iArr[0] = iArr[1] + iArr[2]; 陣列名稱.length
使用陣列元素 元素預設值 陣列在配置後,元素的內容就會被填入預設值。 陣列的基底型態為整數者預設值為0。 浮點數則為0.0f或0.0d。 boolean型別為false。 物件為null。
for(int i=0; i<a.length; i++) a[i] = a.length-i; 範例1:Ch06_01.java:以迴圈設值並列出 int[] a = new int[5]; for(int i=0; i<a.length; i++) a[i] = a.length-i; System.out.println("a[" + i + "]=" + a[i]); 程式於程式區\java(1)\Ch06\Ch06_01.java
以大括號配置陣列並設值 宣告並設定陣列內容 例子: 宣告並設定初值時,勿在中括號內填入元素的個數 已宣告的陣列不可以使用大括號配置陣列及設值 法一:資料型別 陣列名稱[] = new 資料型別[] {元素值1, 元素2,..., 元素值N}; 法二:資料型別 陣列名稱[] = {元素值1,元素值2,...,元素值N}; int myArray[] = new int[] {10, 20, 30, 40, 50, 60}; int myArray[] = {10, 20, 30, 40, 50, 60}; int myArray[3] = {1, 2, 3}; // 錯誤 int myArray[]; myArray = {1, 2, 3}; //錯誤
範例2:Ch06_02.java:以大括號設值與陣列預設值 int[] a = {10, 20, 30, 40, 50, 60}; int[] b = new int[3]; for(int i=0; i<a.length; i++) System.out.print("a[" + i + "]=" + a[i] +"\t"); System.out.print("\n"); for(int i=0; i<b.length; i++) System.out.print("b[" + i + "]=" + b[i] +"\t"); 程式於程式區/java(1)/Ch06/Ch06_02.java
索引勿超出範圍 索引超出範圍時,編譯的過程不會有錯誤訊息 執行時會發生例外訊息(ArrayIndexOutOfBoundsException)。 可以加上if來過濾索引是否超出範圍,避免發生例外訊息 if(ch<0 || ch>=xmen.length) { System.out.println("超出範圍了,請重來!"); System.exit(0); }
範例3:Ch06_03.java: 測試若索引值超出合法範圍 if(args.length<1) { System.out.println("請傳入參數以選擇你最喜歡的 Xmen"); System.out.println("0)超人 1)閃電俠 2)蜘蛛人 3)金剛狼"); System.exit(0); //離開程式 } String[] xmen = {"超人", "閃電俠", "蜘蛛人", "金剛狼"}; int ch = Integer.parseInt(args[0]); //將第一個參數轉換成整數 System.out.println("你選擇的是: "+xmen[ch]); 程式於程式區/java(1)/Ch06/Ch06_03.java
例外訊息
練習一 修正範例3的程式, 使其在輸入值為4或更大的值時, 會出現警告訊息,而非例外訊息 程式於程式區/java(1)/Ch06/EX06_01.java
練習二 Int a[] = {36, 41, 24, 17} Int b[] = {9, 34, 26, 49} 比較兩陣列中相對應位置元素的值,並將值較大者存放到陣列a中,較小者存到b,列出兩陣列中的值 程式於程式區/java(1)/Ch06/Ex06_02.java
練習三 求long型別的最大值9223372036854775807的平方 (利用int陣列,一個元素代表一個位數) 程式於程式區/java(1)/Ch06/Ex06_03.java
陣列的=運算 基本型別使用指定運算子時,會將變數的值存入另一個變數的記憶位址。 指定運算子使用在陣列或物件時,與「以值指定」使用相同的機制,不過其值不是一般的基本型別常數,而是參照(Reference) int a = 5, b; b = a; //將a設定給b,a為5,b為5 b = 6; //將6設定給b,a為5,b為6 int[] arr1 = {16, 17, 18}; //宣告配置arr1並設值 int[] arr2; //宣告arr2陣列 arr2 = arr1; //arr1參照指定給arr2 19
陣列的=運算 兩個陣列名稱指向相同的陣列實體 20
陣列的=運算 兩個陣列的基底型別不同時,參照不可相互指定 int[] arr1 = {16, 17, 18}; long[] arr3 = arr1; //錯誤 21
範例4:Ch06_04.java 陣列指向相同的陣列實體 int[] a1 = {16, 17, 18}; int[] a2; int[] a3 = {16, 17, 18}; a2 = a1; System.out.println("a1的參照:" + a1); System.out.println("a2的參照:" + a2); System.out.println("a3的參照:" + a3); a2[1] = 32; System.out.println("a1的值:"+a1[0]+","+a1[1]+","+a1[2]); System.out.println("a2的值:"+a2[0]+","+a2[1]+","+a2[2]); System.out.println("a3的值:"+a3[0]+","+a3[1]+","+a3[2]); 程式於程式區/java(1)/Ch06/Ch06_04.java 22 22
範例4:Ch06_04.java結果 23
陣列複製 兩個陣列名稱有相同的元素內容,但使用不同的陣列實體,而不是指定參照的方式 使用System.arraycopy方法 來源陣列:欲複製的陣列 來源起始索引:來源陣列中所欲複製的陣列片段起始索引值 目的陣列:存放複製內容的陣列 目的起始索引:目的陣列中存放複製內容的起始位置 陣列長度:陣列中所欲複製的長度(元素個數) System.arraycopy(來源陣列, 來源起始索引, 目的陣列, 目的起始索引, 陣列長度); 24
陣列複製 使用System.arraycopy的例子 沒有配置空間的陣列,只能指定參考,不能用System.arraycopy複製陣列。 int[] a1 = {10, 20, 30, 40, 50}; int[] a2 = new int[a1.length]; System.arraycopy(a1, 0, a2, 0, a1.length); 25
範例1:Ch06_05.java:複製陣列 int[] a1 = {10, 20, 30, 40, 50}; int[] a2 = new int[a1.length]; System.arraycopy(a1, 0, a2, 0, a1.length); int[] a3 = new int[a1.length]; System.arraycopy(a1, 2, a3, 0, 3); a2[1] = -1; for(int i=0; i<a1.length; i++) { System.out.print("a1["+i+"]="+a1[i]+"\t"); System.out.print("a2["+i+"]="+a2[i]+"\t"); System.out.println("a3["+i+"]="+a3[i]); } 程式於程式區/java(1)/Ch06/Ch06_05.java 26 26
範例1:Ch06_05.java結果 27
練習一 不使用直接呼叫System.arraycopy方法,設計一個程式,可以將陣列做複製(非指定參考)。
二維陣列 二維陣列可以想成有好幾列的房間 29
二維陣列的宣告與配置 宣告二維陣列的語法 配置陣列: 宣告並配置的例子: 資料型別 陣列名稱[][ ]; 資料型別[]陣列名稱[ ]; 資料型別 陣列名稱[][ ]; 資料型別[]陣列名稱[ ]; 資料型別[][ ]陣列名稱; 陣列名稱 = new 資料型別[列數][行數]; int[][] arr = new int[3][5]; 30
使用元素 元素的表示法: 行0 行1 行2 行3 列0 a[0][0] a[0][1] a[0][2] a[0][3] 列1 a[1][0] int[][] a = new int[3][4]; 行0 行1 行2 行3 列0 a[0][0] a[0][1] a[0][2] a[0][3] 列1 a[1][0] a[1][1] a[1][2] a[1][3] 列2 a[2][0] a[2][1] a[2][2] a[2][3] 31
JVM中的二維陣列 建立陣列實體,再指定給參照變數 32
範例2:Ch06_06.java使用二維陣列 int[][] a = new int[3][4]; for(int i=0; i<a.length; i++) for(int j=0; j<a[i].length; j++) a[i][j] = i*10 + j; { for(int j=0; j<a[i].length; j++) System.out.print("a["+i+"]["+j+"]="+a[i][j]+"\t"); System.out.print("\n"); } System.out.println("\na=\t" +a); System.out.println("a[0]=\t"+a[0]); System.out.println("a[1]=\t"+a[1]); System.out.println("a[2]=\t"+a[2]); 程式於程式區/java(1)/Ch06/Ch06_06.java 33 33
範例2:Ch06_06.java結果 34
使用大括號建立二維陣列 非矩形二維陣列 行0 行1 行2 行3 列0 1 3 5 列1 2 4 列2 9 8 7 6 int[][] a = {{1, 3, 5}, {2, 4}, {9, 8, 7, 6}}; 行0 行1 行2 行3 列0 1 3 5 列1 2 4 列2 9 8 7 6 35
使用大括號建立二維陣列 若某列只有一個元素時,同樣必須以大括號包起來 int[][] a = {{1, 3, 5}, {2, 4}, {9}}; int[][] a = {{1, 3, 5}, {2, 4}, 9}; //錯誤 36
範例3:Ch06_07.java使用非矩形的二維陣列 int[][] a = {{1, 3, 5}, {2, 4}, {9, 8, 7, 6}}; int b[][] = new int[3][]; b[0] = a[2]; b[1] = new int[2]; b[2] = new int[3]; 37
範例3:Ch06_07.java使用非矩形的二維陣列 int[][] a = {{1, 3, 5}, {2, 4}, {9, 8, 7, 6}}; int b[][] = new int[3][]; b[0] = a[2]; b[1] = new int[2]; b[2] = new int[3]; b[0][0] = 10; for(int i=0; i<a.length; i++) { for(int j=0; j<a[i].length; j++) System.out.print("a["+i+"]["+j+"]="+a[i][j]+"\t"); System.out.print("\n"); } for(int i=0; i<b.length; i++) for(int j=0; j<b[i].length; j++) System.out.print("b["+i+"]["+j+"]="+b[i][j]+"\t"); 38
範例3:Ch06_07.java結果 39
多維陣列 N維陣列的宣告 配置陣列: 使用元素 建立三維陣列的例子: 資料型別 陣列名稱[][]…[]; 資料型別[][]…[]陣列名稱; 資料型別 陣列名稱[][]…[]; 資料型別[][]…[]陣列名稱; 陣列名稱 = new 資料型別[個數1][個數2]…[個數N]; 陣列名稱[索引1][索引2]…[索引N] int[][][]ar = new int[3][4][5]; int[]b[][] = {{{9}}}; 40
練習二 陣列a={12, 23, 34, 45, 56, 67} 陣列b={1, 2, 3, 4, 5, 6} 將b的元素值加到陣列a後面,即 陣列a={12, 23, 34, 45, 56, 67, 1, 2, 3, 4, 5, 6} 程式於程式區/java(1)/Ch06/Ex06_04.java 41 41
練習三 宣告並配置5*4的二維陣列aa,並使用迴圈設值如下: 程式於程式區\java(1)\Ch06\Ex06_05.java 42 42
練習四 修改上一題的程式,宣告並配置4*5的二維陣列bb使用迴圈將陣列aa的元素設定給陣列bb,陣列bb的值為 43 程式於程式區\java(1)\Ch11\Ex11_3.java 43 43
陣列的應用—重心法
重心法應用於供應鏈管理— 地點決策 現存組織會因為各種原因而需要進行地點的決策。 銀行、速食連鎖店、超級市場與零售業,其視地點為行銷策略的一部分。 新地點的決策即是對現行系統的擴充,而且尋找的地點要能幫助其擴展市場。 組織的產品或服務需求增加,且擴展舊地點已不能滿足時,增加新地點來補充現行系統的不足。 有些公司在面臨資源耗竭時,才開始考量選擇新地點。 市場的轉變也會讓公司考量重新設廠,或是在成本考量下,發現一個特定的地點能比原有地點更具吸引力。
地點方案的評估 有助於地點方案評估之方法: 地點成本-利潤-數量分析法 運輸模型 因子評分法 重心法 2017/3/18 第8章 地點規劃與分析
重心法 重心法(center of gravity method)是一種決定設施地點的方法,能使不同目的地間的運送成本或旅程時間最小化。
例題 假設有多個點需要運送,而各點運送量不同,如下圖表示。求出重心點。
例題4—解答
重心法應用於排艙最佳化 每一貨櫃的重量約26噸重,重量會因貨物不同,而有差距很大的重量。
排艙作業流程 各港口當地代理行提供裝貨數量。 碼頭planner根據主作船長所規畫的圖開始配艙。 配完後回傳給主作船長認可,船舶靠港後在送給船上大副作最後確認。 開始裝貨。
各港口當地代理行提供裝貨數量
主作船長使用排艙軟體開始排艙
BAY
ROW
TIER
排艙作業考慮因素 港口 貨物種類 平衡 …
重心位置的計算: 分布在同一平面上多個質點的系統,其個別重量與位置座標如右圖所示,此系統的重心位置座標(xG,yG)的計算公式為 W y x
W y x 將質點系統與座標逆時鐘方向旋轉 90o,相同的討論即得重心 y 座標的公式。
程式題 假設今有1000個貨櫃要進行排艙,貨櫃重量分別為 若將1000個貨櫃放在一個10x10x10的船艙空間中,要如何擺放,可以使得重心在最中間?
討論 貨櫃在船上,一定要平衡嗎? 騎車時,過彎會將身體如何擺,才不會“犂田” 排艙的解題,是否只能應用在排艙? 供應鏈管理 ???