#ifndef CROSSMATRIX_H_
#define CROSSMATRIX_H_
#define FLOWOVER -1
struct SCMNode;//节点
typedef int elemType;//数据域数据类型
typedef struct SCMNode * CMNode;//指向节点的指针
/**************结构体声明与定义**************/
struct SCMNode{
<span style="white-space:pre"> </span>int row;//节点行号
<span style="white-space:pre"> </span>int col;//节点列号
<span style="white-space:pre"> </span>elemType elem;//节点的数值
<span style="white-space:pre"> </span>struct SCMNode * right;//指向节点右侧的下个非零元,若没有则为NULL
<span style="white-space:pre"> </span>struct SCMNode * down;//指向节点下方的下个非零元,若没有则为NULL
};
typedef struct{
<span style="white-space:pre"> </span>CMNode *rowhead;//指针数组,rowhead[1],存的是矩阵第1行第一个节点的地址,若为空行,值为NULL
<span style="white-space:pre"> </span>CMNode *colhead;//指针数组,colhead[1],存的是矩阵第1列第一个节点的地址,若为空列,值为NULL
<span style="white-space:pre"> </span>int numOfRow;//表示矩阵的总行数
<span style="white-space:pre"> </span>int numOfCol;//表示矩阵的总列数
<span style="white-space:pre"> </span>int numOfElem;//表示矩阵的非零元总数
}CrossMatrix;//表头,不是指针,代表十字矩阵本身
/**************方法声明**************/
//创建一个新节点,为后续一些方法的辅助函数
void NewNdoe(CMNode &N, int r, int c, elemType e);
//输入行列数,创建一个空稀疏矩阵
void CreatMatrix(CrossMatrix &CM, int nR, int nC);
//构建并赋值,初始化一个新稀疏矩阵
void InitMatrix(CrossMatrix &CM, int nR, int nC, int nE);
//清空稀疏矩阵
void ClearMatrix(CrossMatrix &CM);
//输出稀疏矩阵
void PrintMatrix(CrossMatrix &CM);
//在输入指针指向的节点左方增加一个新节点,为下面几个运算的辅助函数
void AddNode(CrossMatrix &A, CMNode newN, int r, int c, elemType e);
//删除指定矩阵的指定节点,为下面几个运算的辅助函数
void DeleteNode(CrossMatrix &A, CMNode rowOfA);
//M、N行列数相同,将矩阵M、N相加赋值给M,M = M + N
void AddMatrix(CrossMatrix &M, CrossMatrix N);
//M、N行列数相同,将矩阵M、N相减赋值给M,M = M - N
void SubMatrix(CrossMatrix &M, CrossMatrix N);
//M行数等于N列数,M列数等于N行数,将矩阵M、N相乘赋值给Q,Q = M * N
void MultMatrix(CrossMatrix &Q, CrossMatrix M, CrossMatrix N);
//M转置得到T
void TransposeMatrix(CrossMatrix &T, CrossMatrix M);
#endif
#include "CrossMatrix.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#pragma warning(disable:4996)
void NewNdoe(CMNode &N, int r, int c, elemType e)
{
N = (CMNode)malloc(sizeof(struct SCMNode));
if (N == NULL)
exit(FLOWOVER);
N->row = r;
N->col = c;
N->elem = e;
N->right = NULL;
N->down = NULL;
}
void CreatMatrix(CrossMatrix &CM, int nR, int nC)
{//若输入的结构体不是空结构体,如何判定
CM.numOfRow = nR;
CM.numOfCol = nC;
CM.numOfElem = 0;
CM.rowhead = (CMNode *)malloc(sizeof(CMNode) * (nR + 1));
if (CM.rowhead == NULL)
exit(FLOWOVER);
CM.colhead = (CMNode *)malloc(sizeof(CMNode) * (nC + 1));
if (CM.colhead == NULL)
exit(FLOWOVER);
//头结点初始化,CM.rowhead[0]废弃不用,将头结点也分配空间是为了统一所有节点的插入操作
for (int i = 1; i <= nR; i++){
CM.rowhead[i]= NULL;
}
for (int i = 1; i <= nC; i++){
CM.colhead[i] = NULL;
}
}
void InitMatrix(CrossMatrix &CM, int nR, int nC, int nE)
{//若输入的结构体不是空结构体,如何判定
CM.numOfRow = nR;
CM.numOfCol = nC;
CM.numOfElem = nE;
CM.rowhead = (CMNode *)malloc(sizeof(CMNode) * (nR + 1));
if (CM.rowhead == NULL)
exit(FLOWOVER);
CM.colhead = (CMNode *)malloc(sizeof(CMNode) * (nC + 1));
if (CM.colhead == NULL)
exit(FLOWOVER);
//头结点初始化,CM.rowhead[0]废弃不用
for (int i = 1; i <= nR; i++){
CM.rowhead[i] = NULL;
}
for (int i = 1; i <= nC; i++){
CM.colhead[i] = NULL;
}
printf("分别输入%d个由行、列、数值构成的三元组:", nE);
for (int i = 1; i <= nE; i++){
CMNode Node = NULL;
int r, c, e;//这里的e如何控制输入为double等其他类型时正常运行
scanf("%d%d%d", &r, &c, &e);
NewNdoe(Node, r, c, e);
//行插入
if (CM.rowhead[r] == NULL || CM.rowhead[r]->col > Node->col){
Node->right = CM.rowhead[r];
CM.rowhead[r] = Node;
}
else{
CMNode tempNode = CM.rowhead[r];//循环结束后存的是插入节点的后继
CMNode frontOfTempNode = NULL;//循环结束后存的是插入节点的前驱
while (tempNode != NULL && tempNode->col < Node->col){
frontOfTempNode = tempNode;
tempNode = tempNode->right;
}
frontOfTempNode->right = Node;
Node->right = tempNode;
}
//列插入
if (CM.colhead[c] == NULL || CM.colhead[c]->row > Node->row){
Node->down = CM.colhead[c];
CM.colhead[c] = Node;
}
else{
CMNode tempNode = CM.colhead[c];
CMNode frontOfTempNode = NULL;
while (tempNode != NULL && tempNode->row < Node->row){
frontOfTempNode = tempNode;
tempNode = tempNode->down;
}
frontOfTempNode->down = Node;
Node->down= tempNode;
}
}
}
void ClearMatrix(CrossMatrix &CM)
{
CMNode tempNode;
for (int i = 1; i <= CM.numOfRow; i++){
while (CM.rowhead[i] != NULL){
tempNode = CM.rowhead[i];
CM.rowhead[i] = CM.rowhead[i]->right;
free(tempNode);
}
}
free(CM.rowhead);
free(CM.colhead);
CM.numOfRow = 0;
CM.numOfCol = 0;
CM.numOfElem = 0;
CM.rowhead = NULL;
CM.colhead = NULL;
}
void PrintMatrix(CrossMatrix &CM)
{
CMNode tempNode = NULL;
for (int i = 1; i <= CM.numOfRow; i++){
tempNode = CM.rowhead[i];
for (int j = 1; j <= CM.numOfCol; j++){
if (tempNode != NULL && tempNode->col == j){
printf("%d ", tempNode->elem);
tempNode = tempNode->right;
}
else{
printf("%d ", 0);
}
}
printf("\n");
}
}
void AddNode(CrossMatrix &A, CMNode newN, int r, int c, elemType e)
{//rearOfRow是新节点的行后继
CMNode frontOfRow = NULL;//最终存储新节点的行前驱
CMNode rearOfRow = NULL;//最终存储新节点的行后继
CMNode frontOfCol = NULL;//最终存储新节点的列前驱
CMNode rearOfCol = NULL;//最终存储新节点的列后继
NewNdoe(newN, r, c, e);
//行插入
if (A.rowhead[r] == NULL){//这个和下面的else if能不能合并?
newN->right = A.rowhead[r];
A.rowhead[r] = newN;
A.numOfElem++;
}
else if (A.rowhead[r]->col > newN->col){
newN->right = A.rowhead[r];
A.rowhead[r] = newN;
A.numOfElem++;
}
else{
frontOfRow = A.rowhead[r];
rearOfRow = A.rowhead[r];
while (rearOfRow != NULL && rearOfRow->col < newN->col){
rearOfRow = rearOfRow->right;
}
while (frontOfRow->right != rearOfRow){
frontOfRow = frontOfRow->right;
}
newN->right = rearOfRow;
frontOfRow->right = newN;
A.numOfElem++;
}
//列插入
if (A.colhead[c] == NULL){//这个和下面的else if能不能合并?
newN->down = A.colhead[c];
A.colhead[c] = newN;
}
else if (A.colhead[c]->row > newN->row){
newN->down = A.colhead[c];
A.colhead[c] = newN;
}
else{
frontOfCol = A.colhead[c];
rearOfCol = A.colhead[c];
while (rearOfCol != NULL && rearOfCol->row < newN->row){
rearOfCol = rearOfCol->down;
}
while (frontOfCol->down != rearOfCol){
frontOfCol = frontOfCol->down;
}
newN->down = rearOfCol;
frontOfCol->down = newN;
}
}
void DeleteNode(CrossMatrix &A, CMNode rowOfA)
{//rowOfA为被删除节点地址
CMNode rearOfRow = rowOfA->right;//被删除节点的行后继
CMNode frontOfRow = A.rowhead[rowOfA->row];//被删除节点的行前驱
CMNode rearOfCol = rowOfA->down;//被删除节点的列后继
CMNode frontOfCol = A.colhead[rowOfA->col];//被删除节点的列前驱
//行删除
if (frontOfRow == rowOfA){//删除的节点为行第一个节点
A.rowhead[rowOfA->row] = rearOfRow;
}
else{//删除的节点不是行第一个节点
while (frontOfRow->right != rowOfA){
frontOfRow = frontOfRow->right;
}
frontOfRow->right = rearOfRow;
}
//列删除
if (frontOfCol == rowOfA){//删除的节点为列第一个节点
A.colhead[rowOfA->col] = rearOfCol;
}
else{//删除的节点不是列第一个节点
while (frontOfCol->down != rowOfA){
frontOfCol = frontOfCol->down;
}
frontOfCol->down = rearOfCol;
}
free(rowOfA);
A.numOfElem--;
}
void AddMatrix(CrossMatrix &M, CrossMatrix N)
{
CMNode rowOfM;//指向M从行看的某个节点的指针
CMNode rowOfN;//指向N从行看的某个节点的指针
for (int i = 1; i <= M.numOfRow; i++){
rowOfM = M.rowhead[i];
rowOfN = N.rowhead[i];
if (rowOfN == NULL)
continue;
if (rowOfM == NULL){
while (rowOfN != NULL){
CMNode tempNode = NULL;
rowOfM = M.rowhead[i];
AddNode(M, tempNode, rowOfN->row, rowOfN->col, rowOfN->elem);
rowOfM = rowOfM->right;
rowOfN = rowOfN->right;
}
}
else{
while (rowOfM != NULL && rowOfN != NULL){
if (rowOfM->col > rowOfN->col){
CMNode tempNode = NULL;
CMNode rearOfNewNode = M.rowhead[i];//rowOfM的行后继
while (rearOfNewNode != rowOfM->right){
rearOfNewNode = rearOfNewNode->right;
}
AddNode(M, tempNode, rowOfN->row, rowOfN->col, rowOfN->elem);
rowOfN = rowOfN->right;
}
else if (rowOfM->col < rowOfN->col){
rowOfM = rowOfM->right;
}
else if (rowOfM->col == rowOfN->col && rowOfM->elem + rowOfN->elem != 0){
rowOfM->elem = rowOfM->elem + rowOfN->elem;
rowOfM = rowOfM->right;
rowOfN = rowOfN->right;
}
else{
CMNode tempNodeM = rowOfM->right;
DeleteNode(M, rowOfM);
rowOfM = tempNodeM;
rowOfN = rowOfN->right;
}
}
}
}
}
void SubMatrix(CrossMatrix &M, CrossMatrix N)
{
CMNode rowOfM;//指向M从行看的某个节点的指针
CMNode rowOfN;//指向N从行看的某个节点的指针
for (int i = 1; i <= M.numOfRow; i++){
rowOfM = M.rowhead[i];
rowOfN = N.rowhead[i];
if (rowOfN == NULL)
continue;
if (rowOfM == NULL){
while (rowOfN != NULL){
CMNode tempNode = NULL;
rowOfN = M.rowhead[i];
AddNode(M, tempNode, rowOfN->row, rowOfN->col, -rowOfN->elem);
rowOfM = rowOfM->right;
rowOfN = rowOfN->right;
}
}
else{
while (rowOfM != NULL && rowOfN != NULL){
if (rowOfM->col > rowOfN->col){
CMNode tempNode = NULL;
CMNode rearOfNewNode = M.rowhead[i];//rowOfM的行后继
while (rearOfNewNode != rowOfM->right){
rearOfNewNode = rearOfNewNode->right;
}
AddNode(M, tempNode, rowOfN->row, rowOfN->col, -rowOfN->elem);
rowOfN = rowOfN->right;
}
else if (rowOfM->col < rowOfN->col){
rowOfM = rowOfM->right;
}
else if (rowOfM->col == rowOfN->col && rowOfM->elem - rowOfN->elem != 0){
rowOfM->elem = rowOfM->elem - rowOfN->elem;
rowOfM = rowOfM->right;
rowOfN = rowOfN->right;
}
else{
CMNode tempNodeM = rowOfM->right;
DeleteNode(M, rowOfM);
rowOfM = tempNodeM;
rowOfN = rowOfN->right;
}
}
}
}
}
void MultMatrix(CrossMatrix &Q, CrossMatrix M, CrossMatrix N)
{
CMNode rowOfM;//指向M从行看的某个节点的指针
CMNode colOfN;//指向N从列看的某个节点的指针
CreatMatrix(Q, M.numOfRow, N.numOfCol);
for (int i = 1; i <= M.numOfRow; i++){
rowOfM = M.rowhead[i];
if (rowOfM == NULL)
continue;
for (int j = 1; j <= N.numOfCol; j++){
rowOfM = M.rowhead[i];//轮完一轮重置
colOfN = N.colhead[j];
if (colOfN == NULL)
break;
int tempSum = 0;
while (rowOfM != NULL && colOfN != NULL){
if (rowOfM->col > colOfN->row){
colOfN = colOfN->down;
}
else if (rowOfM->col < colOfN->row){
rowOfM = rowOfM->right;
}
else{
tempSum += rowOfM->elem * colOfN->elem;
rowOfM = rowOfM->right;
colOfN = colOfN->down;
}
}
if (tempSum != 0){
CMNode tempNode = NULL;
AddNode(Q, tempNode, i, j, tempSum);
}
}
}
}
void TransposeMatrix(CrossMatrix &T, CrossMatrix M)
{
CMNode tempOfRow;
CreatMatrix(T, M.numOfCol, M.numOfRow);
for (int i = 1; i <= M.numOfRow; i++){
tempOfRow = M.rowhead[i];
while (tempOfRow != NULL){
AddNode(T, tempOfRow, tempOfRow->col, tempOfRow->row, tempOfRow->elem);
tempOfRow = tempOfRow->right;
}
}
}
#include "CrossMatrix.h"
#include <stdio.h>
#include <stdlib.h>
int main()
{
CrossMatrix testM;
CrossMatrix testN;
CrossMatrix testQ;
/*初始化测试*/
//InitMatrix(testM, 3, 4, 4);//1 1 2 2 2 1 3 3 3 1 4 1
//PrintMatrix(testM);
//InitMatrix(testN, 3, 4, 4);//3 1 1 2 2 2 1 3 1 3 3 -3
//PrintMatrix(testN);
/*加法测试*/
//AddMatrix(testM, testN);
//PrintMatrix(testM);
/*减法测试*/
//SubMatrix(testM, testN);
//PrintMatrix(testM);
/*乘法测试*/
//InitMatrix(testM, 3, 4, 4); //1 1 2 2 2 1 3 3 3 1 4 1
//PrintMatrix(testM);
//InitMatrix(testN, 4, 3, 4); //3 1 1 2 2 2 3 3 -3 1 3 1
//PrintMatrix(testN);
//MultMatrix(testQ, testM, testN);
//PrintMatrix(testQ);
//转置测试
InitMatrix(testM, 3, 4, 4);//1 1 2 2 2 1 3 3 3 1 4 1
PrintMatrix(testM);
TransposeMatrix(testQ, testM);
PrintMatrix(testQ);
system("pause");
}