稀疏矩阵(十字链表存储)6种操作的实现

/*   数据结构分析与学习专栏
*   Copyright (c) 2015, 山东大学 计算机科学与技术专业 学生
*   All rights reserved.
*   作    者:   高祥
*   完成日期:  2015 年 4 月 11 日
*   版 本 号:016

*任务描述:针对稀疏矩阵,实现6个基本操作
*   1:建立稀疏矩阵 ;
*   2:输出稀疏矩阵 ;
*   3:转置稀疏矩阵 ;
*   4:稀疏矩阵相加 ;
*   5:稀疏矩阵相减;
*   6:稀疏矩阵相乘 ;

*主要函数:
*   1.void InitMatrix(Matrix &M);//初始化矩阵
*   2.void InsertElem(Link &newnode,Matrix &M);//将已有的非零元素结点插入到矩阵中
*   3.void DeleteElem(Matrix &M,Link &deletenode,int row,int line);//删除在(row,line)处的结点
*   4.void CreateMatrix(Matrix &M);//创建矩阵
*   5.void Output(Matrix M);//输出矩阵
*   6.void TransposeMatrix(Matrix &M);//转置矩阵
*   7.void AddMatrix(Matrix &M,Matrix &N);//矩阵相加
*   8.void SubtractMatrix(Matrix &M,Matrix &N);//矩阵相减
*   9.void MultiplyMatrix(Matrix &M,Matrix &N);//矩阵相乘

*/
#include
#include
#include
using namespace std;

#define OK 1
#define FALSE 0

typedef int Status;
typedef int ElemType;

typedef struct node
{
    int row;//非零元素的行数
    int line;//非零元素的列数
    ElemType elem;//非零元素的大小
    struct node *right;//同一行的链接
    struct node *down;//同一列的链接
} Node,*Link;

typedef struct
{
    Link *rowhead;//所有行链表表头的指针数组
    Link *linehead;//所有列链表表头的指针数组
    int rownum;//矩阵的总行数
    int linenum;//矩阵的总列数
    int elemnum;//矩阵的非零元素总数
} Matrix;

void InitMatrix(Matrix &M);//初始化矩阵
void InsertElem(Link &newnode,Matrix &M);//将已有的非零元素结点插入到矩阵中
void DeleteElem(Matrix &M,Link &deletenode,int row,int line);//删除在(row,line)处的结点
void CreateMatrix(Matrix &M);//创建矩阵
void Output(Matrix M);//输出矩阵
void TransposeMatrix(Matrix &M);//转置矩阵
void AddMatrix(Matrix &M,Matrix &N);//矩阵相加
void SubtractMatrix(Matrix &M,Matrix &N);//矩阵相减
void MultiplyMatrix(Matrix &M,Matrix &N);//矩阵相乘
void Interaction();//输出操作

int main()
{
    Interaction();

    Matrix M,N;
    int operate;

    while(cin>>operate)
    {
        switch(operate)
        {
        case 0:
            return 0;

        case 1:
            cout<<"请输入创建的稀疏矩阵的行数、列数、非0元素个数:";
            cin>>M.rownum>>M.linenum>>M.elemnum;
            CreateMatrix(M);
            break;

        case 2:
            Output(M);
            break;

        case 3:
            TransposeMatrix(M);
            break;

        case 4:
INPUT1:
            cout<<"请输入创建的稀疏矩阵的行数、列数、非0元素个数:";
            cin>>N.rownum>>N.linenum>>N.elemnum;
            if(M.rownum!=N.rownum||M.linenum!=N.linenum)
            {
                cout<<"矩阵相加的前提是两个矩阵的行数列数分别相等。请创建合法的矩阵。\n";
                goto INPUT1;
            }

            CreateMatrix(N);
            AddMatrix(M,N);
            break;

        case 5:
INPUT2:
            cout<<"请输入创建的稀疏矩阵的行数、列数、非0元素个数:";
            cin>>N.rownum>>N.linenum>>N.elemnum;
            if(M.rownum!=N.rownum||M.linenum!=N.linenum)
            {
                cout<<"矩阵相减的前提是两个矩阵的行数列数分别相等。请创建合法的矩阵。\n";
                goto INPUT2;
            }

            CreateMatrix(N);
            SubtractMatrix(M,N);
            break;

        case 6:
INPUT3:
            cout<<"请输入创建的稀疏矩阵的行数、列数、非0元素个数:";
            cin>>N.rownum>>N.linenum>>N.elemnum;
            if(M.linenum!=N.rownum)
            {
                cout<<"矩阵相乘的前提是矩阵1的列数等于矩阵2的行数。请创建合法的矩阵。\n";
                goto INPUT3;
            }

            CreateMatrix(N);
            MultiplyMatrix(M,N);
            break;

        default:
            cout<<"请输入正确的操作数字!\n";
        }
    }

    return 0;
}

