330 likes | 481 Views
æ•°æ®ç»“æž„ ( DATA STRUCTURE). 计算机科å¦ä¸ŽæŠ€æœ¯å¦é™¢. ç¬¬äº”ç« æ•°ç»„ä¸Žå¹¿ä¹‰è¡¨. 数组 数组的定义åŠå…¶åŸºæœ¬æ“作 数组的å˜å‚¨ç»“æž„ 矩阵的压缩å˜å‚¨ 特殊矩阵的压缩å˜å‚¨ 稀ç–矩阵的压缩å˜å‚¨ 广义表. 5.1 数组的定义åŠå…¶åŸºæœ¬æ“作. 1) 数组的定义 数组是 n(n>=0) 个 ç›¸åŒ æ•°æ®ç±»åž‹æ•°æ®å…ƒç´ æž„æˆçš„ æœ‰é™ åºåˆ—。 数组å¯ä»¥çœ‹æˆæ˜¯ä¸€ç§ç‰¹æ®Šçš„线性表,å³çº¿æ€§è¡¨ä¸æ•°æ®å…ƒç´ 本身也是一个线性表。. ( ).
E N D
数据结构 (DATA STRUCTURE) 计算机科学与技术学院
第五章 数组与广义表 • 数组 • 数组的定义及其基本操作 • 数组的存储结构 • 矩阵的压缩存储 • 特殊矩阵的压缩存储 • 稀疏矩阵的压缩存储 • 广义表
5.1数组的定义及其基本操作 1) 数组的定义 • 数组是n(n>=0)个相同数据类型数据元素构成的有限序列。 • 数组可以看成是一种特殊的线性表,即线性表中数据元素本身也是一个线性表。
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) • 二维数组同样满足数组的定义。一个二维数组可以被看成是特殊的一维数组,其中,每个元素又是一个一维数组。多维数组可以按同样的方法类推。
2) 数组的特点 • 数组中的数据元素数目固定(结构固定) • 数组中的数据元素具有相同的数据类型(元素同构) • 数组中的每个数据元素都与一组唯一的下标值相对应; • 数组是一种随机存储结构。
3) 数组的基本运算 • 构造 n 维数组 • 销毁 n 维数组 • 存取数组元素值(给定一组下标,存取相应数据元素值) • 修改数组元素值(给定一组下标,修改相应数据元素值)
5.2数组的顺序存储 • 一个一维数组,一旦第一个元素a0的存储地址Loc(a0)确定,而每个元素所占用的存储空间大小为l, 则第i个元素的地址可以由以下公式计算: LOC ( i ) = LOC ( i -1 ) + l =α+ i*l
二维数组与高维数组 1)存储方式 计算机的存储结构是一维的,因而多维数组必须按某种次序排成一个线性序列加以存储。 • 按行优先方式顺序存储 a11,a12,…a1n,a21,…,a2n,…,am1,am2,…,amn • 按列优先方式顺序存储 a11,a21,…am1,a12,…,am2,…,a1n,a2n,…,amn
2)任意元素存储地址的计算 • 以二维数组行优先顺序存储为例:假设每个元素占用l 单元 由于任一元素aij 前面有i-1行,每行n个元素 LOC (aij ) = LOC(a11)+((i-1)*n+(j-1))* l • 按列优先顺序存储: LOC (aij ) = LOC(a11)+((j-1)*m+(i-1))* l
推广到 n 维数组 • 将其中的每一个元素映射到一维数组的某一个位置,各维元素个数为m1, m2, m3, …, mn,下标为 i1, i2, i3, …, in的数组元素的存储地址: 3) 数据类型定义:书
5.3矩阵的压缩存储 • 高级语言中一般用二维数组存储矩阵,当矩阵中存在大量相同的元素或零元素时,浪费空间。 • 矩阵的压缩存储:为多个值相同的元素只分配一个存储空间,对零元素不分配空间。 • 特殊矩阵:值相同的元素或零元素在矩阵中分布有一定规律。 • 稀疏矩阵:零元素较多,分布无规律。
5.3.1特殊矩阵 1) 对称矩阵 在一个n阶方阵A中,若元素满足下述性质: 则称A为对称矩阵。对称矩阵中的元素关于主对角线对称,故只需要存储矩阵的上三角或下三角矩阵,这样可以节约大约一半的空间。
a11 a21 a22 a31 a32 a33 ....... an,1 ........ an,n a11 a21 a22 a31 a32 an1 ann …... …... k= 0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 • 在此下三角阵中,第i行恰有i个元素,元素总数为 • 因此可将这些元素存放在一个向量S[n(n+1)/2]中
为了便于访问方阵A中的元素,必须在aij和S[k]之间建立一个对应关系。若aij在下三角矩阵中,则有:为了便于访问方阵A中的元素,必须在aij和S[k]之间建立一个对应关系。若aij在下三角矩阵中,则有: 若aij在上三角矩阵中,则有: • k 和 i、j的对应关系为:
2) 三角矩阵 以主对角线划分,下三角: 在多数情况下,三角矩阵的常数c为0。
5.3.2稀疏矩阵的压缩存储 • 如果一个矩阵的非 0 元素个数远远小于矩阵 元素的总数,则称这个矩阵为稀疏矩阵。 • 一般来说,稀疏矩阵非0元素的分布是无规律的。因此,在存储非0元素的同时,还要存储适当的辅助信息。 • 稀疏矩阵常用的压缩存储方式: • 三元组表 • 十字链表
1) 三元组表 • 存储特点: • 对于矩阵中每个非0元素,用它的行号、列号、元素值,即(i, j, aij)表示。 • 将表示稀疏矩阵的所有非0元素的三元组按行优先(列优先)顺序排列,则可得到一个其结点均是三元组的线性表,称为三元组表。 • 要唯一确定一个稀疏矩阵,还必须存储该矩阵的行数和列数。
数据类型定义: # define maxsize 100 三元组结点: typedef int datatype • typrdef struct • { int i, j; • datatype v; • } Triple; • 稀疏矩阵: • typedef struct • { Triple data[maxsize]; • int mu, nu, tu; /*行、列、非零元素个数*/ • } TsMatrix;
非零元值 行列下标 i j v 0 1 2 3 4 5 6 7 8 data 例: 6 7 8 1 2 12 1 3 9 data[0].i, data[0].j, data[0].v分别 存放矩阵行列维数和非零元个数 3 1 -3 3 6 14 4 3 24 三元组表所需存储单元个数为3(t+1) 其中t为非零元个数 5 2 18 6 1 15 6 4 -7
基本运算举例: 以矩阵的转置为例说明这种压缩存储结构是如何实现矩阵运算的。 • 问题描述:已知一个稀疏矩阵的三元组表,求该矩阵转置矩阵的三元组表。(一个m×n矩阵A,它的转置矩阵是一个n×m 矩阵B,且A[i][j]=B[j][i]) • 一般矩阵转置算法: • for(col=0;col<n;col++) • for(row=0;row<m;row++) • n[col][row]=m[row][col]; • T(n)=O(mn)
快速转置算法 • 思想:即按A.data[]中三元组次序转置,转置结果放入B.data[]中恰当位置。此法关键是要预先确定A中每一列第一个非零元在B.data[]中位置,为确定这些位置,转置前应先求得A的每一列中非零元个数 • 增设辅助数组 num 和 cpot 。 num[col]:表示矩阵A 第col列中非0元素的个数。 cpot[col]:表示第col列第一个非0元素在B.data[]中位置 Cpot[1]=1 Cpot[col]=cpot[col-1]+num[col-1] 2<=col<=A.nu
col 3 6 7 1 2 4 5 2 num[col] 1 0 2 2 1 0 cpot[col] 5 8 9 1 3 7 8 • 扫描矩阵三元组表,根据某项的列号,确定它转置后的行号,查 cpot表,按查到的位置直接将该项存入转置三元组表中。
算法:P100 • 算法分析: O( nu+tu) 当非0元素个数->mu*nu时,接近O(mu*nu)
2) 十字链表 十字链表是稀疏矩阵链接形式存储结构的一种(当然还有其它形式)。在该方法中每一个非0元素用一个结点表示,结点中除了表示非0元素的行、列和值的三元组外,还增加了两个链域:行指针域,用来指向本行中下一个非0元素;列指针域,用来指向本列中下一个非0元素。
i j v/next 行指针 列指针 在每一个行链表和每一个列链表增加一个和表结点相同的表头结点,表头结点中的行、列域置为0,并且将所有的行、列链表和他们的头结点一起链成一个循环链表。 实际实现时,两组头结点可以合用,即第i行链表和第i 列链表共享一个表头结点。因为表头结点中值域v无用,所以可以将它作为指针域,用来指向下一个表头结点的指针。
5.4广义表 (General Lists ) 1) 定义: • 广义表:n ( 0 )个表元素组成的有限序列, 记作LS = (a1, a2, …, an) 或 LS (a1, a2, …, an) LS 是表名,其中ai是表元素,它或者是数据元素 (称为原子),或者是一个广义表(称为子表) • n为表的长度。n = 0 的广义表为空表。 • 广义表深度:广义表中括号的重数。 • n > 0时,表的第一个表元素称为广义表的表头(head),除此之外,其它表元素组成的表称为广义表的表尾(tail)。
非空广义表的表头是表中第一个元素, 它可以是原子, 也可以是子表; 而其表尾必定是子表 例: A=( ) 长度:0 L=(()) 长度:1 L = ( a, b ) 长度:2 head(L) = a tail(L) = (b) head(tail(L)) = b tail(tail(L)) = ( ) B = ( A,x,y ) 长度:3 head(B) = A tail(B) = (x,y) D=( D, f) 长度:2 head(D) = D tail(D) = (f) E = (‘a’ , ( 5, 3, ‘x’ ) ) 长度:2 head(E) = ‘a’ tail(E) = (( 5, 3, ‘x’ ) )
2) 广义表的图形表示 例:A = ( ) B = ( 6, 2 ) C = ( ‘a’, ( 5, 3, ‘x’ ) ) D = ( B, C, A ) F = ( 4, F )
3) 广义表的存储结构 由于广义表(a1,a2,a3,…an)中的数据元素可以具有不同的结构,(或是原子,或是广义表),因此,难以用顺序存储结构表示,通常采用链式存储结构,每个数据元素可用一个结点表示。 由于广义表中有两种数据元素,原子或广义表,因此,需要两种结构的结点:一种是表结点,一种是原子结点。 下面介绍两种广义表的链式存储结构。
tag=1 hp tp • 表结点由三个域组成:标志域、指示表头的指针域和指示表尾的指针域;而原子域只需两个域:标志域和值域。 • 表结点 原子结点 • 表结点由三个域组成:标志域、指示表头的指针域和指示表尾的指针域;原子结点的三个域为:标志域、值域和指示表尾的指针域。
本章小结:需要复习的知识点 • 数组 • 数组的顺序存储(行优先,列优先) 逻辑地址 物理地址的计算; • 矩阵的压缩存储 • 对称矩阵、上三角或下三角等特殊矩阵压缩存储时的地址转换公式 • 稀疏矩阵的压缩存储:存储特点、三元组表表示 • 广义表 • 广义表定义,广义表长度、深度、求广义表的表头、表尾