实验6、压缩矩阵的2种转置运算

实验6、压缩矩阵的2种转置运算

(1)实验目的

通过该实验,让学生理解矩阵压缩存储的概念、方法等相关知识,掌握用三元组表的方式如何进行矩阵的压缩存储,并在此基础上进行转置操作,理解转置和快速转置两种矩阵转置算法的思想。

(2)实验内容

用三元组表压缩存储矩阵,实现创建矩阵、显示以及教材中介绍的两种转置算法。

(3)参考界面

1.创建矩阵

2.销毁矩阵

3.输出矩阵

4.转置矩阵

5.快速转置矩阵

具体要求:请认真查看测试用例

(4)验收/测试用例

  1. 创建矩阵:

注意:检查非零元素个数是否小于等于行数乘列数;检查是否能拦截元素下标重复输入;检查是否能控制输入的非零元素的下标是递增的(即按照行序输入,先输入小的下标,再输入较大的下标)。

注意:输入的过程中如果有一个输入错了,不要让用户从头再把所有的输入一次,只需把刚才输入错误的,重新输入正确即可。

  1. 输入:4(行数) 4(列数) 25(非零元个数),会提示:输入错误,非零元素个数要小于等于行数乘列数,请从新输入。
  2. 输入:4(行数) 4(列数) 5(非零元个数)
  3. 先输入:(1,1,1) (2,3,2)
  4. 再输入(2,3,6),会提示:输入错误,输入的下标重复,请重新输入!
  5. 再输入(1,1,6),会提示:输入错误,输入的下标重复,请重新输入!
  6. 继续输入(3,1,3) (3,4,5)
  7. 再输入(3,2,9),会提示:输入错误,下标输入时要递增输入,请重新输入!
  8. 再输入(2,3,8),会提示:输入错误,下标输入时要递增输入,请重新输入!
  9. 最后输入(4,2,4)
  1. 显示44

屏幕上输出

             1  0  0  0

             0  0  2  0

             3  0  0  5

             0  4  0  0

  1. 转置

屏幕上输出

             1  0  3  0

             0  0  0  4

             0  2  0  0

             0  0  5  0

  1. 创建矩阵

输入三元组表的行,列和非零元素个数,判断非零元素个数是否小于总元素个数(M.tu<M.mu*M.nu),如果不合法,提示重新输入,然后for循环输入矩阵元素,每次输入判断位置是否合法,(i,j不能越界),每次输入就遍历之前已经成功输入的元素,判断当前输入的元素的下标是否与之前输入的元素下标存在重复(M.data[p].i==M.data[q].i&&M.data[p].j==M.data[q].j),以及当前输入元素下标是否为递增输入(M.data[p].i<M.data[q].i),(M.data[p].i==M.data[q].i&&M.data[p].j==M.data[q].j),如果不是,让用户重新输入

  1. 销毁

遍历让每个节点的i,j,e=0,然后让整个三元组表的mu,nu,tu=0

  1. 输出矩阵

两层循环打印矩阵,遍历三元组表,将三元组表中存在的元素,在矩阵对应的位置上打印对应的元素,否则打印0

  1. 转置矩阵

用另一个三元组表T保存转置后的结果,让T的行数等于M的列数,T的列数等于M的行数,T的非零元素个数等于M的非零元素个数,从原矩阵的第一列开始遍历(就是转置后的第一行),如果三元组表M中存在当前位置上的元素,就把M.data域中当前元素的行列互换存入新三元组表T中,因为遍历每列时元素的有序排列,对应的就是转置后每一行的元素的有序排列

  1. 快速转置矩阵