void InitMatrix(Matrix &M)//初始化矩阵
{
    M.rowhead=(Link *)malloc((M.rownum+1)*sizeof(Link));//为每行的行链表分配一个指向该链表的指针
    M.linehead=(Link *)malloc((M.linenum+1)*sizeof(Link));//为每列的列链表分配一个指向该链表的指针

    //未填充元素,所有链表均为空,置空两个指针数组
    for(int index=1; index<=M.rownum; index++)
    {
        M.rowhead[index]=NULL;
    }
    for(int index=1; index<=M.linenum; index++)
    {
        M.linehead[index]=NULL;
    }
}

void InsertElem(Link &newnode,Matrix &M)//将已有的非零元素结点插入到矩阵中
{
    //插入到对应的行链表中:讨论插在头结点还是后续的结点
    Link rowcur=M.rowhead[newnode->row];
    if(rowcur==NULL||rowcur->line>newnode->line)//若行链表为空或者已有的头结点的列数较大,插在头结点
    {
        newnode->right=rowcur;
        M.rowhead[newnode->row]=newnode;
    }
    else//否则插在非头结点处
    {
        //找应该插的结点位置的前一个结点:
        for(; !(rowcur->lineline&&(rowcur->right==NULL||rowcur->right->line>newnode->line)); rowcur=rowcur->right);
        //找到并插入
        newnode->right=rowcur->right;
        rowcur->right=newnode;
    }

    //列链表的插入原理同上
    Link linecur=M.linehead[newnode->line];
    if(linecur==NULL||linecur->row>newnode->row)
    {
        newnode->down=linecur;
        M.linehead[newnode->line]=newnode;
    }
    else
    {
        for(; !(linecur->rowrow&&(linecur->down==NULL||linecur->down->row>newnode->row)); linecur=linecur->down);
        newnode->down=linecur->down;
        linecur->down=newnode;
    }
}

void DeleteElem(Matrix &M,Link &deletenode,int row,int line)
{
    //首先更新行链表的链接:讨论该节点是否为该行链表的头结点
    if(deletenode==M.rowhead[row])
    {
        M.rowhead[row]=deletenode->right;
    }
    else
    {
        Link prenode=M.rowhead[row];
        while(prenode->right!=deletenode)
        {
            prenode=prenode->right;
        }
        prenode->right=deletenode->right;
    }

    //然后更新列链表的链接:讨论该节点是否为该列链表的头结点
    if(deletenode==M.linehead[line])
    {
        M.linehead[line]=deletenode->down;
    }
    else
    {
        Link prenode=M.linehead[line];
        while(prenode->down!=deletenode)
        {
            prenode=prenode->down;
        }
        prenode->down=deletenode->down;
    }

    Link temp=deletenode->right;//预存下一个结点
    free(deletenode);//释放该结点的内存
    deletenode=temp;
}

void CreateMatrix(Matrix &M)//创建矩阵
{
    InitMatrix(M);//首先初始化矩阵

    cout<<"请输入"<>newnode->row>>newnode->line>>newnode->elem;//生成新节点
        InsertElem(newnode,M);//调用插入函数
    }

    cout<<"创建的稀疏矩阵为:\n";
    Output(M);
}

