稀疏矩陣的轉置和加法實驗報告
阿新 • • 發佈:2018-11-22
實驗八 陣列操作
(一)實驗目的
1)通過實驗理解稀疏矩陣。
2)通過實驗掌握稀疏矩陣的儲存結構。
3)通過實驗掌握稀疏矩陣的逆置和相加操作.
必須達到的最少程式行數為150行.
(二)實驗專案內容(儘可能寫具體)
1) 稀疏矩陣的定義。
2) 稀疏矩陣的逆置操作。
3) 稀疏矩陣的相加操作。
1 #include <stdio.h> 2 #include <stdlib.h> 3#include <windows.h> 4 5 #define MAXSIZE 1000 6 #define OK 0 7 8 #define MALLOC_FAIL -1 // 表示分配空間時發生錯誤 9 #define EMPTY_MATRIX -2 // 表示正嘗試對一個空矩陣進行運算操作 10 #define MATRIX_NOT_MATCH -3 // 表示嘗試對不符合運算條件的矩陣進行運算操作(例如非相同行數列數矩陣相加) 11 12 /* ----------- 結構體宣告部分 ----------------*/ 13 typedef struct 14 { 15 int row; // 非零元的行下標 16 int col; // 非零元的列下標 17 int e; // 非零元的值 18 } Triple; //三元組結構 19 20 typedef struct 21 { 22 Triple *data; // 非零元素的元素表 23 int rownum; // 矩陣的行數 24 int colnum; //矩陣的列數 25 int num; // 矩陣非零元的個數 26 } TSMatrix, *PTSMatrix; 27 28 /* ----------- 函式宣告部分 ------------------ */ 29 // 初始化稀疏矩陣結構 30 int TSMatrix_Init(TSMatrix *M); 31 32 // 以三元組的方式輸出稀疏矩陣 33 void TSMatrix_PrintTriple(TSMatrix *M); 34 35 // 從一個二維陣列(普通矩陣)建立一個稀疏矩陣 36 TSMatrix *TSMatrix_Create(int *a, int row, int col); 37 38 // 從鍵盤錄入資料建立一個稀疏矩陣 39 TSMatrix *TSMatrix_CreateFromInput(); 40 41 // 求稀疏矩陣 M 的轉置矩陣 T 42 int TSMatrix_FastTranspose(TSMatrix M, TSMatrix *T); 43 44 // 如果稀疏矩陣 M 和 N 的行數的列數相同,計算 Q = M + N 45 int TSMatrix_Add(TSMatrix M, TSMatrix N, TSMatrix *Q); 46 47 48 // 初始化稀疏矩陣結構 49 int TSMatrix_Init(TSMatrix *M) 50 { 51 M->data = (Triple *)malloc(MAXSIZE * sizeof(Triple)); 52 53 if (!M->data) 54 return MALLOC_FAIL; 55 56 M->num = 0; 57 M->colnum = 0; 58 M->rownum = 0; 59 60 return OK; 61 } 62 63 64 // 以三元組的方式輸出稀疏矩陣 65 void TSMatrix_PrintTriple(TSMatrix *M) 66 { 67 int i; 68 69 if (0 == M->num) 70 { 71 printf("稀疏矩陣為空!\n"); 72 return; 73 } 74 75 printf(" i j v \n"); 76 printf("===============\n"); 77 78 for (i = 0; i < M->num; i++) 79 { 80 81 printf("%3d %3d %3d\n", M->data[i].row, M->data[i].col, M->data[i].e); 82 } 83 84 printf("===============\n"); 85 } 86 87 // 求稀疏矩陣 M 的轉置矩陣 T 88 int TSMatrix_FastTranspose(TSMatrix M, TSMatrix *T) 89 { 90 int *num, *cpot, i, t; 91 92 // 如果矩陣 M 為空矩陣,返回錯誤資訊 93 if (M.num == 0) 94 return EMPTY_MATRIX; 95 96 // 分配臨時的工作空間 97 num = (int *)malloc((M.colnum + 1) * sizeof(int)); 98 cpot = (int *)malloc((M.colnum + 1) * sizeof(int)); 99 100 // 如果臨時的工作空間分配不成功 101 if (num == NULL || cpot == NULL) 102 return MALLOC_FAIL; 103 104 // 初始化臨時工作空間(把 num 陣列用 0 填充) 105 for (i = 1; i <= M.rownum; i++) 106 num[i] = 0; 107 108 // 統計倒置後每行的元素數量(即統計倒置前矩陣每列元素的數量) 109 for (i = 1; i <= M.num; i++) 110 num[M.data[i - 1].col]++; 111 112 // 設定 T 矩陣每行首個非零元的位置 113 cpot[1] = 0; 114 for (i = 2; i <= M.colnum; i++) 115 cpot[i] = cpot[i - 1] + num[i - 1]; 116 117 // 把 T 矩陣的資訊清空 118 TSMatrix_Init(T); 119 120 // 把矩陣 M 的資訊填充到 T 中。 121 // 矩陣倒置以後,T 的行數等於 M 的列數,T 的列數等於 M 的行數 122 T->num = M.num; 123 T->colnum = M.rownum; 124 T->rownum = M.colnum; 125 126 // 對 M 矩陣中每個非零元素進行轉置操作 127 for (i = 0; i < M.num; i++) 128 { 129 t = cpot[M.data[i].col]; 130 131 T->data[t].col = M.data[i].row; 132 T->data[t].row = M.data[i].col; 133 T->data[t].e = M.data[i].e; 134 135 ++cpot[M.data[i].col]; 136 } 137 138 // 轉置完成後釋放臨時工作空間 139 free(num); 140 free(cpot); 141 142 return OK; 143 } 144 145 // 如果稀疏矩陣 M 和 N 的行數的列數相同,計算 Q = M + N 146 int TSMatrix_Add(TSMatrix M, TSMatrix N, TSMatrix *Q) 147 { 148 int i = 0, j = 0, k = 0; 149 150 if (M.colnum != N.colnum || M.rownum != N.rownum) 151 return MATRIX_NOT_MATCH; 152 153 // 填充結果矩陣資訊 154 TSMatrix_Init(Q); 155 Q->colnum = M.colnum; 156 Q->rownum = M.rownum; 157 Q->num = 0; 158 159 while (i < M.num && j < N.num) 160 { 161 // 如果 i j 指向元素是同一行的元素 162 if (M.data[i].row == N.data[j].row) 163 { 164 // 如果 i 和 j 指向的元素指向的是同一個元素 165 if (M.data[i].col == N.data[j].col) 166 { 167 Q->data[k].row = M.data[i].row; 168 Q->data[k].col = M.data[i].col; 169 Q->data[k].e = M.data[i].e + N.data[j].e; 170 i++; 171 j++; 172 if(Q->data[k].e != 0) //如果相加之後的值為0,則不在三元組中儲存 173 { 174 k++; 175 Q->num++; 176 } 177 } 178 // 如果 i 指向元素的列下標大於 j 指向元素的列下標 179 // 把下標小(j 指向的元素)的放入到 Q 矩陣中 180 else if (M.data[i].col > N.data[j].col) 181 { 182 Q->data[k].row = N.data[j].row; 183 Q->data[k].col = N.data[j].col; 184 Q->data[k].e = N.data[j].e; 185 Q->num++; 186 187 j++; 188 k++; 189 } 190 // 如果 i 指向元素的列下標小於 j 指向元素的列下標 191 // 把下標小(i 指向的元素)的放入到 Q 矩陣中 192 else if (M.data[i].col < N.data[j].col) 193 { 194 Q->data[k].row = M.data[i].row; 195 Q->data[k].col = M.data[i].col; 196 Q->data[k].e = M.data[i].e; 197 Q->num++; 198 199 i++; 200 k++; 201 } 202 } 203 // 如果 i 指向的元素行下標大於 j 指向元素的行下標 204 else if (M.data[i].row > N.data[j].row) 205 { 206 Q->data[k].row = N.data[j].row; 207 Q->data[k].col = N.data[j].col; 208 Q->data[k].e = N.data[j].e; 209 Q->num++; 210 211 k++; 212 j++; 213 } 214 // 如果 i 指向元素行下標小於 j 指向元素的行下標 215 else if (M.data[i].row < N.data[j].row) 216 { 217 Q->data[k].row = M.data[i].row; 218 Q->data[k].col = M.data[i].col; 219 Q->data[k].e = M.data[i].e; 220 Q->num++; 221 222 i++; 223 k++; 224 } 225 } 226 227 // 如果還有剩餘元素,按順序把元素新增到結果矩陣中 228 while (i < M.num) 229 { 230 Q->data[k].row = M.data[i].row; 231 Q->data[k].col = M.data[i].col; 232 Q->data[k].e = M.data[i].e; 233 Q->num++; 234 235 i++; 236 k++; 237 } 238 239 while (j < N.num) 240 { 241 Q->data[k].row = N.data[j].row; 242 Q->data[k].col = N.data[j].col; 243 Q->data[k].e = N.data[j].e; 244 245 Q->num++; 246 247 j++; 248 k++; 249 } 250 251 return OK; 252 } 253 254 // 從一個二維陣列建立一個稀疏矩陣 255 TSMatrix *TSMatrix_Create(int *a, int row, int col) 256 { 257 int i, j; 258 TSMatrix *P = (TSMatrix *)malloc(sizeof(TSMatrix)); 259 TSMatrix_Init(P); 260 261 // 設定稀疏矩陣的行數和列數 262 P->rownum = row; 263 P->colnum = col; 264 265 for (i = 0; i < row; i++) 266 { 267 for (j = 0; j < col; j++) 268 { 269 // 如果第 i+1 行第 i+1 列元素是非零元素 270 if (0 != *(a + i * col + j)) 271 { 272 // 把非零元的元素和位置資訊儲存到稀疏矩陣中 273 P->data[P->num].e = *(a + i * col + j); 274 P->data[P->num].row = i + 1; 275 P->data[P->num].col = j + 1; 276 277 // 把稀疏矩陣中的非零元個數加一 278 P->num++; 279 } 280 } 281 } 282 283 return P; 284 } 285 286 //從輸入中建立矩陣 287 TSMatrix *TSMatrix_CreateFromInput() 288 { 289 int *a, i, j, k; 290 TSMatrix *T; 291 292 printf("請輸入新建立的矩陣的行數和列數,分別輸入並利用空格間開:"); 293 294 // 輸入的同時對資料的有效性進行檢查 295 while (2 != scanf("%d%d", &i, &j)) 296 printf("無效輸入,請重新輸入!\n"); 297 298 // 分配臨時儲存輸入資料的空間 299 a = (int *)malloc(i * j * sizeof(int)); 300 301 // 如果分配失敗,則返回一個空指標 302 if (a == NULL) 303 return NULL; 304 305 // 開始從鍵盤中讀入元素 306 for (k = 0; k < i * j; k++) 307 { 308 309 printf("請從鍵盤輸入第 %d 行第 %d 列元素:", (k / j) + 1, (k % j) + 1); 310 311 while (1 != scanf("%d", (a + k))) 312 { 313 printf("無效輸入,請重新輸入!\n"); 314 } 315 } 316 317 T = TSMatrix_Create(a, i, j); 318 319 // 釋放用於臨時儲存輸入的空間 320 free(a); 321 322 return T; 323 } 324 325 /* ----------- 程式主函式 -------------------- */ 326 int main() 327 { 328 int info; 329 char ch; 330 331 // 從一個二維陣列建立一個係數矩陣 332 TSMatrix *M; 333 TSMatrix *N; 334 335 // 用來接收運算結果的空間 336 TSMatrix *T = (TSMatrix *)malloc(sizeof(TSMatrix)); 337 338 while (1) 339 { 340 fflush(stdin); 341 system("cls"); 342 343 printf(" 稀疏矩陣基本操作演示 \n"); 344 printf("1. 矩陣的建立和轉置\n"); 345 printf("2. 矩陣的加法運算並以三元組輸出結果\n"); 346 printf("\n"); 347 printf("Q. 退出程式\n"); 348 printf("\n"); 349 printf(" 請輸入選項:"); 350 351 scanf("%c", &ch); 352 353 switch (ch) 354 { 355 case '1': 356 system("cls"); 357 358 M = TSMatrix_CreateFromInput(); 359 360 if (M != NULL) 361 { 362 printf("\n\n以三元組輸出稀疏矩陣:\n"); 363 TSMatrix_PrintTriple(M); 364 printf("\n轉置後稀疏矩陣的三元組輸出:\n"); 365 TSMatrix_FastTranspose(*M, T); 366 TSMatrix_PrintTriple(T); 367 368 system("pause"); 369 } 370 else 371 { 372 printf("建立矩陣過程發生錯誤"); 373 system("pause"); 374 } 375 376 break; 377 case '2': 378 system("cls"); 379 380 M = TSMatrix_CreateFromInput(); 381 N = TSMatrix_CreateFromInput(); 382 383 if (M == NULL || N == NULL) 384 { 385 printf("建立矩陣過程中發生錯誤!\n"); 386 system("pause"); 387 break; 388 } 389 390 info = TSMatrix_Add(*M, *N, T); 391 392 if (info == MATRIX_NOT_MATCH) 393 { 394 printf("這兩個矩陣不能運算呢!! ⊙﹏⊙\n"); 395 } 396 else if (info == OK) 397 { 398 printf("\n運算結果:\n"); 399 TSMatrix_PrintTriple(T); 400 } 401 402 system("pause"); 403 404 break; 405 406 case 'q': 407 case 'Q': 408 exit(0); 409 } 410 } 411 412 return 0; 413 }