Sparse Matrix (Orthogonal Linked List)
October 13, 2018
简单实现了稀疏矩阵的加法减法乘法和转置
Crosslist.h
#include <iostream> using namespace std; #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define LOVERFLOW -2 //避免与<math.h>中的定义冲突 typedef int Status; typedef int ElemType; class CrossList; //类的提前声明 class OLNode { protected: int i, j; ElemType e; OLNode *right, *down; public: friend istream& operator >> (istream &in, OLNode &n); //输入一个OLNode型对象 friend ostream& operator << (ostream &out, const OLNode &n); //输出一个OLNode型对象 friend class CrossList; //友元 friend istream& operator >> (istream &in, CrossList &m); //取代CreateSMatrix功能,以三元组表的形式输入一个稀疏矩阵 friend ostream& operator << (ostream &out, const CrossList &m); //取代PrintSMatrix,以矩阵形式输出 }; class CrossList { protected: OLNode **rhead, **chead; int mu, nu, tu; public: /* 构造和析构函数 */ CrossList(); //增加的构造函数,对TSMatrix类的对象进行初始化 CrossList(const CrossList &m); //增加的复制构造函数,完成TSMatrix类的对象的复制(三种调用时机) ~CrossList(); //取代DestroySMatrix /* cin/cout的重载 */ friend istream& operator >> (istream &in, CrossList &m); //取代CreateSMatrix功能,以三元组表的形式输入一个稀疏矩阵 friend ostream& operator << (ostream &out, const CrossList &m); //取代PrintSMatrix,以矩阵形式输出 /* 成员函数形式的运算符重载 */ CrossList& operator=(const CrossList m); //取代CopySMatrix,T=M表示把M矩阵复制到T中 CrossList operator+(const CrossList &m); //和=重载一起,取代AddSMatrix, Q=M+N 表示求稀疏矩阵M+N的和 CrossList operator-(const CrossList &m); //和=重载一起,取代SubSMatrix, Q=M-N 表示求稀疏矩阵M-N的差 CrossList operator*(const CrossList &m); //和=重载一起,取代MultSMatrix,Q=M*N 表示求稀疏矩阵M*N的乘积 CrossList operator!(); //和=重载一起,取代TranspostSMatrix,!M 表示求M的转置矩阵 };
Crosslist.cpp
#include <iostream> #include <stdlib.h> #include <algorithm> #include <math.h> #include <string.h> #include "Crosslist.h" using namespace std; istream &operator>>(istream &in, OLNode &n) { return in; } ostream &operator<<(ostream &out, const OLNode &n) { return out; } istream &operator>>(istream &in, CrossList &m) { int i, j, k, mu, nu, tu; ElemType e; OLNode *p, *q; in >> mu >> nu >> tu; m.mu = mu; m.nu = nu; m.tu = tu; m.rhead = (OLNode**)malloc((mu + 1) * sizeof(OLNode*)); m.chead = (OLNode**)malloc((nu + 1) * sizeof(OLNode*)); for (k = 1; k <= mu; k++) m.rhead[k] = NULL; for (k = 1; k <= nu; k++) m.chead[k] = NULL; for (k = 0; k < tu; k++) { in >> i >> j >> e; i++; j++; p = (OLNode*)malloc(sizeof(OLNode)); p->i = i; p->j = j; p->e = e; if (m.rhead[i] == NULL || m.rhead[i]->j > j) { p->right = m.rhead[i]; m.rhead[i] = p; } else { for (q = m.rhead[i]; q->right&&q->right->j < j; q = q->right); p->right = q->right; q->right = p; } if (m.chead[j] == NULL || m.chead[j]->i > i) { p->down = m.chead[j]; m.chead[j] = p; } else { for (q = m.chead[j]; q->down&&q->down->i < i; q = q->down); p->down = q->down; q->down = p; } } return in; } ostream &operator<<(ostream &out, const CrossList &m) { int i, j, tot = 1; OLNode *p; int row[10001], col[10001], num[10001]; for (j = 1; j <= m.mu; j++) { p = m.rhead[j]; while (p) { row[tot] = p->i; col[tot] = p->j; num[tot] = p->e; p = p->right; tot++; } } for (i = 1; i <= m.mu; i++) { for (j = 1; j <= m.nu; j++) { bool flag = 0; for (int k = 1; k <= m.tu; k++) if (i == row[k] && j == col[k]) { out << num[k] << " "; flag = 1; break; } if (flag == 0) out << 0 << " "; } out << endl; } return out; } CrossList::CrossList() { rhead = chead = NULL; mu = nu = tu = 0; } CrossList::CrossList(const CrossList &m) { int i; OLNode *p, *q = NULL, *q1 = NULL, *q2; mu = m.mu; nu = m.nu; tu = m.tu; rhead = (OLNode**)malloc((m.mu + 1) * sizeof(OLNode*)); chead = (OLNode**)malloc((m.nu + 1) * sizeof(OLNode*)); for (i = 1; i <= m.mu; i++) rhead[i] = NULL; for (i = 1; i <= m.nu; i++) chead[i] = NULL; for (i = 1; i <= m.mu; i++) { p = m.rhead[i]; while (p) { q = (OLNode*)malloc(sizeof(OLNode)); q->i = p->i; q->j = p->j; q->e = p->e; if (!rhead[i]) rhead[i] = q1 = q; else q1 = q1->right = q; if (!chead[q->j]) { chead[q->j] = q; q->down = NULL; } else { q2 = chead[q->j]; while (q2->down) q2 = q2->down; q2->down = q; q->down = NULL; } p = p->right; } if (q) q->right = NULL; } } CrossList::~CrossList() { int i; OLNode *p, *q; for (i = 1; i <= mu; i++) { p = *(rhead + i); while (p) { q = p; p = p->right; free(q); } } free(rhead); free(chead); rhead = chead = NULL; mu = nu = tu = 0; } CrossList &CrossList::operator=(const CrossList m) { int i; OLNode *p, *q = NULL, *q1 = NULL, *q2; if (rhead) { for (i = 1; i <= mu; i++) { p = *(rhead + i); while (p) { q = p; p = p->right; free(q); } } } mu = m.mu; nu = m.nu; tu = m.tu; rhead = (OLNode**)malloc((m.mu + 1) * sizeof(OLNode*)); chead = (OLNode**)malloc((m.nu + 1) * sizeof(OLNode*)); for (i = 1; i <= m.mu; i++) rhead[i] = NULL; for (i = 1; i <= m.nu; i++) chead[i] = NULL; for (i = 1; i <= m.mu; i++) { p = m.rhead[i]; while (p) { q = (OLNode*)malloc(sizeof(OLNode)); q->i = p->i; q->j = p->j; q->e = p->e; if (!rhead[i]) rhead[i] = q1 = q; else q1 = q1->right = q; if (!chead[q->j]) { chead[q->j] = q; q->down = NULL; } else { q2 = chead[q->j]; while (q2->down) q2 = q2->down; q2->down = q; q->down = NULL; } p = p->right; } if (q) q->right = NULL; } return *this; } CrossList CrossList::operator+(const CrossList &m) { int i, k; OLNode *p, *pq = NULL, *pm, *pn; OLNode **col = NULL; CrossList Q; Q.mu = mu; Q.nu = nu; Q.tu = 0; Q.rhead = (OLNode**)malloc((Q.mu + 1) * sizeof(OLNode*)); Q.chead = (OLNode**)malloc((Q.nu + 1) * sizeof(OLNode*)); for (k = 1; k <= Q.mu; k++) Q.rhead[k] = NULL; for (k = 1; k <= Q.nu; k++) Q.chead[k] = NULL; col = (OLNode**)malloc((Q.nu + 1) * sizeof(OLNode*)); for (k = 1; k <= Q.nu; k++) col[k] = NULL; for (i = 1; i <= mu; i++) { pm = rhead[i]; pn = m.rhead[i]; while (pm&&pn) { if (pm->j < pn->j) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pm->j; p->e = pm->e; p->right = NULL; pm = pm->right; } else if (pm->j > pn->j) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pn->j; p->e = pn->e; p->right = NULL; pn = pn->right; } else if (pm->e + pn->e) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pn->j; p->e = pm->e + pn->e; p->right = NULL; pm = pm->right; pn = pn->right; } else { pm = pm->right; pn = pn->right; continue; } if (Q.rhead[i] == NULL) Q.rhead[i] = pq = p; else { pq->right = p; pq = pq->right; } if (Q.chead[p->j] == NULL) Q.chead[p->j] = col[p->j] = p; else { col[p->j]->down = p; col[p->j] = col[p->j]->down; } } while (pm) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pm->j; p->e = pm->e; p->right = NULL; pm = pm->right; if (Q.rhead[i] == NULL) Q.rhead[i] = pq = p; else { pq->right = p; pq = pq->right; } if (Q.chead[p->j] == NULL) Q.chead[p->j] = col[p->j] = p; else { col[p->j]->down = p; col[p->j] = col[p->j]->down; } } while (pn) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pn->j; p->e = pn->e; p->right = NULL; pn = pn->right; if (Q.rhead[i] == NULL) Q.rhead[i] = pq = p; else { pq->right = p; pq = pq->right; } if (Q.chead[p->j] == NULL) Q.chead[p->j] = col[p->j] = p; else { col[p->j]->down = p; col[p->j] = col[p->j]->down; } } } for (k = 1; k <= Q.nu; k++) if (col[k]) col[k]->down = NULL; free(col); return Q; } CrossList CrossList::operator-(const CrossList &m) { int i, k; OLNode *p, *pq = NULL, *pm, *pn; OLNode **col = NULL; CrossList Q; Q.mu = mu; Q.nu = nu; Q.tu = 0; Q.rhead = (OLNode**)malloc((Q.mu + 1) * sizeof(OLNode*)); Q.chead = (OLNode**)malloc((Q.nu + 1) * sizeof(OLNode*)); for (k = 1; k <= Q.mu; k++) Q.rhead[k] = NULL; for (k = 1; k <= Q.nu; k++) Q.chead[k] = NULL; col = (OLNode**)malloc((Q.nu + 1) * sizeof(OLNode*)); for (k = 1; k <= Q.nu; k++) col[k] = NULL; for (i = 1; i <= mu; i++) { pm = rhead[i]; pn = m.rhead[i]; while (pm&&pn) { if (pm->j<pn->j) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pm->j; p->e = pm->e; p->right = NULL; pm = pm->right; } else if (pm->j>pn->j) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pn->j; p->e = -pn->e; p->right = NULL; pn = pn->right; } else if (pm->e - pn->e) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pn->j; p->e = pm->e - pn->e; p->right = NULL; pm = pm->right; pn = pn->right; } else { pm = pm->right; pn = pn->right; continue; } if (Q.rhead[i] == NULL) Q.rhead[i] = pq = p; else { pq->right = p; pq = pq->right; } if (Q.chead[p->j] == NULL) Q.chead[p->j] = col[p->j] = p; else { col[p->j]->down = p; col[p->j] = col[p->j]->down; } } while (pm) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pm->j; p->e = pm->e; p->right = NULL; pm = pm->right; if (Q.rhead[i] == NULL) Q.rhead[i] = pq = p; else { pq->right = p; pq = pq->right; } if (Q.chead[p->j] == NULL) Q.chead[p->j] = col[p->j] = p; else { col[p->j]->down = p; col[p->j] = col[p->j]->down; } } while (pn) { p = (OLNode*)malloc(sizeof(OLNode)); Q.tu++; p->i = i; p->j = pn->j; p->e = -pn->e; p->right = NULL; pn = pn->right; if (Q.rhead[i] == NULL) Q.rhead[i] = pq = p; else { pq->right = p; pq = pq->right; } if (Q.chead[p->j] == NULL) Q.chead[p->j] = col[p->j] = p; else { col[p->j]->down = p; col[p->j] = col[p->j]->down; } } } for (k = 1; k <= Q.nu; k++) if (col[k]) col[k]->down = NULL; free(col); return Q; } CrossList CrossList::operator*(const CrossList &m) { int i, j, e; OLNode *q, *p0, *q0, *q1=NULL, *q2; CrossList Q; Q.mu = mu; Q.nu = m.nu; Q.tu = 0; Q.rhead = (OLNode**)malloc((Q.mu + 1) * sizeof(OLNode*)); Q.chead = (OLNode**)malloc((Q.nu + 1) * sizeof(OLNode*)); for (i = 1; i <= Q.mu; i++) Q.rhead[i] = NULL; for (i = 1; i <= Q.nu; i++) Q.chead[i] = NULL; for (i = 1; i <= Q.mu; i++) for (j = 1; j <= Q.nu; j++) { p0 = rhead[i]; q0 = m.chead[j]; e = 0; while (p0&&q0) { if (q0->i<p0->j) q0 = q0->down; else if (q0->i>p0->j) p0 = p0->right; else { e += p0->e*q0->e; q0 = q0->down; p0 = p0->right; } } if (e) { Q.tu++; q = (OLNode*)malloc(sizeof(OLNode)); q->i = i; q->j = j; q->e = e; q->right = NULL; q->down = NULL; if (!Q.rhead[i]) Q.rhead[i] = q1 = q; else q1 = q1->right = q; if (!Q.chead[j]) Q.chead[j] = q; else { q2 = Q.chead[j]; while (q2->down) q2 = q2->down; q2->down = q; } } } return Q; } CrossList CrossList::operator!() { int u, i; OLNode **head, *p, *q, *r; CrossList T = *this; u = mu; mu = nu; nu = u; head = rhead; rhead = chead; chead = head; for (u = 1; u <= mu; u++) { p = rhead[u]; while (p) { q = p->down; i = p->i; p->i = p->j; p->j = i; r = p->down; p->down = p->right; p->right = r; p = q; } } return T; }