void Output(Matrix M)//输出矩阵
{
    for(int row=1; row<=M.rownum; row++)
    {
        Link cur=M.rowhead[row];
        for(int line=1; line<=M.linenum; line++)
        {
            if(cur&&cur->line==line)
            {
                cout<elem;
                cur=cur->right;
            }
            else
            {
                cout<right;//预存后一个结点
            swap(cur1->row,cur1->line);
            swap(cur1->right,cur1->down);
            cur1=cur2;
        }
    }
    swap(M.rownum,M.linenum);//交换矩阵的行列数
    swap(M.rowhead,M.linehead);//交换矩阵的行列链表的指针数组

    cout<<"转置后的矩阵是:\n";
    Output(M);
}

void AddMatrix(Matrix &M,Matrix &N)//矩阵相加
{
    for(int row=1; row<=M.rownum; row++)
    {
        Link cur1=M.rowhead[row];
        Link cur2=N.rowhead[row];
        for(int line=1; line<=M.linenum; line++)
        {
            //对应位置的非零元素存在情况共四种:
            //当M有且N也有时:将运算结果赋给M,若结果为0,则删除M对应的结点,注意必须更新链接
            if(cur1&&cur1->line==line&&cur2&&cur2->line==line)
            {
                cur1->elem=cur1->elem+cur2->elem;
                if(cur1->elem!=0)
                {
                    cur1=cur1->right;
                }
                else//删除M的结点
                {
                    M.elemnum--;
                    DeleteElem(M,cur1,row,line);
                }

                Link temp=cur2->right;
                free(cur2);//N的运算后的结点已没有存在的意义,释放其内存
                cur2=temp;
            }
            //当M没有N有时:将N的结点插入到M中
            if((cur1==NULL||cur1->line!=line)&&cur2&&cur2->line==line)
            {
                M.elemnum++;
                Link temp=cur2->right;
                InsertElem(cur2,M);//调用插入结点函数
                cur2=temp;
            }
            //当M有N没有时:只需要右移M的指针
            if(cur1&&cur1->line==line&&(cur2==NULL||cur2->line!=line))
            {
                cur1=cur1->right;
            }
            //当M、N都没有时,无需考虑。
        }
    }

    cout<<"相加后的矩阵是:\n";
    Output(M);
}


void SubtractMatrix(Matrix &M,Matrix &N)//矩阵相减
{
    //基本同矩阵相加的算法
    for(int row=1; row<=M.rownum; row++)
    {
        Link cur1=M.rowhead[row];
        Link cur2=N.rowhead[row];
        for(int line=1; line<=M.linenum; line++)
        {
            if(cur1&&cur1->line==line&&cur2&&cur2->line==line)
            {
                cur1->elem=cur1->elem-cur2->elem;
                if(cur1->elem!=0)
                {
                    cur1=cur1->right;
                }
                else
                {
                    M.elemnum--;
                    DeleteElem(M,cur1,row,line);
                }
                Link temp=cur2->right;
                free(cur2);
                cur2=temp;
            }

            if((cur1==NULL||cur1->line!=line)&&cur2&&cur2->line==line)
            {
                M.elemnum++;
                cur2->elem=-cur2->elem;
                Link temp=cur2->right;
                InsertElem(cur2,M);
                cur2=temp;
            }

            if(cur1&&cur1->line==line&&(cur2==NULL||cur2->line!=line))
            {
                cur1=cur1->right;
            }
        }
    }

    cout<<"相减后的矩阵是:\n";
    Output(M);
}

void MultiplyMatrix(Matrix &M,Matrix &N)
{
    Matrix Q;//结果矩阵
    Q.rownum=M.rownum;
    Q.linenum=N.linenum;
    Q.elemnum=0;
    InitMatrix(Q);//初始化矩阵

    int cnt=0;//计数矩阵中非零元素的个数
    //遍历行数列数:
    for(int row=1; row<=Q.rownum; row++)
    {
        for(int line=1; line<=Q.linenum; line++)
        {
            ElemType elem=0;
            Link cur1=M.rowhead[row];
            Link cur2=N.linehead[line];
            //做到求每个元素时,M的一行元素和N的一列元素只遍历一遍
            for(; cur1; cur1=cur1->right)
            {
                for(; cur2&&cur2->row<=cur1->line; cur2=cur2->down)
                {
                    if(cur2->row==cur1->line)
                    {
                        elem=elem+cur1->elem*cur2->elem;
                        break;
                    }
                }
            }

            if(elem)
            {
                cnt++;//计数器加1
                Link newnode=(Link )malloc(sizeof(Node));
                newnode->row=row;
                newnode->line=line;
                newnode->elem=elem;
                InsertElem(newnode,Q);//插入新结点
            }
        }
    }

    Q.elemnum=cnt;
    M=Q;
    cout<<"相乘后的稀疏矩阵为:\n";
    Output(M);
}

void Interaction()//输出操作
{
    cout<<"请输入对应操作的序号:\n";
    cout<<"0:退出程序 ;\n";
    cout<<"1:建立稀疏矩阵 ;\n";
    cout<<"2:输出稀疏矩阵 ;\n";
    cout<<"3:转置稀疏矩阵 ;\n";
    cout<<"4:稀疏矩阵相加 ;\n";
    cout<<"5:稀疏矩阵相减;\n";
    cout<<"6:稀疏矩阵相乘 ;\n";
}

你可能感兴趣的:(稀疏矩阵(十字链表存储)6种操作的实现)