码迷,mamicode.com
首页 > 其他好文 > 详细

稀疏矩阵的三元组顺序表存储结构表示及实现

时间:2015-08-07 20:10:50      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:c   数据结构   考研   计算机专业   

#define MAX_SIZE 100

struct Triple
{
    int i, j;//行下标,列下标
    ElemType e;//非零元素值
};

struct TSMatrix
{
    Triple data[MAX_SIZE + 1];//非零元三元组表,data[0]未用
    int mu, nu, tu;//矩阵的行数,列数,非零元个数
};
int comp(int c1, int c2){//比较这个数c1和c2的大小关系
    if (c1 < c2)
        return -1;
    if (c1 == c2)
        return 0;
    return 1;
}

Status CreateSMatrix(TSMatrix &M){//创建稀疏矩阵M
    int i;
    Triple T;
    Status k;
    printf("请输入矩阵的行数,列数,非零元素个数:");
    scanf("%d,%d,%d", &M.mu, &M.nu, &M.tu);
    if (M.tu > MAX_SIZE)//非零元个数太多
        return ERROR;
    M.data[0].i = 0;//为以下比较顺序做准备
    for (i = 1; i <= M.tu; i++)//依次输入M.tu个非零元素
    {
        do{
            printf("请按行序顺序输入第%d个非零元素所在的行(1~%d),列(1~%d),元素值:", i, M.mu, M.nu);
            scanf("%d,%d,%d", &T.i, &T.j, &T.e);
            k = 0;//输入值的范围正确的标志
            if (T.i < 1 || T.i > M.mu || T.j < 1 || T.j > M.nu)//行或列超出范围
                k = 1;
            if (T.i < M.data[i - 1].i || T.i == M.data[i - 1].i && T.j <= M.data[i - 1].j)
                k = 1;//行或列的顺序有错
        } while (k);//输入值的范围不正确则重新输入
        M.data[i] = T;//将输入正确的值赋给三元组结构体M的相应单元
    }
    return OK;
}

Status AddSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q){//求稀疏矩阵的和Q = M + N
    int m = 1, n = 1, q = 0;
    if (M.mu != N.mu || M.nu != N.nu)//M,N两稀疏矩阵行或列数不同
        return ERROR;
    Q.mu = M.mu;//设置稀疏矩阵Q的行数和列数
    Q.nu = M.nu;
    while (m <= M.tu && n <= N.tu)//矩阵M和N的元素都未处理完
    {
        switch (comp(M.data[m].i, N.data[n].i))//比较两当前元素的行值关系
        {
        case -1:Q.data[++q] = M.data[m++];//矩阵M的行值小,将M的当前元素值赋给矩阵Q
            break;
        case 0:switch (comp(M.data[m].j, N.data[n].j))//M,N矩阵当前元素的行值相等,继续比较两当前元素的列值关系
        {
        case -1:Q.data[++q] = M.data[m++];//矩阵M的列值小,将M的值赋给矩阵Q
            break;
        case 0:Q.data[++q] = M.data[m++];//M,N矩阵当前非零元素的行列均相等,将两元素求和并赋给矩阵Q
            Q.data[q].e += N.data[n++].e;
            if (Q.data[q].e == 0)//两元素之和为0,不存入稀疏矩阵
                q--;
            break;
        case 1:Q.data[++q] = N.data[n++];//矩阵N的列值小,将N的值赋给矩阵Q
            break;
        }
            break;
        case 1:Q.data[++q] = N.data[n++];//矩阵N的列值小,将N的值赋给矩阵Q
        }
    }//以下2个循环最多执行1个
    while (m <= M.tu)//矩阵N的元素已全部处理完毕,处理矩阵M的元素
        Q.data[++q] = M.data[m++];
    while (n <= N.tu)//矩阵M的元素已全部处理完毕,处理矩阵N的元素
        Q.data[++q] = N.data[n++];
    if (q > MAX_SIZE)//非零元素个数太多
        return ERROR;
    Q.tu = q;//矩阵Q的非零元素个数
    return OK;
}

void TransposeSMatrix(TSMatrix M, TSMatrix &T){//求稀疏矩阵M的转置矩阵T
    int p, col, q = 1;//q指示转置矩阵T的当前元素,初值为1
    T.mu = M.nu;//矩阵T的行数 = 矩阵M的列数
    T.nu = M.mu;//矩阵T的列数 = 矩阵M的行数
    T.tu = M.tu;//矩阵T的非零元素个数 = 矩阵M的非零元素个数
    if (T.tu)//矩阵非空
    {
        for (col = 1; col <= M.nu; ++col)//从矩阵T的第1行到最后一行
        {
            for (p= 1; p <= M.tu; ++p)//对于矩阵M的所有元素
            {
                if (M.data[p].j == col)//该元素的列数 = 当前矩阵T的行数
                {
                    T.data[q].i = M.data[p].j;//将矩阵M的值行列对调赋给T的当前元素
                    T.data[q].j = M.data[p].i;
                    T.data[q++].e = M.data[p].e;//转置矩阵T的当前元素指针+1
                }
            }
        }
    }
}

