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

#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);
}

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

时间: 2024-08-26 10:49:28

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

稀疏矩阵的三元组顺序表存储及矩阵相乘算法小结

稀疏矩阵的三元组顺序表存储及矩阵相乘算法小结 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 一:稀疏矩阵的三元组顺序表数据结构 typedef int ElemType; typedef struct { intx, y;  //该非零元素的行下标和列下标 ElemTypee; //该非零元素的值 } Triple; typedef struct { Tripledata[MAXSIZE]; //非零元素三元组顺序表 intmu, nu, t

稀疏矩阵的三元组顺序表的C语言实现

对于没有排序功能的集合来说,都可以使用java.util.Collections.sort()方法进行排序,它除了集合对象以外,还需要提供一个比较器.如果列表中的元素全部都是相同的类型,并且这个类实现了Comparable接口,就可以简单的调用Collections.sort()方法,如果这个类没有实现comparable接口,那么可以创建一个比较器传递一个Comparator实例作为Sort()的第二个参数进行排序,另外,如果不想使用默认的分类顺序进行排序,同样也可以传递一个Comparato

稀疏矩阵的三元组行逻辑链接的顺序表存储结构表示及实现

#define MAX_SIZE 100 #define MAX_RC 20 struct Triple { int i, j;//行下标,列下标 ElemType e;//非零元素值 }; struct RLSMatrix { Triple data[MAX_SIZE + 1];//非零元三元组表,data[0]未用 int rpos[MAX_RC + 1];//各行第1个非零元素的位置表 int mu, nu, tu;//矩阵的行数,列数,非零元个数 }; int comp(int c1,

7-4-无向图的邻接多重表存储结构-图-第7章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第7章  图 - 无向图的邻接多重表存储结构 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c.LinkQueue.c      

线性表存储结构的选择

1.从存储的角度考虑: 顺序表的存储空间是静态分布的,在程序执行之前必须明确规定它的规模,也就是说事先对MAXSIZE要有合适的设计,过大造成浪费,过小容易溢出. 点线性表的长度或存储规模难以估计时,不易采用顺序表:链表不用事先估计存储规模,链表存储密度低,(存储密度是指一个节点中数据元素所占的存储单元和整个节点所占存储单元之比.) 链式存储结构的存储密度小于1. 2.从运算的角度考虑: 在顺序表中按序号访问ai的时间复杂度是O(1),而链表中按序号查找的时间复杂度是O(n),如果经常做的运算是

几种常见的线性表存储结构

1.线性表的的动态分配顺序存储结构 1 #define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量 2 #define LISTINCREMENT 100 //线性表存储空间的分配增量 3 typedef struct { 4 ElemType *elem; //存储空间基址 5 int length; //当前长度 6 int size; //当前分配的存储容量 7 }SqList; //动态分配 + 顺序存储结构 2.线性表的单链表存储结构 1 typedef st

三元组顺序表表示的稀疏矩阵的转置和加法运算的实现----《数据结构》

#include<stdio.h> #include<malloc.h> #include<stdlib.h> #include<string.h> #define MAXSIZE 225 #define N 9 typedef struct{ int i,j; int e; }Triple; typedef struct{ Triple data[MAXSIZE+1]; int mu,nu,tu; }TSMatrix; int CreatSMatrix(T

Java栈之顺序栈存储结构实现

一.栈的基本定义 栈是一种数据结构,它代表一种特殊的线性表,这种线性表只能在固定一端(通常认为是线性表的尾端)进行插入.删除操作的特殊线性表,通常就是在线性表的尾端进行插入.删除操作. 二.顺序栈的实现 顺序栈是利用一组地址连续的存储单元依次存放从栈底到栈顶的数据元素,栈底位置固定不变,它的栈顶元素可以直接通过顺序栈底层数组的数组元素arr[size - 1]来访问. 1 package com.ietree.basic.datastructure.stack; 2 3 import java.

MySQL两种表存储结构MyISAM和InnoDB的性能比较测试

转载 http://www.jb51.net/article/5620.htm MySQL支持的两种主要表存储格式MyISAM,InnoDB,上个月做个项目时,先使用了InnoDB,结果速度特别慢,1秒钟只能插入10几条.后来换成MyISAM格式,一秒钟插入上万条.当时决定这两个表的性能也差别太大了吧.后来自己推测,不应该差别这么慢,估计是写的插入语句有问题,决定做个测试:测试环境:Redhat Linux9,4CPU,内存2G,MySQL版本为4.1.6-gamma-standard测试程序: