最近正在弄數據結構課程設計內容,說實話,感覺自己數據結構學的就是渣,好多東西都不會。還是要多學點東西啊。現在暫且貼點之前寫完的東西吧,到時候也好有個總結。
1 諸論
1.1 問題描述
稀疏矩陣是指那些多數元素為零的矩陣。利用“稀疏”特點進行存儲和計算可以大大節省存儲空間,提高計算准備效率。實現一個能進行稀疏矩陣基本運算的運算器。
1.2 基本要求
以“帶行邏輯鏈接信息”的三元組順序表示稀疏矩陣,實現兩個稀疏矩陣相加、相減、相乘和求逆的運算。稀疏矩陣的輸入形式采用三元組表示,而運算結果的矩陣則以通常的陣列形式列出。
2 分析問題和確定解決方案
2.1 問題描述
稀疏矩陣是指那些多數元素為零的矩陣。利用“稀疏”特點進行存儲和計算可以大大節省存儲空間,提高計算准備效率。實現一個能進行稀疏矩陣基本運算的運算器。
2.2 輸入輸出
2.2.1 輸入形式及輸入值范圍
以三元組的形式輸入,首先應輸入稀疏矩陣的行數、列數和非零元個數,控制好矩陣大小。其次分別輸入非零元對應的行列和數值。
例如:輸入3 3 4分別代表稀疏矩陣的行數、列數和非零元個數
其后分別輸入:1 1 3
3 3 5
2 2 7
2 3 9
在輸入非零元時,應判別給出的數據是否在矩陣的行列范圍內,以及是否非零元有重復輸入現象。若重復輸入非零元后,應判斷如何取舍和處理錯誤帶來需要重新計數的情況。對手動輸入和文件讀入兩種方式應采取不同的方式進行輸入操作。
2.2.2 輸出形式
運算結果通常以陣列形式輸出。
2.3 矩陣各功能實現
2.3.1 矩陣相加運算
通過對兩矩陣行行列列對應相加,實現矩陣加法運算。通常的矩陣加法被定義在兩個相同大小的矩陣。兩個m×n矩陣A和B的和,標記為A+B,一樣是個m×n矩陣,其內的各元素為其相對應元素相加后的值。例如:
2.3.2 矩陣相減運算
矩陣減法可將其中一個矩陣非零元全部取負,再進行矩陣加法。所以,矩陣減法和加法本質是一致的。A-B內的各元素為其相對應元素相減后的值,且此矩陣會和A、B有相同大小。例如:
2.3.3 矩陣相乘運算
矩陣相乘運算可由一般矩陣相乘的定義進行運算,即一矩陣的行元素乘以另一矩陣的列元素。它只有在第一個矩陣的列數(column)和第二個矩陣的行數(row)相同時才有定義。
例如當A是個4×2矩陣和B是個2×3矩陣時。分別來自兩個矩陣的元素都依箭頭方向而兩兩配對,把每一對中的兩個元素相乘,再把這些乘積加總起來,最后得到的值即為箭頭相交位置的值。
2.3.4 矩陣求逆矩陣運算
(空)
2.1 課程設計目的
(1)了解稀疏矩陣的相關應用。
(2)掌握稀疏矩陣存儲、創建、顯示、轉置等方法。
(3)實現一個能進行稀疏矩陣基本運算的運算器。
2.2 課程設計意義
本次課程設計可以使我們更熟練地掌握稀疏矩陣的相關知識,利用“稀疏”特點進行存儲和計算可以大大節省存儲空間,提高計算准備效率。
本次課程設計是本組成員共同努力而完成的,第一次進行課程設計是我們的探索過程,這個過程中,我們克服了一個個困難,在摸索中前行,我們相信通過此次課程設計我們每個人都會對數據結構這門課程有更深一步的了解。
2.3 模塊及任務分配
2.3.1 建立並初始化稀疏矩陣及程序輸出、連接各個子函數
本模塊要求以三元組表形式存儲方式建立稀疏矩陣並進行初始化。在以三元組表存儲方式建立稀疏矩陣時,應考慮到手動輸入及文件讀入兩種不同情況下矩陣越界及其他錯誤的情況,做好對初始化矩陣的檢查,這樣可以保證之后的運算能順利進行。
2.3.2 進行稀疏矩陣相加、減運算
本模塊要求設計函數進行稀疏矩陣的加減運算。在編寫函數時,要先輸入兩個稀疏矩陣才能進行下一步的運算。減法運算中,只要將其中一個矩陣的非零元變為負數,即可進行矩陣加法運算,所以,矩陣加法運算是本模塊核心。在矩陣加法運算中,需要判斷兩矩陣類型是否符合相加條件。
2.3.3 進行稀疏矩陣乘法運算
本模塊要求設計函數對兩個矩陣進行乘法運算。在運算中,需要判斷兩矩陣是否符合相乘條件,即一矩陣行數是否等於另一矩陣的列數。
2.3.4 進行稀疏矩陣求逆矩陣運算
本模塊要求設計函數對矩陣進行求其逆矩陣的運算。在求逆矩陣中,應考慮到運算過程中中間結果可能不是整數,所以三元組表中存儲的數據類型應為單精度或雙精度型。求逆矩陣應先判斷其運算成立條件,並進行相應運算。打印結果時,也應注意數據類型為單精度或雙精度。
2.3.5 任務分配
(空)
3 分析問題和確定解決方案
(空)
代碼部分
Matrix.h
#include <stdio.h> #include <stdlib.h> #define Max 5000 /*以三元組表為存儲方式定義的稀疏矩陣*/ typedef struct //以三元組表存儲方式存儲稀疏矩陣的非零元數據 { int row, col; //非零元行列值 int data; //非零元數值 } triple; typedef struct { int line, list, element; //稀疏矩陣的行列及非零元個數 triple data[Max]; //以三元組表形式存儲稀疏矩陣非零元對應行列以及數值 } matrix; typedef struct { int row; int col; float data; //稀疏矩陣用float型擴大精度,用於計算逆矩陣 } triple_f; typedef struct { int line, list, element; triple_f data[Max]; } matrix_f; /*函數聲明*/ /*main.cpp*/ matrix *Init(); //初始化矩陣Matrix matrix_f *Init_f(); //初始化矩陣Matrix_f /*Print_line.cpp*/ extern void Print_line(); //打印橫線 /*Print_menu.cpp*/ extern void Print_menu(); //打印菜單 /*Print_Matrix.cpp*/ extern void Print_Matrix(); //打印稀疏矩陣Matrix extern void Print_Matrix_f(); //打印稀疏矩陣Matrix_f /*Creat_Matrix.cpp*/ extern void Creat_Matrix(matrix **); //創建稀疏矩陣Matrix extern void Creat_Matrix_f(matrix_f **); //創建稀疏矩陣Matrix_f /*Print_Matrix.cpp*/ extern void Print_Matrix(matrix *); //打印稀疏矩陣Matrix extern void Print_Matrix_f(matrix_f *); //打印稀疏矩陣Matrix_f /*Matrix_addition_subtraction.cpp*/ extern void Matrix_addition(matrix *, matrix *, matrix **); //稀疏矩陣加法運算 extern void Matrix_subtraction(matrix *, matrix *, matrix **); //稀疏矩陣減法運算 /*Matrix_multiplication.cpp*/ extern int elem(matrix *, int, int); //取值 extern void Matrix_multiplication(matrix *, matrix *, matrix **); //稀疏矩陣乘法運算 /*Inverse_Matrix.cpp*/ void Inverse_Matrix(matrix_f *, matrix_f **); //稀疏矩陣求其逆矩陣
Print_line.cpp
#include <stdio.h> #include "Matrix.h" void Print_line() { for (int i = 0; i<78; i++) printf("%c", '*'); printf("\n"); }
Print_menu.cpp
#include <stdio.h> #include "Matrix.h" /*打印主菜單*/ void Print_menu() //主菜單 { Print_line(); printf("* 1.創建矩陣A(做加減乘運算) *\n"); printf("* 2.創建矩陣B(做加減乘運算) *\n"); printf("* 3.創建矩陣C(求逆矩陣) *\n"); printf("* 4.矩陣加法運算 *\n"); printf("* 5.矩陣減法運算 *\n"); printf("* 6.矩陣乘法運算 *\n"); printf("* 7.求矩陣C的逆矩陣 *\n"); printf("* 8.退出 *\n"); Print_line(); printf("請選擇要進行的操作:"); }
Print_Matrix.cpp
#include <stdio.h> #include "Matrix.h" /*打印稀疏矩陣Matirx*/ void Print_Matrix(matrix *a) { int i = 0; for (int row = 1; row <= a->line; row++) //控制稀疏矩陣A的行 { for (int col = 1; col <= a->list; col++) //控制稀疏矩陣B的列 { int flag = 1; for (int j = 0; j < a->element; j++) if ((col == a->data[j].col) && (row == a->data[j].row)) //判斷當前位置是否是非零元,若是,則輸出非零元值 { printf("%2d ", a->data[j].data); flag = 0; } if (flag) printf("%2c ", '0'); } printf("\n"); } } /*打印稀疏矩陣Matrix_f*/ //此段有錯 void Print_Matrix_f(matrix_f *a) { int i = 0; /*for (int j = 0; j < a->element; j++) printf("%2.4f ", a->data[i].data);*/ for (int row = 1; row <= a->line; row++) //控制稀疏矩陣C的行 { for (int col = 1; col <= a->list; col++) //控制稀疏矩陣C的列 { int flag = 1; //做標記 for (int j = 0; j < a->element; j++) if (a->data[i].col == col&&a->data[i++].row == row) //判斷當前位置是否是非零元,若是,則輸出非零元值 { printf("%2.4f ", a->data[i].data); flag = 0; } if (flag) printf("%2.4C ", '0'); } printf("\n"); } }
Matrix_addition_subtraction.cpp
#include <stdio.h> #include <stdlib.h> #include "Matrix.h" /*稀疏矩陣加法運算*/ void Matrix_addition(matrix *a, matrix *b, matrix **c) //矩陣相加 { if ((a->line == b->line) && (a->list == b->list)) //兩矩陣類型相同(行數、列數相同) { int i = 0, j = 0, k = 0; (*c)->line = a->line; (*c)->list = a->list; for (int i = 0; i<a->element; ++i) //將稀疏矩陣A存入稀疏矩陣C中 { (*c)->data[i].col = a->data[i].col; //將稀疏矩陣A行存入C (*c)->data[i].row = a->data[i].row; //將稀疏矩陣A列存入C (*c)->data[i].data = a->data[i].data; //將稀疏矩陣A非零元值存入C (*c)->element++; } for (int i = 0; i<b->element; ++i) //將稀疏矩陣B和C相加 { bool flag = false; //flag做標記 for (int j = 0; j<(*c)->element; ++j) //對稀疏矩陣C做搜索,將稀疏矩陣B中位置與矩陣C相同的非零元進行相加 { if ((b->data[i].col == (*c)->data[j].col) && (b->data[i].row == (*c)->data[j].row)) //稀疏矩陣B和C非零元位置相同 { (*c)->data[j].data += b->data[i].data; //做矩陣相加 flag = true; break; } } if (!flag) //如果標記未改變,則稀疏矩陣C對應位置數值為0 { int k = (*c)->element; (*c)->data[k].col = b->data[i].col; //將稀疏矩陣B行存入C (*c)->data[k].row = b->data[i].row; //將稀疏矩陣B列存入C (*c)->data[k].data = b->data[i].data; //將稀疏矩陣B數值存入C (*c)->element++; //稀疏矩陣C非零元個數增大 } } } else //如果以上情況均未出現 { printf("您輸入的兩個矩陣不滿足運算條件!\n"); system("pause"); } } /*稀疏矩陣減法運算*/ void Matrix_subtraction(matrix *A, matrix *B, matrix **C) //矩陣相減 { if (A->line == B->line && A->list == B->list) //判斷矩陣A和矩陣B是否符合條件,用矩陣相加的方法處理矩陣相減 { /*將其中一矩陣所有非零元變為負數*/ for (int i = 0; i<A->element; i++) A->data[i].data = (-1)*A->data[i].data; //將矩陣A的非零元素均變成相反數 Matrix_addition(A, B, C); //調用矩陣加法運算 for (int i = 0; i<A->element; i++) //運算完畢后將矩陣A變回來 A->data[i].data = (-1)*A->data[i].data; } else //兩矩陣無法進行運算,不符合條件 { printf("您輸入的兩個矩陣不滿足運算條件!\n"); system("pause"); } }
Matrix_multiplication.cpp
/*矩陣相乘條件: 如果矩陣A與矩陣B相乘,必須A中的列數等於B中的行數。如果不相同,則AB無意義。 注意:不要求A的行數與B的列數是否相等。*/ #include <stdio.h> #include <stdlib.h> #include "Matrix.h" /*對矩陣三元組表進行取值*/ int elem(matrix *a, int i, int j) { int k = 0; while ((k<a->element) && (a->data[k].row != i || a->data[k].col != j)) //搜索矩陣元素位置 k++; if (k<a->element) return a->data[k].data; //如果矩陣中有,則返回數值 else return 0; //如果沒有,則返回0 } /*稀疏矩陣乘法運算*/ void Matrix_multiplication(matrix *a, matrix *b, matrix **c) { int p = 0; if (a->list != b->line) //矩陣A的列數不等於矩陣B的行數 { printf("您輸入的兩個矩陣不滿足相乘條件!\n"); system("pause"); exit(0); } for (int i = 0; i<a->list; ++i) { for (int j = 0; j<b->line; ++j) { int temp = 0; for (int k = 0; k<a->list; ++k) //矩陣A的行*矩陣B的列 temp += elem(a, i, k)*elem(b, k, j); if (temp != 0) //如果矩陣行列相乘不為零 { (*c)->data[p].row = i; (*c)->data[p].col = j; (*c)->data[p].data = temp; //把temp數值賦值給矩陣C p++; } } (*c)->line = a->line; (*c)->list = a->list; (*c)->element = p; } }
Inverse_Matrix.cpp (暫未調試)
main.cpp
#include <stdio.h> #include <stdlib.h> #define Max 5000 /*連接文件*/ #include "Matrix.h" /*稀疏矩陣初始化*/ matrix *Init() { matrix *A; A = (matrix*)malloc(sizeof(matrix)); A->line = 0; A->list = 0; A->element = 0; for (int i = 0; i<Max; i++) { A->data[i].col = 0; A->data[i].row = 0; A->data[i].data = 0; } return A; } matrix_f *Init_f() { matrix_f *A; A = (matrix_f*)malloc(sizeof(matrix_f)); A->line = 0; A->list = 0; A->element = 0; for (int j = 0; j<Max; j++) { A->data[j].col = 0; A->data[j].row = 0; A->data[j].data = 0; } return A; } /*主函數*/ int main() { int num; matrix *A; matrix *B; matrix *C; matrix_f *S; matrix_f *T; A = Init(); B = Init(); C = Init(); S = Init_f(); T = Init_f(); Print_menu(); //打印菜單 scanf_s("%d", &num); while (1) { if (num>9 && num<1) printf("錯誤!\n"); //菜單選項不是1-8時打印錯誤 switch (num) { /*創建矩陣A*/ case 1: { system("cls"); //清屏 printf("創建矩陣A...\n"); Creat_Matrix(&A); //創建矩陣A system("pause"); //按任意鍵返回 system("cls"); //清屏 Print_menu(); //打印菜單 break; } /*創建矩陣B*/ case 2: { system("cls"); //清屏 printf("創建矩陣B...\n"); Creat_Matrix(&B); //創建矩陣B system("pause"); //按任意鍵返回 system("cls"); //清屏 Print_menu(); //打印菜單 break; } /*創建矩陣C(求逆矩陣)*/ case 3: { system("cls"); //清屏 printf("創建矩陣C...\n"); Creat_Matrix_f(&S); //創建矩陣C system("pause"); //按任意鍵返回 system("cls"); //清屏 Print_menu(); //打印菜單 break; } /*矩陣加法運算*/ case 4: { printf("正在執行矩陣加法運算...\n"); C = Init(); //初始化 Matrix_addition(A, B, &C); Print_Matrix(C); //打印結果 system("pause"); //按任意鍵返回 system("cls"); //清屏 Print_menu(); //打印菜單 break; } /*矩陣減法運算*/ case 5: { printf("正在執行減法運算...\n"); C = Init(); //初始化 Matrix_subtraction(A, B, &C); //矩陣減法運算 Print_Matrix(C); //打印結果 system("pause"); //按任意鍵返回 system("cls"); //清屏 Print_menu(); //打印菜單 break; } /*矩陣乘法運算*/ case 6: { printf("正在執行乘法運算...\n"); C = Init(); //初始化 Matrix_multiplication(A, B, &C); //矩陣乘法運算 Print_Matrix(C); //打印結果 system("pause"); //按任意鍵返回 system("cls"); //清屏 Print_menu(); //打印菜單 break; } case 7: { if (A->line != A->list) //如果行不等於列 printf("矩陣行數不等於列數,沒有逆矩陣!\n"); else { printf("正在執行求逆運算...\n"); Inverse_Matrix(S, &T); //矩陣求逆 Print_Matrix_f(T); //打印矩陣Matrix_f system("pause"); //按任意鍵返回 system("cls"); //清屏 Print_menu(); //打印菜單 } break; } case 8: { exit(0); //退出 break; } }//switch結束 scanf_s("%d", &num); }//while結束 return 0; }
參考資料
課程設計:用C語言編寫的稀疏矩陣運算器(加、減、乘、求逆):http://blog.csdn.net/zhplovelyt/article/details/12028889
數據結構課程設計(稀疏矩陣運算器).doc:http://max.book118.com/html/2014/0228/6187693.shtm
求逆矩陣——C語言:http://blog.csdn.net/abcjennifer/article/details/6693612