zoukankan      html  css  js  c++  java
  • 数据结构课程设计《稀疏矩阵运算器》

    最近正在弄数据结构课程设计内容,说实话,感觉自己数据结构学的就是渣,好多东西都不会。还是要多学点东西啊。现在暂且贴点之前写完的东西吧,到时候也好有个总结。

    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

          代表稀疏矩阵非零元对应位置及数值,及建立的稀疏矩阵为: clip_image002

          在输入非零元时,应判别给出的数据是否在矩阵的行列范围内,以及是否非零元有重复输入现象。若重复输入非零元后,应判断如何取舍和处理错误带来需要重新计数的情况。对手动输入和文件读入两种方式应采取不同的方式进行输入操作。

    2.2.2 输出形式

           运算结果通常以阵列形式输出。

    2.3 矩阵各功能实现

    2.3.1 矩阵相加运算

          通过对两矩阵行行列列对应相加,实现矩阵加法运算。通常的矩阵加法被定义在两个相同大小的矩阵。两个m×n矩阵A和B的和,标记为A+B,一样是个m×n矩阵,其内的各元素为其相对应元素相加后的值。例如:

    clip_image003

    2.3.2 矩阵相减运算

          矩阵减法可将其中一个矩阵非零元全部取负,再进行矩阵加法。所以,矩阵减法和加法本质是一致的。A-B内的各元素为其相对应元素相减后的值,且此矩阵会和A、B有相同大小。例如:

    clip_image004

    2.3.3 矩阵相乘运算

          矩阵相乘运算可由一般矩阵相乘的定义进行运算,即一矩阵的行元素乘以另一矩阵的列元素。它只有在第一个矩阵的列数(column)和第二个矩阵的行数(row)相同时才有定义。

          例如当A是个4×2矩阵和B是个2×3矩阵时。分别来自两个矩阵的元素都依箭头方向而两两配对,把每一对中的两个元素相乘,再把这些乘积加总起来,最后得到的值即为箭头相交位置的值。

    clip_image006clip_image009

    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("
    ");
    }

    Print_menu.cpp

    #include <stdio.h>
    #include "Matrix.h"
    /*打印主菜单*/
    void Print_menu()  //主菜单
    {
        Print_line();
        printf("*                      1.创建矩阵A(做加减乘运算)                           *
    ");
        printf("*                      2.创建矩阵B(做加减乘运算)                           *
    ");
        printf("*                      3.创建矩阵C(求逆矩阵)                               *
    ");
        printf("*                      4.矩阵加法运算                                        *
    ");
        printf("*                      5.矩阵减法运算                                        *
    ");
        printf("*                      6.矩阵乘法运算                                        *
    ");
        printf("*                      7.求矩阵C的逆矩阵                                     *
    ");
        printf("*                      8.退出                                                *
    ");
        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("
    ");
        }
    }
    
    /*打印稀疏矩阵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("
    ");
        }
    }

    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("您输入的两个矩阵不满足运算条件!
    ");
            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("您输入的两个矩阵不满足运算条件!
    ");
            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("您输入的两个矩阵不满足相乘条件!
    ");
            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("错误!
    ");    //菜单选项不是1-8时打印错误
            switch (num)
            {
            /*创建矩阵A*/
            case 1:
            {
                system("cls");    //清屏
                printf("创建矩阵A...
    ");
                Creat_Matrix(&A);    //创建矩阵A
                system("pause");    //按任意键返回
                system("cls");    //清屏
                Print_menu();    //打印菜单
                break;
            }
            /*创建矩阵B*/
            case 2:
            {
                system("cls");    //清屏
                printf("创建矩阵B...
    ");
                Creat_Matrix(&B);    //创建矩阵B
                system("pause");    //按任意键返回
                system("cls");    //清屏
                Print_menu();    //打印菜单
                break;
            }
            /*创建矩阵C(求逆矩阵)*/
            case 3:
            {
                system("cls");    //清屏
                printf("创建矩阵C...
    ");
                Creat_Matrix_f(&S);    //创建矩阵C
                system("pause");    //按任意键返回
                system("cls");    //清屏
                Print_menu();    //打印菜单
                break;
            }
            /*矩阵加法运算*/
            case 4:
            {
                printf("正在执行矩阵加法运算...
    ");
                C = Init();    //初始化
                Matrix_addition(A, B, &C);
                Print_Matrix(C);    //打印结果
                system("pause");    //按任意键返回
                system("cls");    //清屏
                Print_menu();    //打印菜单
                break;
            }
            /*矩阵减法运算*/
            case 5:
            {
                printf("正在执行减法运算...
    ");
                C = Init();    //初始化
                Matrix_subtraction(A, B, &C);    //矩阵减法运算
                Print_Matrix(C);    //打印结果
                system("pause");    //按任意键返回
                system("cls");    //清屏
                Print_menu();    //打印菜单
                break;
            }
            /*矩阵乘法运算*/
            case 6:
            {
                printf("正在执行乘法运算...
    ");
                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("矩阵行数不等于列数,没有逆矩阵!
    ");
                else
                {
                    printf("正在执行求逆运算...
    ");
                    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

    稀疏矩阵设计说明书_百度文库:http://wenku.baidu.com/link?url=-lg9XBtczDAszts6GUvNYqhG6B4_h-A7vC1hDypy3_q0SF6pxOejsUxuiOLEGe_OQ8NiM00OJ8wcdcNR01mrWxJl3aGzM5fxik_4ICQaO3S

    求逆矩阵——C语言:http://blog.csdn.net/abcjennifer/article/details/6693612

  • 相关阅读:
    uva-321-暴力枚举-隐式图搜索
    uva-704-暴力枚举-双向bfs
    整数的无符号编码和有符号编码
    HDU 5793
    HDU 5730
    HDU 5740
    HDU 5768
    HDU 1194
    HDU 1086
    HDU 5145
  • 原文地址:https://www.cnblogs.com/secret114/p/4200406.html
Copyright © 2011-2022 走看看