新增两个向量num,和cpot分别记录原矩阵中每一列的非零元素的个数以及每一列第一个非零元素在转置后的三元组T的data域中的位置(一次遍历nu一次遍历tu,记录num[],cpot[1]=1从第二个非零元素开始,一次遍历tu记录copt[](cpot[col]=cpot[col-1]+num[col-1];)然后在转置时就不需要在进行遍历,便可直接放到T的data对应的位置上去,(注意每次放入元素后当前cpot[col]++来记录下一个元素应该放到的对应位置)

 

#include<iostream>

#include<stdlib.h>

#define MAXSIZE 125000

#define OK 1

#define ERROR 0

using namespace std;

typedef int ElemType;

typedef int Status;

typedef struct{

    int i;

    int j;

    ElemType e;

}Triple;

typedef struct{

    Triple data[MAXSIZE+1];

    int mu;

    int nu;

    int tu;

}TsMatrix;

TsMatrix M,T;

int flag=0;

//创建矩阵

void CreateSMatrix(TsMatrix &M){

    while(true){

        cout<<"请输入矩阵行数,列数和非零元素的个数:";

        cin>>M.mu>>M.nu>>M.tu;

        if(M.mu<=0)

        cout<<"输入行数不合法,请重新输入!"<<endl;

        if(M.nu<=0)cout<<"输入列数不合法,请重新输入!"<<endl;

        if(M.tu<0)cout<<"输入元素个数不合法,请重新输入!"<<endl;

        if(M.tu>M.mu*M.nu){

            cout<<"输入错误,非零元素个数要小于等于行数乘列数,请重新输入!"<<endl;

        }

        else{

            break;

        }

    }

    cout<<"请输入矩阵元素(元素下标不能重复,且下标需要递增):"<<endl;

    for(int p=1;p<=M.tu;p++){

        cin>>M.data[p].i>>M.data[p].j>>M.data[p].e;

        if(M.data[p].i>M.mu||M.data[p].j>M.nu||M.data[p].i<=0||M.data[p].j<=0){

            cout<<"元素输入位置不合法,请重新输入"<<endl;

            p--;

        }

        int q;

        if(p>1){

            for(q=1;q<p;q++){

                if(M.data[p].i==M.data[q].i&&M.data[p].j==M.data[q].j){

                    cout<<"输入错误,输入下标重复,请重新输入!"<<endl;

                    p--;

                    break;

                }

                else if(M.data[p].i<M.data[q].i){

                    cout<<"输入错误,下标输入时要递增输入,请重新输入!"<<endl;

                    p--;

                    break;

                }

                else if(M.data[p].i==M.data[q].i&&M.data[p].j<M.data[q].j){

                    cout<<"输入错误,下标输入时要递增输入,请重新输入!"<<endl;

                    p--;

                    break; 

                }

            }

        }

    }

    cout<<"矩阵元素输入完成!"<<endl;

}

//输出

void PrintSMatrix(TsMatrix M){

    int cnt=1;

    for(int r=1;r<=M.mu;r++){

        for(int c=1;c<=M.nu;c++){

            if(r==M.data[cnt].i&&c==M.data[cnt].j){

                cout<<M.data[cnt].e<<" ";

                cnt++;

            }

            else cout<<"0"<<" ";

        }

        cout<<endl;

    }

}

//销毁

Status DestoryTsMatrix(TsMatrix &M){

    for(int i=0;i<=M.tu;i++){

        M.data[i].e=0;

        M.data[i].i=0;

        M.data[i].j=0;

    }

    M.mu=0;M.nu=0;M.tu=0;

    return OK;

}

//转置矩阵

Status TransPoseSMatrix(TsMatrix M,TsMatrix &T){

    T.mu=M.nu;

    T.nu=M.mu;

    T.tu=M.tu;

    if(T.tu){

        int q=1;

        for(int col=1;col<=M.nu;col++){

            for(int p=1;p<=M.tu;p++){

                if(M.data[p].j==col){

                    T.data[q].i=M.data[p].j;

                    T.data[q].j=M.data[p].i;

                    T.data[q].e=M.data[p].e;

                    q++;

                }

            }

        }

    }

    return OK;

}

//快速转置矩阵

Status FastTransposeSMatrix(TsMatrix M,TsMatrix &T){

    T.mu=M.nu;

    T.nu=M.mu;

    T.tu=M.tu;

    int num[99];int cpot[99];

    if(T.tu){

        for(int i=1;i<=M.nu;i++){

            num[i]=0;

        }

        for(int i=1;i<=M.tu;i++){

            num[M.data[i].j]++;

        }

        cpot[1]=1;

        for(int col=2;col<=M.nu;col++){

            cpot[col]=cpot[col-1]+num[col-1];

        }

        for(int p=1;p<=M.tu;p++){

            int col,q;

            col=M.data[p].j;

            q=cpot[col];

            T.data[q].i=M.data[p].j;

            T.data[q].j=M.data[p].i;

            T.data[q].e=M.data[p].e;

            cpot[col]++;

        }

    }

    return OK;

}

int main(){

    int n = 1;//退出菜单的标记

        cout<<"====欢迎使用集合运算小工具~~===="<<endl;

        cout<<"++输入对应数字指令实现相应功能++"<<endl;

        cout<<"********1---创建矩阵********"<<endl;

        cout<<"********2---销毁矩阵********"<<endl;

        cout<<"********3---输出矩阵********"<<endl;

        cout<<"********4---转置矩阵********"<<endl;

        cout<<"********5---快速转置矩阵******"<<endl;

        cout<<"*****输入一个负数退出程序~*****"<<endl;

   

    while(n){//n不等于0  n!=0

        int s;     

        cout<<"请输入指令编号(1--5),(退出时输入负数):\n";       

        scanf("%d",&s);

        switch(s){

            case 1:

                CreateSMatrix(M);

                flag=1;

                break;

            case 2:

                if(flag){

                    if(DestoryTsMatrix(M)==OK){

                        flag=0;

                        cout<<"销毁成功!"<<endl;

                    }

                }

                else

                cout<<"请先创建一个矩阵!"<<endl;

                break;

            case 3:

                if(flag){

                cout<<"矩阵为:"<<endl;

                PrintSMatrix(M);

            }

                else

                cout<<"请先创建一个矩阵!"<<endl;

                break;

            case 4:

                if(flag){

                    if(TransPoseSMatrix(M,T)==OK){

                        cout<<"转置成功,转置后的矩阵为:"<<endl;

                        PrintSMatrix(T);

                    }

                }

                else

                cout<<"请先创建一个矩阵"<<endl;

                break;

            case 5:

                if(flag){

                    if(FastTransposeSMatrix(M,T)==OK){

                        cout<<"转置成功,转置后的矩阵为:"<<endl;

                        PrintSMatrix(T);

                    }

                }

                else

                cout<<"请先创建一个矩阵"<<endl;

                break;

            default:

           

                if(s<0){

                    n = 0;

                    cout<<"程序退出成功,欢迎下次使用~~"<<endl;

                    break;

                }

                else

                    cout<<"您输入的指令有误,请重新输入~"<<endl;

             

        }

    }

    return 0;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值