Status MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q){//求稀疏矩阵的乘积Q = M * N
    int i, j, q, p;
    ElemType Qs;//矩阵单元Q[i][j]的临时存放处
    TSMatrix T;//N的转秩矩阵
    if (M.nu != N.mu)//矩阵M和N无法相乘
        return ERROR;
    Q.mu = M.mu;//Q的行数 = M的行数
    Q.nu = N.nu;//Q的列数 = M的列数
    Q.tu = 0;//Q的非零元素个数的初值为0
    TransposeSMatrix(N, T);//T是N的转秩矩阵
    for (i = 1; i <= Q.mu; i++)//对于M的每一行,求Q[i][]
    {
        q = 1;//q指向M的第1个非零元素
        for (j = 0; j  <= T.mu; j ++)//对于T的每一行(即N的每一列),求Q[i][j]
        {
            Qs = 0;//设置Q[i][j]的初值为0
            p = 1;//p指向M的第1个非零元素
            while (M.data[p].i < i)//使p指向矩阵M的第i行的第1个非零元素
                p++;
            while (T.data[q].i < j)//使q指向矩阵T的第j行(即矩阵N的第j列)的第一个非零元素
                q++;
            while (p <= M.tu && q <= T.tu && M.data[p].i == i && T.data[q].i == j)
            {//[p]仍是M的第i行的非零元素且[q]仍是T的第j行(即N的第j列)的非零元素
                switch (comp(M.data[p].j, T.data[q].i))//比较M矩阵当前元素的列值和T矩阵当前元素的列值(即N矩阵当前元素的行值)
                {
                case -1:p++;//M矩阵当前元素的列值<T(N)矩阵当前元素的列(行)值,p向后移
                    break;
                case 0:Qs += M.data[p++].e * T.data[q++].e;//M当前元素的列值 = T(N)当前元素的列(行)值,则两值相乘并累加到Qs,p、q均向后移
                    break;
                case 1:q++;//M矩阵当前元素的列值>T(N)矩阵当前元素的列(行)值,q向后移
                }
                if (Qs)//Q[i][j]不为0
                {
                    if (++Q.tu > MAX_SIZE)//Q的非零元素个数+1.如果非零元素个数过多
                        return ERROR;
                    Q.data[Q.tu].i = i;//将Q[i][j]按顺序存入稀疏矩阵Q
                    Q.data[Q.tu].j = j;
                    Q.data[Q.tu].e = Qs;
                }
            }
        }
    }
    return OK;
}

void DestroySMatrix(TSMatrix &M){//销毁稀疏矩阵M
    M.mu = M.nu = M.tu = 0;
}

void PrintSMatrix(TSMatrix M){//按矩阵形式输出M
    int i, j, k = 1;//非零元计数器,初值为1
    Triple * p = M.data + 1;//p指向M的第1个非零元素
    for (i = 1; i <= M.mu; i++)//从第1行到最后一行
    {
        for (j = 1; j <= M.nu; j++)//从第1列到最后一列
        {
            if (k <= M.tu && p->i == i && p->j == i)//p指向非零元,且p所指元素为当前循环在处理元素
            {
                printf("%3d", (p++)->e);//输出p所指元素的值,p指向下一个元素
                k++;//计数器+1
            }
            else//p指向元素不是当前循环在处理元素
                printf("%3d", 0);//输出0
        }
        printf("\n");
    }
}

void CopySMatrix(TSMatrix M, TSMatrix &T){//由稀疏矩阵M复制得T
    T = M;
}

Status SubtSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q){//求系数矩阵的差Q = M - N
    int i;
    if (M.mu != N.nu || M.nu != N.nu)//M,N两稀疏矩阵行或列数不同
        return ERROR;
    for (i = 1; i <= N.tu; ++i)//对于N的每一元素,其他乘以-1
        N.data[i].e *= -1;
    AddSMatrix(M, N, Q);//Q = M + (- N)
    return OK;
}

void FastTransposeSMatrix(TSMatrix M, TSMatrix &T){//快速求稀疏矩阵M的转置矩阵T
    int p, q, col, *num, *cpot;
    num = (int *)malloc((M.nu + 1) * sizeof(int));//存M每列(T每行)非零元素个数([0]不用)
    cpot = (int *)malloc((M.nu + 1) * sizeof(int));//存T每行下一个非零元素的位置([0]不用)
    T.mu = M.nu;//T的行数 = M的列数
    T.nu = M.mu;//T的列数 = M的行数
    T.tu = M.tu;//T的非零元素个数 = M的非零元素个数
    if (T.tu)//T是非零矩阵
    {
        for (col = 1; col <= M.nu; ++col)//从M的第1列到最后一列
            num[col] = 0;//计数器初值设为0
        for (p = 1; p <= M.tu; ++p)//对于M的每一个非零元素
            ++num[M.data[p].j];//根据它所在的列进行统计
        cpot[1] = 1;//T的第1行的第1个非零元在T.data中的序号为1
        for (col = 2; col <= M.nu; ++col)//从M(T)的第2列(行)到最后一列(行)
            cpot[col] = cpot[col - 1] + num[col - 1];//求T的第col行第1个非零元在T.data中的序号
        for (p = 1; p <= M.tu; ++p)//对于M的每一个非零元素
        {
            col = M.data[p].j;//将其在M中的列数赋给col
            q = cpot[col];//q指示M当前的元素在T中的序号
            T.data[q].i = M.data[p].j;//将M当前的元素转秩赋给T
            T.data[q].j = M.data[p].i;
            T.data[q].e = M.data[p].e;
            ++cpot[col];//T第col行的下1个非零元在T.data中的序号比当前元素的序号大1
        }
    }
    free(num);//释放num和cpot所指向的动态存储空间
    free(cpot);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

稀疏矩阵的三元组顺序表存储结构表示及实现

标签:c   数据结构   考研   计算机专业   

原文地址:http://blog.csdn.net/zhou554291911/article/details/47341245

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!