稀疏矩阵十字链表类java_数据结构之---C/C++实现稀疏矩阵的十字链表

本文介绍了如何使用C/C++实现稀疏矩阵的十字链表存储结构,包括创建和打印十字链表的方法。十字链表允许高效地存储和操作稀疏矩阵的非零元素。
摘要由CSDN通过智能技术生成

标签:

首先这里介绍什么是矩阵的十字链表,大家可以理解稀疏矩阵是顺序存储的,那么这个就是链式存储的。

如图:

存储该矩阵

072afad7db6cd37f381550aea5de8fe1.png

那么应该是如下的格式:

b810539be08963fcb8715f311fffad6f.png

ab19b4b8000ed8d86b28254abf21abe1.png

我们知道稀疏矩阵的三元组存储方式的实现很简单,每个元素有三个域分别是col,row, e。代表了该非零元的行号、列号以及值。那么在十字链表的存储方式下,首先这三个域是肯定少不了的,不然在进行很多操作的时候都要自己使用计数器,很麻烦。而十字链表的形式大家可以理解成每一行是一个链表,而每一列又是一个链表

通过上面的图我们可以知道,每个结点不止要存放row, col, e。还要存放它横向的下一个结点的地址以及纵向的下一个结点的地址。形成一个类似十字形的链表的结构。

注意Rhead与Chead的类型,它们是指向指针的指针,也就是说,它们是指向我们定义的OLNode结构的结点的指针的指针。

两个版本C语言:

//稀疏矩阵的十字链表存储表示

//杨鑫

#include

#include

typedef int ELemType;

typedef struct OLNode

{

ELemType e;

int i, j;

struct OLNode *right, *down;

}OLNode, *OLink;

typedef struct

{

OLink *rhead, *chead;

int mu, nu, tu;

}CrossList;

int create_SMatrix(CrossList *M)

