数据结构-稀疏矩阵

一、稀疏矩阵

1.1 概念

矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。

二、图解和代码实现

2.1 结构图

稀疏矩阵

由上图可知非零元素远少于零元素,这是稀疏矩阵最大的特点

2.2 代码实现

Triple.cpp

/**
 * @Author: lwj
 * @Date: 2022-06-04 20:09:36
 * @Description:三元组表构建稀疏矩阵
 * @FilePath: /Linux_C_C-plus-plus/数据结构(C++)/Triple/triple.h
 **/
#include <iostream>
#include <assert.h>

template <typename Type>
class Triple //三元组表
{
private:
    struct Node //三元组表的类型,一个struct类型代表一个结点
    {
        int row;                                 //非零元素的行号
        int col;                                 //非零元素的列号
        Type data;                               //非零元素的值
        Node(int r = -1, int c = -1, Type d = 0) //结点构造函数
        {
            row = r;
            col = c;
            data = d;
        }
        void pushNodeValue(int r, int c, Type d) //元素赋值
        {
            row = r;
            col = c;
            data = d;
        }
    };
    Node *matrix; //三元组表
    int numRow;   //矩阵的行数
    int numCol;   //矩阵的列数
    int count;    //非零元素个数
    int maxSize;  //矩阵容量
public:
    Triple(int r, int c, int size = 10);            //构造函数,默认矩阵容量为10
    ~Triple() { delete[] matrix; }                  //析构函数
    void pushValue(int r, int c, const Type &size); //元素赋值
    Type getValue(int r, int c) const;              //取元素的值
    void transpose(const Triple<Type> &t);          //用当前对象保存A的转置的三元组表
    void print() const;                             //输出三元组表
    void resize();                                  //扩大三元组表空间
};
template <typename Type>
Triple<Type>::Triple(int r, int c, int size) //行数r,列数c,非零个数size
{
    assert(r >= 0 && c >= 0 && size >= 0); //判定传入的数是否越界
    numRow = r;
    numCol = c;
    count = 0;
    if (r * c > size) // r*c为最大容量
    {
        maxSize = size;
    }
    else
    {
        maxSize = r * c; //最多只能有c*r个非零元素
    }
    if (maxSize != 0)
    {
        matrix = new Node[maxSize]; //开辟矩阵空间
    }
    else
    {
        matrix = nullptr;
    }
}
template <typename Type>
void Triple<Type>::pushValue(int r, int c, const Type &size) //元素赋值
{
    if (size == 0) // 0不存储
    {
        return;
    }
    assert(r >= 0 && r < numRow && c >= 0 && c < numCol); //越界报错
    if (count == maxSize)                                 //空间满扩容
    {
        resize();
    }
    int i;
    for (i = 0; i < count; i++)
    {
        if (matrix[i].row > r || (matrix[i].row == r && matrix[i].col > c))
        {
            break; //说明要插入的位置没有元素,跳出循环
        }
        if (matrix[i].row == r && matrix[i].col == c)
        {
            //说明要插入位置已有元素,则用新值覆盖它
            matrix[i].pushNodeValue(r, c, size);
            return;
        }
    }
    for (int j = count - 1; j >= i; j--)
    {
        matrix[j + 1] = matrix[j];
    }
    matrix[i].pushNodeValue(r, c, size);
    count++;
}
template <typename Type>
Type Triple<Type>::getValue(int r, int c) const //取元素的值
{
    if (count == 0) //如果为空,直接返回0
    {
        return 0;
    }
    assert(r >= 0 && r < numRow && c >= 0 && c < numCol); //越界报错
    for (int i = 0; i < count; i++)
    {
        if (matrix[i].row == r && matrix[i].col == c)
        {
            return matrix[i].data;
        }
    }
    return 0;
}
// a为未逆置前,b是逆置后,根据矩阵的规律发现,逆置后:a[i][j]=b[j][i]
template <typename Type>
void Triple<Type>::transpose(const Triple<Type> &A) //用当前对象保存A的转置的三元组表
{
    //先构建b矩阵
    numCol = A.numRow;
    numRow = A.numCol;
    if (maxSize < A.count) //如果b矩阵存不下a的逆置,重新开辟空间
    {
        maxSize = A.maxSize;
        delete[] matrix; //释放b的空间
        matrix = new Node[maxSize];
    }
    count = A.count;
    int q = 0;                         //控制当前对象matrix空间的下标
    for (int i = 0; i < A.numCol; i++) //按列转序,列号不为-1则存在非0元素
    {
        for (int j = 0; j < A.count; j++) // j控制对象A的数组的下标
        {
            if (A.matrix[j].col == i)
            {
                matrix[q].row = A.matrix[j].col;
                matrix[q].col = A.matrix[j].row;
                matrix[q].data = A.matrix[j].data;
                q++;
            }
        }
    }
}

template <typename Type>
void Triple<Type>::print() const //输出三元组表
{
    std::cout << "Row:" << numRow << "\t"
              << "Col:" << numCol << "\t"
              << "Count:" << count << std::endl;
    for (int i = 0; i < count; i++)
    {
        std::cout << "(" << matrix[i].row << ","
                  << matrix[i].col << ","
                  << matrix[i].data << ")" << std::endl;
    }
}

template <typename Type>
void Triple<Type>::resize() //扩大三元组表空间
{
    Node *tmp = matrix; //把原空间先给tmp保管
    if (2 * maxSize > numRow * numCol)
    {
        maxSize = numRow * numCol;
    }
    else
    {
        maxSize = 2 * maxSize;
    }
    matrix = new Node[maxSize];     //创建新空间
    for (int i = 0; i < count; i++) //把数据放入新空间中
    {
        matrix[i] = tmp[i];
    }
    delete[] tmp;
    tmp = nullptr;
}

main.cpp

/**
 * @Author: lwj
 * @Date: 2022-06-04 20:11:32
 * @Description:稀疏矩阵的测试
 * @FilePath: /Linux_C_C-plus-plus/数据结构(C++)/Triple/main.cpp
 **/
#include <iostream>
#include "triple.h"

using namespace std;
void test01()
{
    Triple<int> T1(3, 3, 2);
    T1.pushValue(0, 2, 3);
    T1.pushValue(0, 1, 2);
    T1.pushValue(0, 0, 1);
    T1.print();
    //取位置为(2,0),(0,2)的元素
    int value01 = T1.getValue(2, 0);
    int value02 = T1.getValue(0, 2);
    cout << "value01 = " << value01 << "\t"
         << "value02 = " << value02 << endl;
    //逆置
    Triple<int> T2(3, 3, 2);
    T2.transpose(T1);
    T2.print();
}
int main()
{
    test01();
    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里狼~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值