370 likes | 585 Views
第 2 章 陣列結構與矩陣. 線性串列的定義 多項式的抽象資料型態應用 認識陣列 矩陣的應用 字串與字元陣列應用 字串運算處理. 線性串列的特性 (1). 2-1 線性串列的定義. 定義「線性串列」 (Linear List) :. 1. 存在的唯一的第一個元素 2. 存在唯一的最後一個元素 3. 除第一個元素外,每一個元素都有一個唯一的前相鄰元素 4. 除了最後一個元素之外,每一個元素都有一個唯一的後相鄰元素. 線性串列的特性 (2). 2-1 線性串列的定義. 線性串列包含了以下 9 種運算方式:.
E N D
第2章 陣列結構與矩陣 線性串列的定義 多項式的抽象資料型態應用 認識陣列 矩陣的應用 字串與字元陣列應用 字串運算處理
線性串列的特性(1) 2-1 線性串列的定義 • 定義「線性串列」(Linear List): 1.存在的唯一的第一個元素 2.存在唯一的最後一個元素 3.除第一個元素外,每一個元素都有一個唯一的前相鄰元素 4.除了最後一個元素之外,每一個元素都有一個唯一的後相鄰元素
線性串列的特性(2) 2-1 線性串列的定義 • 線性串列包含了以下9種運算方式: 1.取出串列中的第i項;1≦i≦n 2.計算串列的長度n 3.由左至右,或由右至左讀此串列 4.加入一個新值到第i項,使得原來的第i,i+1……n變為第 i+1,i+2,……,n+1項 5.刪除位於第i項的一個元素,使原來的i+1,i+2,…項,變成第i,i +1,……,n-1項 6.複製串列 7.合併串列 8.分割串列 9.從兩端逐個讀取串列的元素值
一維陣列(1) 2-2 認識陣列 • 宣告格式如下: • 以下舉出C中幾個一維陣列的宣告實例: 資料型態 陣列名稱[陣列長度]; int a[5];/*宣告一個int型態的陣列a,陣列a中可以存放5個int型態的資料*/ long b[3];/*宣告一個long型態的陣列b,陣列b可以存放3個long型態的資料*/ float c[10];/*宣告一個float型態的陣列c,陣列c可以存放10個float型態的資料*/
一維陣列(2) 2-2 認識陣列 • 範例程式:ch02_01.c
2-2 認識陣列 執行結果
二維陣列(1) 2-2 認識陣列 • 宣告格式如下: • 例如宣告陣列A的列數是2,行數是3,所有元素個數為6。格式如下所示: • 陣列中元素的分佈圖說明如下: 資料型態 陣列名稱 [m] [n]; int A [2] [3];
二維陣列(2) 2-2 認識陣列 • 範例程式:ch02_02.c
2-2 認識陣列 • 執行結果
二維陣列(3) 2-2 認識陣列 • 以列為主(Row-Major),如C、C++、Java語言 • 即為A(1,1)、A(1,2)、…A(1,n)、…A(m,n),且所在位址的計算公式: • 以行為主(Column-Major),如Fortran語言 • 即為A(1,1)、A(2,1)、……A(m,1)、A(1,2)…A(m,n),則位址計算公式: Loc(A(i,j))=α+n*(i-1)*d +(j-1)*d (d為每單位空間,α為起始位址) Loc(A(i,j))=α+(i-1)*d+m*(j-l)*d
2-2 認識陣列 • 假設α仍為起始位址,而且m=(u1-l1+1),n=(u2-l2+1)。則有下列公式: • 以列為主(Row-Major): • 以行為主(Column-Major): Loc A(i,j)=α+((i-l1+1)-1)*n*d+((j-l2+1)-1)*d Loc A(i,j)=α+((j-l2+1)-1)*m*d+((i-l1+1)-1)*d
二維陣列(4) 2-2 認識陣列 • 範例2.2.1 • 陣列(Array)被以橫列(Row)為主的順序存放在記憶體內,每個陣列元素佔用4個單位的記憶體。若起始位址是100,在下列宣告中,所列元素存放位置為何? • 1.VarA=array[-100…1,1…100],求A[1,12]之位址。 • 2.VarA=array[5…10,-10…20],求A[5,-5]之位址。 • 範例2.2.2 • 有一個二維陣列A,已知a3,2的位址為1110,a2,3的位址為1115,且每個元素佔一個位址,則a5,4的位址為何? • 範例2.2.3 • A(-3:5,-4:2)之起始位址A(-3,-4)=100,以列為主排列,請問A(1,1)所在位址?(d=1)
多維陣列(1) 2-2 認識陣列 • 宣告格下如下: • 例如:宣告一個int型態的三維陣列A 資料型態 陣列名稱[N1][N2][N3]; int A[2][2][2]={{ {1,2}, {5,6} }, { {3,4}, {7,8﹜ }};
多維陣列(2) 2-2 認識陣列 • 以列為主(Row-Major) • 可以將陣列A視為u1個u2*u3的二維列陣,再將每個陣列視為有u2個一維陣列,每一個一維陣列可包含u3的元素。 • 位址計算公式: Loc(A(i,j,k))=α+(i-1)u2u3d+(j-1)u3d+(k-1)d
多維陣列(3) 2-2 認識陣列 • 以行為主(Column-Major) • 將陣列A視為u3個u2*u1的二為陣列,再將每個二維陣列視為有u2個一維陣列,每一陣列含有u1個元素。 • 若陣列宣告為A(l1:u1,l2:u2,l3:u3),則 a= u1- l1+1,b= u2- l2+1,c= u3- l3+1; Loc(A(i,j,k))=α+(k-l3)abd+(j-l2)ad+(i-l1)d
多維陣列(4) 2-2 認識陣列 • 範例2.2.4 • 假設有A(1:3,1:4,1:5)陣列,且Loc(A(1,1,1))=100,請求出以列為主排列的Loc(A(1,2,3))=? • 範例2.2.5 • 有一個三維陣列A(-3:2,-2:3,0:4),以Row-Major方式排列,陣列之起始位址是318,試求Loc(A(1,3,3))=?(每個元素佔一空間) • 範例2.2.6 • A(6,4,2)是以列為主方式排列,若α=300,且d=1,求A(4,4,1)的位址。
矩陣的運算(1) 2-3 矩陣的應用 • 矩陣相加 • 首先必須符合A為一個m*n的矩陣,B為一個n*p的矩陣,對A*B之後的結果為一個m*p的矩陣C。 C11= a11 * b11+ a12* b21+………+ a1n* bn1 : : C1p= a11* b1p+ a12* b2p+……+ a1n*bnp : : Cmp= am1* b1p+am2* b2p+………+ amn* bnp
矩陣的運算(2) 2-3 矩陣的應用 • 範例程式:ch02_03.c 01/********************************* 02 *程式檔名:ch02_03.c 03 *程式功能:兩個矩陣相加 04 *********************************/ 05#include <stdio.h> 06#include <stdlib.h> 07#define ROWS 2 08#define COLS 2 09/*矩陣內容列印副程式*/ 10void PrintMatrix(int* arrA) 11{ 12int i,j; 13for(i=0;i<ROWS;i++) 14 { 15 for(j=0;j<COLS;j++) 16 printf("%d\t",arrA[i*COLS+j]); 17 printf("\n"); 18} 19} 20/*矩陣內容相加副程式*/ 21void MatrixAdd(int* arrA,int* arrB,int* arrC,int dimX,int dimY) 22{
2-3 矩陣的應用 23 int row,col; 24 if(dimX<=0||dimY<=0) 25 { 26 printf("矩陣維數必須大於0\n"); 27 return; 28 } 29 for(row=1;row<=dimX;row++) 30 for(col=1;col<=dimY;col++) 31 arrC[(row-1)*dimY+(col-1)]=arrA[(row-1)*dimY+(col-1)]+arrB[(row-1)*dimY+(col-1)]; 32} 33 34int main(void) 35{ 36int A[ROWS][COLS] = {{15,35},{12,23}}; 37 int B[ROWS][COLS] = {{24,17},{36,51}}; 38 int C[ROWS][COLS] = {0}; 39 printf("矩陣A的各個元素===\n"); /*印出矩陣A的內容*/ 40 PrintMatrix(&A[0][0]); 41 printf("矩陣B的各個元素===\n"); /*印出矩陣B的內容*/ 42 PrintMatrix(&B[0][0]); 43 MatrixAdd(&A[0][0],&B[0][0],&C[0][0],ROWS,COLS); 44 printf("矩陣A和矩陣B相加===\n"); /*印出A+B的內容*/ 45 PrintMatrix(&C[0][0]); 46 system("pause"); 47}
2-3 矩陣的應用 • 程式執行結果
矩陣的運算(3) 2-3 矩陣的應用 • 矩陣相乘 • 首先必須符合A為一個m*n的矩陣,B為一個n*p的矩陣,對A*B之後的結果為一個m*p的矩陣C。 C11= a11 * b11+ a12* b21+………+ a1n* bn1 : : C1p= a11* b1p+ a12* b2p+……+ a1n*bnp : : Cmp= am1* b1p+am2* b2p+………+ amn* bnp
矩陣的運算(4) 2-3 矩陣的應用 • 範例程式:ch02_04.c • 01/********************************* • 02 *程式檔名:ch02_04.c • 03 *程式功能:兩個矩陣相乘 • 04 *********************************/ • 05#include <stdio.h> • 06#include <stdlib.h> • 07#include <conio.h> • 08#define MSize 2 • 09#define NSize 3 • 10#define PSize 2 • 11/*矩陣內容列印副程式*/ • 12void PrintMatrix(int* arrA,int rows,int cols) • 13{ • int i,j; • 15for(i=0;i<rows;i++)
2-3 矩陣的應用 • 16{ • 17for(j=0;j<cols;j++) • 18printf("%d\t",arrA[i*cols+j]); • 19printf("\n"); • 20} • 21} • 22/*矩陣內容相乘副程式*/ • 23void MatrixMultiply(int* arrA,int* arrB,int* arrC,int M,int N,int P) • 24{ • 25int i,j,k,Temp; • 26if(M<=0||N<=0||P<=0) • 27{ • 28printf("[錯誤:維數M,N,P必須大於0]\n"); • 29return; • 30} • 31for(i=0;i<M;i++) • for(j=0;j<P;j++) • 33{ • Temp = 0; • 35for(k=0;k<N;k++)
2-3 矩陣的應用 36Temp = Temp + arrA[i*N+k]*arrB[k*P+j]; 37arrC[i*P+j] = Temp; 38} 39} 40 41int main(void) 42{ 43int A[MSize][NSize] = {{1,1,1},{2,2,2}}; 44int B[NSize][PSize] = {{2,3},{4,5},{6,7}}; 45int C[MSize][PSize] = {0}; 46printf("矩陣A的各個元素===\n"); /*印出矩陣A的內容*/ 47PrintMatrix(&A[0][0],MSize,NSize); 48printf("矩陣B的各個元素===\n"); /*印出矩陣B的內容*/ 49PrintMatrix(&B[0][0],NSize,PSize); 50MatrixMultiply(&A[0][0],&B[0][0],&C[0][0],MSize,NSize,PSize); 51printf("矩陣A和矩陣B相乘===\n");/*印出A*B的內容*/ 52PrintMatrix(&C[0][0],MSize,PSize); 53system("pause"); 54}
2-3 矩陣的應用 • 程式執行結果
矩陣的運算(5) 2-3 矩陣的應用 • 轉置矩陣 • 「轉置矩陣」(At)就是把原矩陣的行座標元素與列座標元素相互調換,假設At為A的轉置矩陣,則有At[j,i]=A[i,j]如下所示:
稀疏矩陣 2-3 矩陣的應用 • 在一個稀疏矩陣中,若共有t個非零項,則利用一個A(0:t,1:3)的二維陣列來表示,其中A(i,1)表列數、A(i,2)表行數、A(i,3)表示非零項的值(0≦i≦t)。 • 範例 2.3.1 • 試舉例說明兩個稀疏矩陣的乘積不再是稀疏矩陣。
字元陣列的應用 2-4 字串與字元陣列應用 • 例如在C中宣告一個長度為10字元的字元陣列arr2。如下所示: • 字元型態的資料會佔用記憶體1byte的空間,因此上述字元陣列一共佔用了記憶體10bytes的空間。 • 通常字元陣列會應用在字串的處理上,例如要將字串「tomguns」存入字元陣列。 char arr2[10]; char arr2[8]= "tomguns";
字串陣列與二維陣列 2-4 字串與字元陣列應用 • 字串陣列宣告方式如下: • 其中字串數是表示此字串陣列容納最多的字串數目,而字元數是表示每個字串大小最多可容納多少字元,並且包含了\0結尾字元。例如: char 字串陣列名稱[字串數][字元數]; char arr[3][8]=﹛﹛"tomguns"﹜, ﹛"sandy"﹜, ﹛"kelly"﹜﹜
2-4 字串與字元陣列應用 • 上述字串陣列方式如下圖所示: • 如果要使用二維陣列arr內字串「sandy」的「d」字元時,那麼就要將索引值指定到「arr[1][3]」: arr[2]→"kelly" arr[1][3]→"d"
字串長度與複製 2-5 字串運算處理 • 以下是字串長度與複製的C部份演算法: 01for(i=0; str[i]!='\0';i++) 02{ 03str1[i]=str[i];/* 逐一字元拷貝 */ 04} 05str1[i]=‘\0’;/* 在計算字串長度時,並不包含字串結 尾字元'\0' */ 06printf("此字串有%d個字元\n",i); 07printf("原字串str=%s\n",str); 08printf("複製後字串str1=%s\n",str1);
字串連結 2-5 字串運算處理 • 以下是字串連結的C部份演算法: 01for (count=0; Str_1[count] != ‘\0’; count++, s_record++) /* 將 Str_1 字串複製到 Str_3 */ 02Str_3[s_record]=Str_1[count]; 03for (count=0; Str_2[count] != ‘\0’; count++, s_record++) /* 將 Str_2 字串複製到 Str_3 */ 04Str_3[s_record]=Str_2[count]; 05Str_3[s_record]='\0'; /* 字串最後要加上 NULL 字元 */ 06printf(“連結後的字串 Str_3:%s”, Str_3); /* 顯示字串連 結的結果 */
字串比較 2-5 字串運算處理 • 以下是字串比較的C部份演算法: 01for (count=0; Str_1[count] != '\0' && Str_2[count] != '\0'; count++) 02if ( Str_1[count] == Str_2[count] ) 03continue; /* 相等則繼續比較下一個字元 */ 04else 05break; /* 不相等即跳出迴圈的執行 */ 06if ( Str_1[count] == ‘\0’ && Str_2[count] == ‘\0’ ) /* 判 斷兩個字串是否都比較到結尾字元 */ 07printf("2個字串相等..."); /* 顯示結果 */ 08else 09printf("2個字串不相等..."); /* 顯示結果 */
多項式的定義(1) 2-6 多項式的抽象資料型態應用 • 通常多項式在電腦中的表示法可用線性循環串列(如陣列)或鏈結串列來表示。 • 而利用陣列表示法有以下兩種: • 1.不考慮P是否含有零項次,而利用一個n+2長的陣列,以指數大小儲存,陣列的第一元素是代表最大的指數,例如A(1:n+2)=(n,an,an-1,…a1,a0) 優點:相關演算法簡單。 缺點:對於某些多項式而言,太浪費空間,如X10000+1,用此方法需要長度10002,=>A=(10000,1,0,0,……,0,1)。
多項式的定義(2) 2-6 多項式的抽象資料型態應用 • 2.只考慮多項式的非零項項目數目,若有m項,則用一個2m+1長的陣列,分別儲存每一個非零的指數和係數,而此陣列的第一個元素是多項式非零項的個數。 優點:避免空間浪費。 缺點:相關演算法較為複雜。(如多項式的加法演算)。
多項式的加法運算 2-6 多項式的抽象資料型態應用 • 對於多項式的相關演算法而言,最典型的就是加法運算。 • 基本上,兩多項式A、B相加的原理很簡單。 • 將A(X)和B(X)逐項相加,並在比較時以下列三種狀況來區分: ①A指數=B指數 ②A指數>B指數 ③A指數<B指數