标签:
首先这里介绍什么是矩阵的十字链表,大家可以理解稀疏矩阵是顺序存储的,那么这个就是链式存储的。
如图:
存储该矩阵
那么应该是如下的格式:
我们知道稀疏矩阵的三元组存储方式的实现很简单,每个元素有三个域分别是col,row, e。代表了该非零元的行号、列号以及值。那么在十字链表的存储方式下,首先这三个域是肯定少不了的,不然在进行很多操作的时候都要自己使用计数器,很麻烦。而十字链表的形式大家可以理解成每一行是一个链表,而每一列又是一个链表
通过上面的图我们可以知道,每个结点不止要存放row, col, e。还要存放它横向的下一个结点的地址以及纵向的下一个结点的地址。形成一个类似十字形的链表的结构。
注意Rhead与Chead的类型,它们是指向指针的指针,也就是说,它们是指向我们定义的OLNode结构的结点的指针的指针。
两个版本C语言:
//稀疏矩阵的十字链表存储表示
//杨鑫
#include <stdio.h>
#include <stdlib.h>
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;
}
如图:
C++版本:
#include<iostream>
#include <stdlib.h>
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<<"输入矩阵几行,几列,几个非零元素:\n";
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<<"输入 行 列 元素"<<endl;
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<<pTemp->e<<" ";
pTemp = pTemp->pRight;
}else
{
cout<<"0 ";
}
}
cout<<endl;
}
cout<<endl;
}
int main()
{
CrossList c;
CreateCrossList(&c);
cout<<"================分割线========="<<endl;
PrintCrossList(&c);
return 0;
}
如图:
标签:
原文地址:http://blog.csdn.net/u012965373/article/details/46285531