十字链表实现矩阵

本文详细介绍了如何利用十字链表来高效地实现矩阵的各种操作,如增删元素、矩阵相加和乘法等。通过十字链表的特殊结构,可以方便地进行行列遍历,提高数据访问速度。
摘要由CSDN通过智能技术生成
#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");
}



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值