标准 第五章 数组和广义表.docx
《标准 第五章 数组和广义表.docx》由会员分享,可在线阅读,更多相关《标准 第五章 数组和广义表.docx(20页珍藏版)》请在冰豆网上搜索。
标准第五章数组和广义表
第五章数组和广义表
5.1数组
数组是最常用的一种数据结构,几乎所有的程序设计语言都把数组设为固有的数据类型。
C语言支持多维数组。
intarray1[N];声明了一个一维数组,有多少个元素?
答:
有N个数据元素
intarray2[M][N];声明了一个二维数组,有多少个元素?
答:
有M*N个数据元素
intarray3[X][Y][Z];声明了一个三维数组,有多少个元素?
答:
有X*Y*Z个数据元素。
C语言对数组的维数没有严格的界限。
但是三维以上的数组基本不大使用,用得最多的是一、二维数组。
下面来看一下数组的存储
5.2数组的存储
所有的语言都是把数组元素放在一组地址连续的存储单元中
一维数组的存储相对来说比较简单
就是把数组元素从a0至an依次放在一组地址连续的存储单元中
a0
a1
a2
…
an
…
a0
a1
a2
…
an
…
二维数组的存储相对复杂一点,有两种存储方式
行优先顺序(以行序为主序)——先存储第一行的元素,再存储第二行的元素,最后存储第m行的元素
a00,a01,…,a0n-1,a10,a11,…,a1n-1,…,am-11,am-12,…,am-1n-1
在PASCAL、C语言中,二维数组就是按行优先顺序存储的。
列优先顺序(以列序为主序)——先存储第一列的元素,再存储第二列的元素,最后存储第n列的元素
a00,a10,…,am-10,a01,a11,…,am-11,…,a0n-1,a1n-1,…,am-1n-1
在FORTRAN语言中,数组就是按列优先顺序存储的。
假设二维数组a[m,n]每个元素只占L个存储单元,”按行优先”存放数组,首元素a00的地址为Loc(0,0),求任意元素aij的地址:
最基本的原理
aij的起始地址
=第一个元素的起始地址+该元素前面的元素个数*单位长度
第一个元素的起始地址是已知的,每个元素的单位长度L也是已知的。
集中精力要解决的问题是aij前面的元素个数。
aij是排在第i+1行,第j+1列;前面的i行有n×i个元素,
第i+1行第j+1个元素aij前面还有j个元素。
aij前面的元素个数共有n×i+j个
由此得到如下地址计算公式:
Loc(i,j)=Loc(0,0)+(n×i+j)L
(考试时从这地方出题)
有关于数组的内容,掌握这些就可以
程序员考试试题:
2006-1
对于二维数组a[0…4,1…5],设每个元素占1个存储单元,且以行为主序存储,则元素a[2,1]相对于数组空间起始地址的偏移量是______。
也就是a[21]前面的元素个数*单位长度
A.5 B.10
C.15 D.25
解:
C语言二维数组的行下标和列下标都是从0开始,其他语言则不一定。
本题二维数组行下标从0开始,列下标从1开始。
数组第一个元素是a[01]。
数组的所有元素如下所示:
a[01]a[02]a[03]a[04]a[05]
a[11]a[12]a[13]a[14]a[15]
a[21]a[22]a[23]a[24]a[25]
a[31]a[32]a[33]a[34]a[35]
a[41]a[42]a[43]a[44]a[45]
a[21]前面的元素个数一共有10个,每个元素的单位长度是1,10*1=10。
所以元素a[2,1]相对于数组空间起始地址的偏移量是10。
故答案选B.
5.3矩阵
求A+B
怎样上机实现?
(小儿科问题)
1、怎样表示矩阵?
用二维数组存储矩阵中的元素
2、编写算法
#include
voidmain()
{
floata[3][4];//第一个矩阵
floatb[3][4];//第二个矩阵
floatc[3][4];//和矩阵
inti,j;
for(i=0;i<=2;i++)
for(j=0;j<=3;j++)
{printf(“\nA%d%d=”,i+1,j+1);
scanf(“%f”,&a[i][j]);}//输入第一个矩阵元素值
for(i=0;i<=2;i++)
for(j=0;j<=3;j++)
{printf(“\nB%d%d=”,i+1,j+1);
scanf(“%f”,&b[i][j]);}//输入第二个矩阵元素值
printf(“\n相加后的矩阵C:
\n”);
for(i=0;i<=2;i++)
for(j=0;j<=3;j++)
{c[i][j]=a[i][j]+b[i][j];
printf(“\nC%d%d=%f”,i+1,j+1,c[i][j]);}
}//求和矩阵
但是在一些特殊矩阵中,元素呈某种规律分布或者矩阵中有大量的零元素(对称矩阵,三角矩阵,稀疏矩阵),如果仍用二维数组存,会造成极大的浪费,尤其是处理高阶矩阵的时候。
为了节省存储空间,我们可以对这类矩阵进行压缩存储。
5.2.1特殊矩阵的压缩存储
1、对称矩阵的压缩存储
若n阶方阵A中的元满足特性 aij=aji0≤i,j≤n-1
则称A为n阶对称矩阵。
15137
50800
A=18926
30251
70613
矩阵A是否是对称矩阵,满足对称矩阵定义,显然是。
矩阵A关于主对角线对称,只需存储上三角或下三角中的元素。
存储下三角:
a11
a21a22
a31a32a33
a41a42a43a44
a51a52a53a54a55
对称矩阵A的压缩存储就是将矩阵A下三角中的元素按行优先的顺序存储到一维数组中。
a11
a21
a22
a31
。
。
。
a51
。
。
。
a55
1)假设对称矩阵A有n行n列,对称矩阵A的压缩存储需要一个多大的一维数组?
答:
对称矩阵A的下三角中有多少元素就需要一个多大的一维数组。
那麽对称矩阵A的下三角中有多少元素呢?
a11
a21a22
:
:
:
:
:
:
:
:
ai-11ai-12……ai-1i-1
ai1ai2ai3…aij…aii
:
:
:
:
:
:
:
:
:
:
an1an2an3…anj…ani…ann
第1行1个元素
第2行2个元素
第3行3个元素
。
。
。
第i行i个元素
第n行n个元素
共有1+2+。
。
。
+n=n(n+1)/2个元素。
对称矩阵A的压缩存储需要一个n(n+1)/2长度的一维数组
2)假设对称矩阵A中的元素定义为float型,压缩存储可以节省多少存储空间?
答:
非压缩存储所用存储空间为4*n*n个字节,(即用二维数组存储,)
压缩存储所用存储空间=4*n(n+1)/2=2n(n+1)个字节
节省的存储空间=4*n*n-2n(n+1)=2n(n-1)个字节
3)下三角中的元素aij在一维数组中的下标是什麽?
答:
要想知道元素aij在一维数组中的下标是什麽,必须知道元素aij前面有多少个元素。
元素aij前面有i-1行,每行i个元素。
共:
1+2+…+i-1=i(i-1)/2
共有i(i-1)/2+j-1个元素,所以它是一维数组的第i(i-1)/2+j个元素,它的下标是i(i-1)/2+j-1。
2、三角矩阵
若n阶方阵中下(上)三角(不包括对角线)中的元均为常量c或0,则称为上(下)三角矩阵。
下三角矩阵A的压缩存储就是将矩阵A下三角中的元素按行优先的顺序存储到一维数组中。
常量c或0存储到数组的最后一个位置。
掌握三个问题:
1)假设下三角矩阵A有n行n列,下三角矩阵A的压缩存储需要一个多大的一维数组?
a11
a21a22
:
:
:
:
:
:
:
:
ai-11ai-12……ai-1i-1
ai1ai2ai3…aij…aii
:
:
:
:
:
:
:
:
:
:
an1an2an3…anj…ani…ann
第1行1个元素
第2行2个元素
第3行3个元素
。
。
。
第i行i个元素
第n行n个元素
还有一个常数c
共有1+2+。
。
。
+n+1=n(n+1)/2+1个元素。
2)下三角矩阵A中的元素定义为float型,下三角矩阵A的压缩存储节省了多少存储空间?
答:
非压缩存储即用二维数组存储,所用存储空间为4n*n个字节,
压缩存储所用存储空间为2n(n+1)+4个字节,
可节省2n(n-1)-4个字节的存储空间。
3)下三角矩阵A中的元素aij在一维数组中的下标是什麽?
答:
元素aij前面有多少个元素?
共有i(i-1)/2+j-1个元素,所以它是一维数组的第i(i-1)/2+j个元素,它的下标是i(i-1)/2+j-1。
C是一维数组中的最后一个元素。
它的下标是n(n+1)/2+1
程序员试题
2004-1对矩阵压缩存储的主要目的是____。
A.方便运算 B.节省存储空间
C.降低计算复杂度 D.提高运算速度
2003将一个三对角矩阵A[l..100,1..100]中的元素按行存储在一维数组B[l..298]中,矩阵A中的元素A[66,65]在数组B中的下标为______。
A.195B.196C.197D.198
3、稀疏矩阵
如果矩阵中只有少量的非零值元,并且这些非零值元在矩阵中的分布没有一定规律,则称为随机稀疏矩阵,简称为稀疏矩阵。
300500
00-2000
A5*6=104060
000000
00-1000
假设在mxn的矩阵中有t个非零值元,令δ=t/m*n,称δ为矩阵的稀疏因子。
A的稀疏因子是多少?
7/30=0.23=23%。
A并不属于严格意义上的稀疏矩阵,只有稀疏因子小于5%的矩阵才能称之为稀疏矩阵。
稀疏矩阵的压缩存储:
只存储非0元素。
描述非0元素的信息有:
该非0元素所在的行数;该非0元素所在的列数;该非0元素的值。
整个矩阵的存储:
每个非零元素由(row,col,value)唯一确定,整个矩阵可表示成一个三元组表。
1)三元组表的顺序存储
如何表示三元组表的一行?
三元组表的每一行都是由三个数据项组成的,考虑用结构体表示。
structTriple{
introw,col;
floatvalue;
};
如何表示整个三元组?
用结构体数组
定义了结构体型Triple后,Triple的作用等同于int,float等。
intb[6];//定义了一个整型数组b,它有6个数据元素,元素类型是整型。
Tripledata[7];//数组data中有7个数据元素,每个元素类型都是结构体Triple型
c语言中认为三元组表的顺序存储就是把三元组表存放到结构体数组中。
假设稀疏矩阵A的数据元素是浮点型,row、col是整型,value是浮点型,稀疏矩阵A采用三元顺序表存储节省了多少存储空间?
答:
稀疏矩阵A采用二维数组存储所用的存储空间=5*6*4=120字节。
稀疏矩阵A采用三元顺序表存储所用的存储空间=7*6=42字节。
节省的存储空间=120-42=78字节。
2)三元组表的链式存储
在链式存储中,矩阵的每一个非零元素用一个结点表示,该结点除了(row,col,Value)数据部分以外,还有两个指针:
行指针和列指针。
row
col
Value
列指针down
行指针right
列指针指示同一列中的下一个非0元素
行指针指示同一行中的下一个非0元素
矩阵A的链式存储结构如下图所示:
3005
A3*4=0-100
3000
每行有一个头指针,头指针指向各行的第一个非零元素结点。
如果行中没有非零元结点,头指针是空。
每列有一个头指针,头指针指向各列的第一个非零元素结点。
如果列中没有非零元结点,头指针是空。
第一行第一列的数据元素值是3,列指针DOWN指向同一列中的下一个非零元素,行指针RIGHT指向同一行中的下一个非零元素。
因为每个非零元结点
即处于某一行的单链表中,又处于某一列的单链表中;像一个交叉的十字路口。
故稀疏矩阵的这种链式存储存储结构又被称为十字链表。
作业:
请画出稀疏矩阵M和N的十字链表结构。
(比葫芦画瓢)
(比着书上101页5-5和104页图5-6画)
5.4广义表
线性表的定义:
线性表(LinearList)是由n(n≥0)个类型相同的数据元素组成的有限序列。
L=(a1,a2,...,ai-1,ai,ai+1,...,an)
广义表的定义:
广义表(GeneralizedList)是n(n>=0)个数据元素组成的有限序列。
LS=(α1,α2,α3,…,αn)
几点说明:
1、αi与αj类型可以不同。
αi可以是原子元素,也可以是子表元素。
说起来比较抽象,举例来看:
C=(a,(b,c,d))
C是一个广义表,第一个数据元素是一个原子元素a,第二个数据元素是子表(b,c,d)。
2、广义表的长度:
广义表中的数据元素个数。
广义表C的长度是2。
广义表A=()的长度是?
3、广义表的深度:
广义表展开以后所含括号的重数。
广义表C的深度是2。
广义表B=(A,C)的深度?
1?
广义表B的展开式=((),(a,(b,c,d)))
括号的重数是三重,广义表B的深度是3。
4、广义表的表头和表尾
广义表LS=(α1,α2,α3,…,αn)的表头head是α1,表尾tail是(α2,α3,…,αn)。
广义表C=(a,(b,c,d))的表头head是a,广义表C的表尾tail是((b,c,d))。
广义表B=(e)表头为e,表尾为空。
5.5广义表的存储结构
因为广义表数据元素可具有不同结构,故难以用顺序方式存储。
一般用链接方式存储,称之为广义链表。
LS=(α1,α2,α3,…,αn)
因为LS的元素αi可以是原子,也可以是子表。
所以广义链表中有两种不同类型的结点:
原子结点和子表结点。
原子数据元素结点由两部分组成:
标志域0和原子元素的值。
子表数据元素结点由三部分组成:
标志域1、子表表头指针和子表表尾指针。
1
headp
tailp
请画出广义表L=(a,(b))的链式存储结构:
先分析再画
广义表L的表头是原子元素a,表尾是((b))。
[((b))还是一个表]
表((b))的表头是(b)[(b)还是一个表],表尾是空表。
[空表用NULL表示]
表(b)的表头是原子元素b,表尾是空表。
[空表用NULL表示]
作业:
请画出广义表C=(a,(b,c,d))的链式存储结构: