代码小白写的关系矩阵

这篇博客介绍了C++中一个自定义的类`Matrix`,用于表示和操作矩阵,支持基本的初始化、添加元素、设置元素、显示、求和等操作。此外,还定义了一个`RelationSet`类来表示关系集合,并提供了关系矩阵的运算,如并集、自反闭包、对称闭包、传递闭包等。文章适用于离散数学和矩阵运算的学习。
摘要由CSDN通过智能技术生成
#pragma once
#include <iostream>
#include <vector>
#include <stdarg.h>
#include <set>
#include <map>
#include <initializer_list>
#define endll "\n"
using namespace std;
class _Matrix
{
protected:
    int rows;
    int cols;
    vector<vector<int>> v;

public:
    _Matrix() : rows(0), cols(0) {}
    _Matrix(int rows, int cols) : rows(rows), cols(cols)
    {
        for (int i = 0; i < rows; ++i)
        {
            v.push_back(vector<int>(cols));
        }
    }
    virtual bool scanf_initalize()
    {
        int temp;
        for (int i = 0; i < rows; ++i)
        {
            vector<int> vv;
            for (int j = 0; j < cols; ++j)
            {
                scanf("%d", &temp);
                vv.push_back(temp);
            }
            v.at(i) = vv;
        }
        return true;
    }
    virtual bool add(int num, ...)
    {
        if (cols == 0)
        {
            cols = num;
        }
        else if (num != cols)
        {
            throw "The matrix needs to be a rectangle";
        }
        vector<int> vv(num);
        va_list ptr;
        int temp;
        va_start(ptr, num);
        for (int i = 0; i < num; ++i)
        {
            temp = va_arg(ptr, int);
            vv.at(i) = temp;
        }
        va_end(ptr);
        v.push_back(vv);
        ++rows;
        return true;
    }
    virtual bool set_matrix_element(int row, int cols, int val)
    {
        if (row <= rows && row >= 0 && cols <= this->rows && cols >= 0)
        {
            v.at(row - 1).at(cols - 1) = val;
            return true;
        }
        return false;
    }
    int get_rows() const
    {
        return rows;
    }
    int get_cols() const
    {
        return cols;
    }
    void display() const //??
    {
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                cout << v[i][j] << " ";
            }
            cout << endll;
        }
    }
    void remove_clear()
    {
        v.clear();
        this->cols = 0;
        this->rows = 0;
    }
    int sum()
    {
        int s = 0;
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                s += v.at(i).at(j);
            }
        }
        return s;
    }
    _Matrix inverse()
    {
        _Matrix m(cols, rows);
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                m.v.at(j).at(i) = v.at(i).at(j);
            }
        }
        return m;
    }
    _Matrix& operator+=(const _Matrix& m)
    {
        if (m.cols == this->cols && m.rows == this->rows)
        {
            for (int i = 0; i < this->rows; ++i)
            {
                for (int j = 0; j < this->cols; ++j)
                {
                    this->v.at(i).at(j) += m.v.at(i).at(j);
                }
            }
        }
        else
        {
            throw "Different matrices for rows or columns are used";
        }
        return *this;
    }
    _Matrix& operator-=(const _Matrix& m)
    {
        if (m.cols == this->cols && m.rows == this->rows)
        {
            for (int i = 0; i < this->rows; ++i)
            {
                for (int j = 0; j < this->cols; ++j)
                {
                    this->v.at(i).at(j) -= m.v.at(i).at(j);
                }
            }
        }
        else
        {
            throw "Different matrices for rows or columns are used";
        }
        return *this;
    }
    _Matrix& operator*=(const _Matrix& m)
    {
        if (this->cols == m.rows)
        {
            _Matrix temp_m(*this);
            this->cols = m.cols;
            int element = 0;
            v.clear();
            for (int i = 0; i < temp_m.rows; ++i)
            {
                vector<int> temp_element;
                for (int k = 0; k < m.cols; ++k)
                {
                    for (int j = 0; j < m.rows; ++j)
                    {
                        element += temp_m.v.at(i).at(j) * m.v.at(j).at(k);
                    }
                    temp_element.push_back(element);
                    element = 0;
                }
                v.push_back(temp_element);
            }
            return *this;
        }
        else
        {
            throw "The number of rows and columns should be equal";
        }
    }
    _Matrix& operator*=(int m)
    {
        for (int i = 0; i < this->rows; ++i)
        {
            for (int j = 0; j < this->cols; ++j)
            {
                this->v.at(i).at(j) *= m;
            }
        }
        return *this;
    }
    friend _Matrix operator+(_Matrix a, _Matrix b)
    {
        return a += b;
    }
    friend _Matrix operator-(_Matrix a, _Matrix b)
    {
        return a -= b;
    }
    friend _Matrix operator*(_Matrix a, int b)
    {
        return (a *= b);
    }
    friend _Matrix operator*(int b, _Matrix a)
    {
        return a *= b;
    }
    friend _Matrix operator*(_Matrix a, _Matrix b)
    {
        return a *= b;
    }
    friend ostream& operator<<(ostream& os, const _Matrix& m)
    {
        m.display();
        return os;
    }
};
template <typename T>
class RelationSet : public set<pair<T, T>>
{
public:
    friend class Relation_matrix;
    RelationSet() {}
    RelationSet(set<pair<T, T>>& r) : set<pair<T, T>>(r) {}
    RelationSet(initializer_list<initializer_list<T>> il)
    {
        for (auto it = il.begin(); it != il.end(); ++it)
        {
            if (it->size() > 2)
                throw "Ordered couple needs two elements";
            auto itt = it->begin();
            int first_ = *itt;
            int second_ = *(++itt);
            this->emplace(first_, second_);
        }
    }
    void display() const
    {
        cout << "{";
        auto in_end = this->end();
        in_end--;
        for (auto it = this->begin(); it != in_end; ++it)
        {
            cout << "<" << it->first << "," << it->second << ">"
                << ",";
        }
        cout << "<" << in_end->first << "," << in_end->second << ">"
            << "}";
    }
    friend ostream& operator<<(ostream& os, const RelationSet& m)
    {
        m.display();
        return os;
    }
};
class Relation_matrix : public _Matrix
{
protected:
    bool isBitMatrix;
    bool equal_randc() const
    {
        return (rows == cols);
    }
    bool is_bit_matrix() const
    {
        return isBitMatrix;
    }
    void throw_exception() const
    {
        if (!equal_randc())
            throw "It's not a determinant";
        if (!is_bit_matrix())
            throw "It's not a binary matrix";
    }
    template<typename T>
    static void seach(T t, RelationSet<T>& r, set<T>& temp) {
        for (auto i = r.begin(); i != r.end(); ++i) {
            if (i->first == t && temp.find(i->second) == temp.end()) {
                temp.insert(i->second);
                seach(i->second, r, temp);
            }
        }
    }

public:
    Relation_matrix(int r_and_c) : _Matrix(r_and_c, r_and_c), isBitMatrix(true)
    {
    }
    Relation_matrix() : _Matrix(), isBitMatrix(true) {}
    template <typename T>
    Relation_matrix(set<T>& s, RelationSet<T>& r) : _Matrix(s.size(), s.size()), isBitMatrix(true)
    {
        for (auto it = r.begin(); it != r.end(); ++it)
        {
            if (s.find(it->first) == s.end() || s.find(it->second) == s.end())
                throw "The relation is not defined on the set";
        }
        map<T, int> m;
        int i = 0;
        for (auto it = s.begin(); it != s.end(); ++it)
        {
            m.emplace(*it, i);
            ++i;
        }
        for (auto it = r.begin(); it != r.end(); ++it)
        {
            v.at(m.find(it->first)->second).at(m.find(it->second)->second) = 1;
        }
    }
    bool scanf_initalize() override
    {
        int temp;
        for (int i = 0; i < rows; ++i)
        {
            vector<int> vv;
            for (int j = 0; j < cols; ++j)
            {
                scanf("%d", &temp);
                if (temp != 0 || temp != 1)
                {
                    isBitMatrix = false;
                }
                vv.push_back(temp);
            }
            v.at(i) = vv;
        }
        return true;
    }
    bool add(int num, ...) override
    {
        if (cols == 0)
        {
            cols = num;
        }
        else if (num != cols)
        {
            throw "The matrix needs to be a rectangle";
        }
        vector<int> vv(num);
        va_list ptr;
        int temp;
        va_start(ptr, num);
        for (int i = 0; i < num; ++i)
        {
            temp = va_arg(ptr, int);
            if (temp != 1 && temp != 0)
                isBitMatrix = false;
            vv.at(i) = temp;
        }
        va_end(ptr);
        v.push_back(vv);
        ++rows;
        return true;
    }
    bool set_matrix_element(int row, int cols, int val) override
    {
        if (row <= rows && row >= 0 && cols <= this->rows && cols >= 0 && (val == 1 || val == 0))
        {
            v.at(row - 1).at(cols - 1) = val;
            return true;
        }
        return false;
    }
    Relation_matrix& operator|=(const Relation_matrix& d)
    {
        this->throw_exception();
        d.throw_exception();
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < d.cols; ++j)
            {
                if (v.at(i).at(j) | d.v.at(i).at(j))
                {
                    v.at(i).at(j) = 1;
                }
                else
                {
                    v.at(i).at(j) = 0;
                }
            }
        }
        return *this;
    }
    friend Relation_matrix operator|(Relation_matrix a, Relation_matrix b)
    {
        a |= b;
        return a;
    }
    bool is_reflexive() const
    {
        throw_exception();
        for (int i = 0; i < rows; ++i)
        {
            if (v.at(i).at(i) == 0)
                return false;
        }
        return true;
    }
    bool is_anti_reflexive() const
    {
        throw_exception();
        for (int i = 0; i < rows; ++i)
        {
            if (v.at(i).at(i) == 1)
                return false;
        }
        return true;
    }
    bool is_symmetric() const
    {
        throw_exception();
        for (int i = 0; i < rows - 1; ++i)
        {
            for (int j = i + 1; j < cols; ++j)
            {
                if (v.at(i).at(j) != v.at(j).at(i))
                {
                    return false;
                }
            }
        }
        return true;
    }
    bool is_anti_symmetric() const
    {
        throw_exception();
        for (int i = 0; i < rows - 1; ++i)
        {
            for (int j = i + 1; j < cols; ++j)
            {
                if (v.at(i).at(j) == 1 && v.at(j).at(i) == 1)
                {
                    return false;
                }
            }
        }
        return true;
    }
    bool is_transmit() const
    {
        throw_exception();
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                for (int k = 0; k < cols; ++k)
                {
                    if (v.at(i).at(j) == 1 && v.at(j).at(k) == 1 && v.at(i).at(k) != 1)
                    {
                        return false;
                    }
                }
            }
        }
        return true;
    }
    bool is_equal() const
    {
        return is_reflexive() && is_symmetric() && is_transmit();
    }
    template <typename T>
    static set<set<T>> make_equal_class(set<T>& s, RelationSet<T>& r)
    {
        Relation_matrix temp_m(s, r);
        set<T> temp_ele; set<set<T>>val_;
        set<T>v;
        if (temp_m.is_equal())
        {
            for (auto it = s.begin(); it != s.end(); ++it) {
                if (v.find(*it) != v.end())continue;
                temp_ele.insert(*it);
                seach(*it, r, temp_ele);
                val_.insert(temp_ele);
                temp_ele.clear();
            }
        }
        return val_;
    }
    Relation_matrix reflexive_closure() const
    {
        throw_exception();
        if (this->is_reflexive())
        {
            return *this;
        }
        Relation_matrix temp(*this);
        for (int i = 0; i < rows; ++i)
        {
            temp.v.at(i).at(i) = 1;
        }
        return temp;
    }
    Relation_matrix symmetric_closure() const
    {
        throw_exception();
        if (this->is_symmetric())
        {
            return *this;
        }
        Relation_matrix temp(*this);
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                if (i != j && v.at(i).at(j) == 1 && v.at(j).at(i) == 0)
                {
                    temp.v.at(j).at(i) = 1;
                }
            }
        }
        return temp;
    }
    Relation_matrix transmit_closure() const
    {
        throw_exception();
        if (this->is_transmit())
        {
            return *this;
        }
        Relation_matrix temp(*this);
        Relation_matrix temp3(*this);
        for (int i = 0; i < rows - 1; ++i)
        {
            temp *= *this;
            temp3 |= temp;
        }
        return temp3;
    }
    Relation_matrix warshall() const
    {
        throw_exception();
        if (this->is_transmit())
        {
            return *this;
        }
        Relation_matrix temp(*this);
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                if (temp.v.at(j).at(i) == 1)
                {
                    for (int k = 0; k < rows; ++k)
                    {
                        if (temp.v.at(j).at(k) + temp.v.at(i).at(k))
                            temp.v.at(j).at(k) = 1;
                        else
                            temp.v.at(j).at(k) = 0;
                    }
                }
            }
        }
        return temp;
    }
    template <typename T>
    RelationSet<T> make_RelationSet(set<T>& s) const
    {
        RelationSet<T> r;
        map<T, int> m;
        int i = 0;
        for (auto it = s.begin(); it != s.end(); ++it)
        {
            m.emplace(i, *it);
            ++i;
        }
        for (int i = 0; i < this->rows; ++i)
        {
            for (int j = 0; j < this->rows; ++j)
            {
                if (v.at(i).at(j) == 1)
                {
                    r.emplace(m.find(i)->second, m.find(j)->second);
                }
            }
        }
        return r;
    }
};

分装的不好,应付一下离散数学还是可以的。(有些bug,懒得改了,重在能跑)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值