{

int i, j, m, n, t;

int k, flag;

ELemType e;

OLNode *p, *q;

if(M->rhead)

{

do

{

flag = 1;

printf("输入要创建矩阵的行数,列数,以及非零元素的个数:\n");

scanf("%d%d%d", &m, &n, &t);

if(m < 0 || n < 0 || t < 0 || t > m * n)

flag = 0;

}while(!flag);

M->mu = m;

M->nu = n;

M->tu = t;

M->rhead = (OLink *)malloc((m + 1) * sizeof(OLink));

if(!M->rhead)

exit(-1);

M->chead = (OLink *)malloc((n + 1) * sizeof(OLink));

if(!(M->chead))

exit(-1);

for(k = 1; k <= m; k++)

M->rhead[k] = NULL;

for(k = 1; k <= n; k++)

M->chead[k] = NULL;

for (k=1; k<=t; ++k)

{

do {

flag = 1;

printf("输入第%d个结点行号、列号以及值:\n", k);

scanf("%d%d%d", &i, &j, &e);

if (i<=0 || j<=0)

flag = 0;

}while (!flag);

p = (OLink) malloc (sizeof(OLNode));

if (NULL == p)

exit(-1);

p->i = i;

p->j = j;

p->e = e;

if(NULL==M->rhead[i] || 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(NULL==M->chead[j] || 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 1;

}

}

int main()

{

CrossList M;

create_SMatrix(&M);

return 0;

}

如图:

b12fb3ae354ee4f827c3e48465216073.png

C++版本:

#include

#include

using namespace std;

typedef int ElemType;

typedef struct _NODE_

{

int i,j;//行和列下标

ElemType e;//元素值

struct _NODE_ *pRight;

struct _NODE_ *pDown;

}Node,*pNode;

typedef struct _CROSSLIST_

{

pNode *RowHead,*ColHead;//行和列链表头指针向量

int iRow,iCol,nodeCount;//矩阵行数,列数,非零元个数

}CrossList,*pCrossList;

//------------------------------------------------

void CreateCrossList(pCrossList pCrossListTemp);//创建十字链表

void PrintCrossList(pCrossList pCrossListTemp);//打印十字链表

//------------------------------------------------

void CreateCrossList(pCrossList pCrossListTemp)

{

//1.输入行数列数以及非零元个数

cout<

cin>>pCrossListTemp->iRow;

cin>>pCrossListTemp->iCol;

cin>>pCrossListTemp->nodeCount;

if(pCrossListTemp->nodeCount > pCrossListTemp->iRow*pCrossListTemp->iCol)

{

return;

}

//2.动态申请行和列指针数组

pCrossListTemp->RowHead = (pNode *)malloc(sizeof(pNode)*pCrossListTemp->iRow);

if(pCrossListTemp->RowHead == NULL)

{

return;

}

pCrossListTemp->ColHead = (pNode *)malloc(sizeof(pNode)*pCrossListTemp->iCol);

if(pCrossListTemp->ColHead == NULL)

{

free(pCrossListTemp->RowHead);

return;

}

//3.初始化这两个数组

int i,j;

for(i = 0; i < pCrossListTemp->iRow; i++)

{

pCrossListTemp->RowHead[i] = NULL;

}

for(j = 0; j < pCrossListTemp->iCol; j++)

{

pCrossListTemp->ColHead[j] = NULL;

}

//4.创建节点并连接到十字链表上

for(i = 0; i < pCrossListTemp->nodeCount; i++)

{

//4.1创建节点

pNode pNodeTemp = (pNode)malloc(sizeof(Node));

if(pNodeTemp == NULL)

{

return;

}

cout<

cin>>pNodeTemp->i;

cin>>pNodeTemp->j;

cin>>pNodeTemp->e;

pNodeTemp->pDown = NULL;

pNodeTemp->pRight = NULL;

//4.2连接

//连接行

//如果该行并没有连接任何节点(NULL)或者该行连接的第一个节点的列值大于当前待连接的节点则直接将当前节点连接到该行第一个节点的位置

if(pCrossListTemp->RowHead[pNodeTemp->i] == NULL || pCrossListTemp->RowHead[pNodeTemp->i]->j>pNodeTemp->j)

{

pNodeTemp->pRight = pCrossListTemp->RowHead[pNodeTemp->i];

pCrossListTemp->RowHead[pNodeTemp->i] = pNodeTemp;

}else//否则遍历该行找到合适的位置插入

{

pNode pNodeTravel = pCrossListTemp->RowHead[pNodeTemp->i];//指向第一个节点,从第一个节点开始遍历

while(pNodeTravel->pRight != NULL && pNodeTravel->pRight->j < pNodeTemp->j)//遍历到前一个节点

{

pNodeTravel = pNodeTravel->pRight;

}

//连接

pNodeTemp->pRight = pNodeTravel->pRight;

pNodeTravel->pRight = pNodeTemp;

}

//连接列,逻辑跟连接行一致

if(pCrossListTemp->ColHead[pNodeTemp->j]==NULL || pCrossListTemp->ColHead[pNodeTemp->j]->i>pNodeTemp->i)

{

pNodeTemp->pDown = pCrossListTemp->ColHead[pNodeTemp->j];

pCrossListTemp->ColHead[pNodeTemp->j] = pNodeTemp;

}else

{

pNode pNodeTravel = pCrossListTemp->ColHead[pNodeTemp->j];

while(pNodeTravel->pDown != NULL && pNodeTravel->pDown->i < pNodeTemp->i)

{

pNodeTravel = pNodeTravel->pDown;

}

pNodeTemp->pDown = pNodeTravel->pDown;

pNodeTravel->pDown = pNodeTemp;

}

}

}

void PrintCrossList(pCrossList pCrossListTemp)

{

int i,j;

pNode pTemp;

for(i = 0; i < pCrossListTemp->iRow; i++)

{

pTemp = pCrossListTemp->RowHead[i];

for(j = 0; j < pCrossListTemp->iCol; j++)

{

if(pTemp != NULL && pTemp->j == j)

{

cout<e<

pTemp = pTemp->pRight;

}else

{

cout<

}

}

cout<

}

cout<

}

int main()

{

CrossList c;

CreateCrossList(&c);

cout<

PrintCrossList(&c);

return 0;

}

如图:

710b3d4ccf514fb1f4cb4a57c64a2d5c.png

标签:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值