第五章 数组和广义表

数组

数组是一种特殊的线性表,线性表元素本身又是一个线性表

一、顺序存储

行序存储下aij储存位置为:

Loc(aij) = Loc(a11)+[(i-1)n + (j-1)]*L

列序存储下aij的存储位置为:

Loc(aij) = Loc(a11)+[(j-1)m + (i-1)]*L

二、压缩存储

一)特殊矩阵

1.对称矩阵
元素特性: aij = aji
存储空间:n(n+1)/2
存储位置:Loc(aij)=Loc(a11)+[i(i-1)/2+(j-1)]*L            (i>j)
		 Loc(aij)=Loc(a11)+[j(j-1)/2+(i-1)]*L            (j>i)
2.三角矩阵
元素特性:aij = 0   (i<j)
存储空间:n(n+1)/2
存储位置:Loc(aij)=Loc(a11)+[i(i-1)/2+(j-1)]*L            (i>j)
3.对角矩阵
元素特性:aij = 0    (|i-j|>1)
存储空间:(n-2)*3+4 = 3n-2
存储位置:Loc(aij) = Loc(a11) + [(i-1)*2+j-1]*L

二)稀疏矩阵

1.定义
元素特性:非零元较少,分布无规律
存储原则:储存行列下标(三元组表)、矩阵维数

三元组结构

typedef struct
{ 	int i , j;
	ELemType e ;//ELemType应该是预先定义的元素类型
}Tripe;

稀疏矩阵结构

#define MAXSIZE 100
typedef struct
{	Tripe data[MAXSIZE + 1];//data[0]不使用
	int mu , nu ,tu;
}TSMatrix;
2.顺序压缩储存

顺序压缩储存之后,稀疏矩阵失去了随机存取的能力
 
问题:存取第i行第j列非零元
 
三元组表:从头查找
带行链接信息的三元组表
增加一个数组 rpos[MaxRC+1](MaxRC为行数,rpos[0]不用)
rpos[i]表示第i行第1个非零元在三元组表中的下标
 

Alt
伪地址表示法
伪地址定义:行优先储存时,包括零元素在内的元素相对位置
 
在这里插入图片描述

2.转置
①直接转置
//m*n的矩阵
for(col=0;row<mu;col++)
{ 
	for(row=0;row<mu;row++)
	T[col][row]=M[row][col];
}
②三元组表法以M的列序转置

在这里插入图片描述

Status TransposeSMatrix(TSMatrix M,TSMATRIC &T)//希望在函数内部设置的三元组表通过引用方式进行返回
{	int col,p,k;
	T.mu=M.nu;	
	T.nu=M.mu;
	T.tu=M.tu;//赋予T矩阵行数、列数、元素个数
	if(T.tu)
	{	k=1;//k为T.data的下标
		for(col=1;col<=M.nu;col++)//查找每一列的非零元
		{
			for(p=1;p<=M.tu;p++)//p是M.data的下标,用于遍历M三元组
			{
				if(M.data[p].j==col)//当M三元组中的某一元素中的列数与所求列数相同
				{	T.data[k].i = M.data[p].j;
					T.data[k].j = M.data[p].i;
					T.data[k].e = M.data[p].e;
					k++;//完成了T.data[k]位置的元素,前往下一个位置
				}
			}
		}
		return OK;
	}
	return ERROR;	
}

算法时间复杂度 T(n) = O(M.nu*M.tu),若M.tuM.mu*M.nu同一个数量级,则时间算法复杂度T(n)=O(M.mu*M.nu^2),与一般转置方法相比没有优势。

③快速转置

按M.data中三元组次序转置,结果直接找到T.data中正确位置。
在这里插入图片描述

void fast_transpos(TSMatrix M,TSMatrix &T)
{	int col,p,num[N],num[N];
	T.mu = M.nu;
	T.nu = M.mu;
	T.tu = M.tu;
	if(T.tu)
	{
		for(col=1;col<=M.nu;col++)num[col]=0;
		for(p=1;p<=M.tu;col++)num[M.data[p].j]++;
		cpot[0]=0;cpot[1]=1;
		for(col=2;col<=M.nu;col++)
			cpot[col]=cpot[col-1]+num[col-1];
		for(p=1;p<=M.tu;p++)
		{	col=M.data[p].j;k=cpot[col];
			T.data[k].i=M.data[p].j;
			T.data[k].j=M.data[p].i;
			T.data[k].e=M.data[p].e;
			cpot[col]++; 
		}
	}
}

时间复杂度为T(n)=O(M.nu+M.tu),若M.tuM.mu*M.nu同数量级,T(n)=O(M.mu*M.nu)与直接转置数量相同,故在算法上有优越性。

3.链式压缩存储

如果要进行矩阵相加等运算,稀疏矩阵的非零元位置个数都会发生变化。使用三元组表必然会引起数组元素的大量移动。

①带行指针向量的单链表表示

每行非零元用一个单链表储存,建立一个数组储存各行单链表的头指针。
在这里插入图片描述

typedef struct RLNode//单链表节点
{	int j;//列数
	ElemType e;//节点元素
	struct RLNode *right;//指向节点指针
}RLNide,*Rlink;//定义了一个被Rlink指针所指的对象
typedef struct
{	RLink rhead[M];//创建了一个指向RLNide结构体的指针数组
	int mu,nu,tu;
}RowList;	
②十字链表存储

非零元结点包含五个域(非零元所在行、列、值,指向同行同列的下一个非零元指针)
实际上就是两个单链表交叉

typedef struct OLNode//结点结构
{	int row,col;//所在行列
	ElemType val;//非零元的值
	struct OLNode *right,*down;//同行、同列的下一个非零元指针
}OLNode,*OLink;
typedef struct//十字链表结构
{	OLink rhead[M],chead[N];//行列指针数组
	int mu,nu,tu;
}CrossList;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值