1 / 124

第五章 数组和广义表

第五章 数组和广义表. 本章主要内容 :. 数组的类型定义. 数组的顺序表示和实现. 稀疏矩阵的压缩存储. 广义表的类型定义. 广义表的表示方法. 广义表操作的递归函数. 本章重点 : 数组的类型定义 稀疏矩阵的压缩存储 广义表的类型定义 本章难点 : 稀疏矩阵的压缩存储 广义表的表示和实现. 第五章 数组和广义表. 数组和广义表可以看成线性表在下述含义上的扩展:表中数据元素本身也是一个数据结构。 几乎所有的程序设计语言都把数组类型设为固定类型。 本章以抽象数据类型的形式讨论数组的定义和实现。. 5.1 数组的类型定义. ADT Array {

julio
Télécharger la présentation

第五章 数组和广义表

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第五章 数组和广义表

  2. 本章主要内容: • 数组的类型定义 • 数组的顺序表示和实现 • 稀疏矩阵的压缩存储 • 广义表的类型定义 • 广义表的表示方法 • 广义表操作的递归函数

  3. 本章重点: • 数组的类型定义 • 稀疏矩阵的压缩存储 • 广义表的类型定义 本章难点: • 稀疏矩阵的压缩存储 • 广义表的表示和实现

  4. 第五章 数组和广义表 • 数组和广义表可以看成线性表在下述含义上的扩展:表中数据元素本身也是一个数据结构。 • 几乎所有的程序设计语言都把数组类型设为固定类型。 • 本章以抽象数据类型的形式讨论数组的定义和实现。

  5. 5.1 数组的类型定义 ADT Array { 数据对象: D={aj1,j2, ...,,ji,jn| ji =0,...,bi -1, i=1,2,..,n } 数据关系: R={R1, R2, ..., Rn} Ri={<aj1,... ji,... jn, aj1, ...ji +1, ...jn> | 0  jk  bk -1, 1  k  n 且k  i, 0  ji bi -2, i=2,...,n } } ADT Array 基本操作:

  6. 二维数组的定义: 数据对象: D = {aij | 0≤i≤b1-1, 0 ≤j≤b2-1} 数据关系: R = { ROW, COL } ROW = {<ai,j,ai+1,j1>| 0≤i≤b1-2, 0≤j≤b2-1} COL = {<ai,j,ai,j+1>| 0≤i≤b1-1, 0≤ j≤b2-2}

  7. 我们可以把二维数组看成这样一个定长线性表:它的每个数据元素也是一个定长线性表。我们可以把二维数组看成这样一个定长线性表:它的每个数据元素也是一个定长线性表。 • 可以把二维数组看成一个一维数组,其中每个数据元素也是一维数组。

  8. 如下所示二维数组,以m行n列的矩阵表示: • A= a00 a01 a02 … a0,n-1 • a10 a11 a12 … a1,n-1 • . . . . • . . . . • am-1,0 ……. am-1,n-1 • 它可以看成一个线性表: • A=(A0,A1,A2,…Ap) (p=m-1或n-1) • Aj可以看成列向量形式=(a0j,a1j,…am-1j) • 或者Ai是行向量形式列表=(ai0,ai1,..ai,n-1)

  9. 基本操作: 数组一旦被定义,它的维数和上、下界 就不会再改变,因此,除了结构的初始化和销毁之外,数组只有存取元素和修改元素的操作。

  10. 基本操作: InitArray(&A, n, bound1, ..., boundn) DestroyArray(&A) Value(A, &e, index1, ..., indexn) Assign(&A, e, index1, ..., indexn)

  11. InitArray(&A, n, bound1, ..., boundn) 操作结果:若维数 n 和各维长度合法, 则构造相应的数组A,并 返回OK。

  12. DestroyArray(&A)操作结果:销毁数组A。

  13. Value(A, &e, index1, ..., indexn) 初始条件:A是n维数组,e为元素变量, 随后是n 个下标值。 操作结果:若各下标不超界,则e赋值为 所指定的A 的元素值,并返 回OK。

  14. Assign(&A, e, index1, ..., indexn) 初始条件:A是n维数组,e为元素变量, 随后是n 个下标值。操作结果:若下标不超界,则将e的值赋 给所指定的A的元素,并返回 OK。

  15. 5.2 数组的顺序表示和实现 类型特点: 1) 只有引用型操作,没有加工型操作; 2) 数组是多维的结构,而存储空间是 一个一维的结构。 • 有两种顺序映象的方式: • 1)以行序为主序(低下标优先); • 2)以列序为主序(高下标优先)。

  16. 0 a00  b1*b2数组 按行序为主序存放 1 a01 ……. m-1 a0n m a00 a01 …….. a0n a10 a10 a11 …….. a1n a11 …….. …………………. a1n am0 am1 …….. amn ………. am0 Loc(aij)=Loc(a00)+[i*b2+j]*l am1 …….. m*n-1 amn

  17. 0 a00   b1*b2数组按列序为主序存放 1 a10 ……. m-1 am0 m a00 a01……..a0n a01 a10 a11 ……..a1n a11 …….. …………………. am1 am0am1…….. amn ………. a0n Loc(aij)=Loc(a00)+[j*b1+i]*l a1n …….. m*n-1 amn

  18. 以“行序为主序”的存储映象 二维数组A中任一元素ai,j的存储位置 LOC(i,j) = LOC(0,0) + (b2×i+j)× L 称为基地址或基址。

  19. 推广到一般情况,可得到 n 维数组数据元素存储位置的映象关系 n LOC(j1, j2, ..., jn ) = LOC(0,0,...,0) + ∑ ci ji = LOC(0,0,...,0) +(b2*b3*b4*…*bn*j1+b3 *b4*b5*…*bn*j2+…+bn*jn-1+jn)L =1 i 称为 n 维数组的映象函数。数组元素 的存储位置是其下标的线性函数。

  20. 例:以行序为主序存储的整数数组A(9*3*5*8),第一个元素的地址是100,每个整数占4个字节,问a(3125)的地址是多少?例:以行序为主序存储的整数数组A(9*3*5*8),第一个元素的地址是100,每个整数占4个字节,问a(3125)的地址是多少? • LOC(a[3125])=100+(3*5*8*3+5*8*1+8*2+5)*4=1784

  21. 5.3 稀疏矩阵的压缩存储 在这里我们考虑的不是矩阵本身,而是如何 存储矩阵的元,从而使矩阵的各项运算能够进行。 用高级语言编程序的时候,通常用二维数组来存放矩阵的元。 但是,有时一些阶数很高的矩阵,里面存了很多值相同的元,或者零元,所以要对矩阵进行压缩存储。

  22. 5.3 稀疏矩阵的压缩存储 何谓稀疏矩阵? 假设 m 行 n 列的矩阵含 t 个非零元素,则称 为稀疏因子。 通常认为 0.05 的矩阵为稀疏矩阵。

  23. 5.3 稀疏矩阵的压缩存储 何谓压缩存储? 就是为多个值相同的元分配一个存储空间;对零元不分配空间。

  24. 有两类稀疏矩阵: 1) 特殊矩阵 非零元在矩阵中的分布有一定规则 例如: 三角矩阵 对角矩阵 2) 随机稀疏矩阵 非零元在矩阵中随机出现

  25. 特殊矩阵的压缩存储 以n阶对称矩阵为例: 在一个n阶方阵A中,若元素满足下述性质: aij=aji(1≦i,j≦n) 则称A为n阶对称矩阵。如图5.1 1 5 1 3 7 a11 5 0 8 0 0 a21 a 22 1 8 9 2 6 a31 a32 a33 3 0 2 5 1 ……………….. 7 0 6 1 3 an1 an2 an3 …a nn 图 5.1 对称矩阵

  26. n阶对称矩阵中的元素关于主对角线对称,故只要存储矩阵中上三角或下三角中的元素,让每两个对称的元素共享一个存储空间,这样,能节约近一半的存储空间。n阶对称矩阵中的元素关于主对角线对称,故只要存储矩阵中上三角或下三角中的元素,让每两个对称的元素共享一个存储空间,这样,能节约近一半的存储空间。 不失一般性,我们按“行优先顺序”存储主对角线(包括对角线)以下的元素。

  27. 在这个下三角矩阵中,第i行恰有i个元素,元素总数为n(n+1)/2,这样就可将n2个数据元素压缩存储在n(n+1)/2个存储单元中。在这个下三角矩阵中,第i行恰有i个元素,元素总数为n(n+1)/2,这样就可将n2个数据元素压缩存储在n(n+1)/2个存储单元中。 假设以一维数组va作为n阶对称矩阵A的压缩存储单元,k为一维数组va的下标序号,aij为n阶对称矩阵A中i行j列的数据元素(其中1≦i,j≦n ),其数学映射关系为: i(i-1)/2+j-1 当i≧j j(j-1)/2+i-1 当i<j k=

  28. a11 0 0…….. 0 a21 a220…….. 0 …………………. 0 an1 an2 an3…….. ann 按行序为主序: …... a11 a21 a22 a31 a32 an1 ann …... k=0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 i(i-1) Loc(aij)=Loc(a11)+[( +(j-1)]*l 2 • 三角矩阵

  29. a11a12 0 …………… . 0 a21 a22a230…………… 0 0a32 a33a340……… 0 …………………………… 00… an-1,n-2 an-1,n-1an-1,n 00… …an,n-1 ann. …... a11 a12 a21 a22 a23 ann-1 ann 按行序为主序: …... k=0 1 2 3 4 n(n-1)/2 n(n+1)/2-1 • 对角矩阵 Loc(aij)=Loc(a11)+2(i-1)+(j-1)

  30. 特殊矩阵中非零元的分布都有一个明显的规律,所以可以压缩存储到一维数组中,并找出在一维数组中的对应关系。特殊矩阵中非零元的分布都有一个明显的规律,所以可以压缩存储到一维数组中,并找出在一维数组中的对应关系。

  31. 随机稀疏矩阵的压缩存储方法: 一、三元组顺序表 二、行逻辑联接的顺序表 三、 十字链表

  32. 一、三元组顺序表 #define MAXSIZE 12500 typedef struct { int i, j; //该非零元的行下标和列下标 ElemType e; // 该非零元的值 } Triple; // 三元组类型 typedef struct{ Triple data[MAXSIZE + 1]; int mu, nu, tu; } TSMatrix; // 稀疏矩阵类型

  33. 例1:写出下图5.3所示稀疏矩阵的压缩存储形式。例1:写出下图5.3所示稀疏矩阵的压缩存储形式。 1 2 3 4 5 6 1 2 3 4 5 6 图5.3 012 9 0 0 0 00 0 0 0 0 -3 0 0 0 14 0 0 0 24 0 0 0 018 0 0 0 0 150 0 -7 0 0 解:用三元组线性表表示: {{1,2,12},{1,3,9},{3,1,-3},{3,5,14}, {4,3,24},{5,2,18},{6,1,15},{6,4,-7}}

  34. 00 0 0 00 0 0 0 0 0 0 00 0 0 02 0 0 00 0 0 120 0 0 00 0 0 3 0 0 0 00 0 4 00 6 0 160 0 0 例2:下面的三元组表表示一个稀疏矩阵,试还原出它的稀疏矩阵。

  35. 如何求转置矩阵?

  36. 用常规的二维数组表示时的算法 for (col=1; col<=nu; ++col) for (row=1; row<=mu; ++row) T[col][row] = M[row][col]; 其时间复杂度为: O(mu×nu)

  37. 用“三元组”表示时如何实现? • 先分析转置的过程:能否将行、列直接互换??

  38. 用“三元组”表示时如何实现? 2 1 14 1 2 14 5 1 -5 1 5 -5 2 2 -7 2 2 -7 1 3 36 3 1 36 4 3 28 3 4 28

  39. 有两种解决方法: • 1、按照矩阵M的列序来转置。

  40. 用“三元组”表示时如何实现? 1 3 36 1 2 14 2 1 14 1 5 -5 2 2 -7 2 2 -7 4 3 28 3 1 36 5 1 -5 3 4 28

  41. cpot[1]=1; cpot[col]=cpot[col-1]+num[col-1];(2col a.nu) 2、快速转置 即按a中三元组次序转置,转置结果放入b中恰当位置 此法关键是要预先确定M中每一列第一个非零元在b中位置,为确定这些位置,转置前应先求得M的每一列中非零元个数 实现:设两个数组 num[col]:表示矩阵M中第col列中非零元个数 cpot[col]:指示M中第col列第一个非零元在b中位置 显然有:

  42. cpot[1]=1; cpot[col]=cpot[col-1]+num[col-1]; col 3 6 7 1 2 4 5 2 num[col] 1 0 2 2 1 0 cpot[col] 实现:设两个数组 num[col]:表示矩阵M中第col列中非零元个数 cpot[col]:指示M中第col列第一个非零元在b中位置 显然有: 5 8 9 1 3 7 8

  43. cpot[1] = 1; for (col=2; col<=M.nu; ++col) cpot[col] = cpot[col-1] + num[col-1];

  44. i j v 0 1 2 3 4 5 6 7 8 p p p p p p p p 678 1 2 12 1 3 9 3 1 -3 col 7 6 4 1 5 2 3 3 6 14 num[col] T 0 2 2 2 1 1 0 4 3 24 9 cpot[col] 8 1 5 8 3 7 5 2 18 6 1 15 6 4 -7 2 4 6 9 3 5 7 i j v 768 0 1 2 3 4 5 6 7 8 1 3 -3 1 6 15 2 1 12 2 5 18 3 1 9 3 4 24 4 6 -7 6 3 14 M

  45. Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){ 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 (t=1; t<=M.tu; ++t) ++num[M.data[t].j]; 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) { } } // if return OK; } // FastTransposeSMatrix 转置矩阵元素

  46. Col = M.data[p].j; q = cpot[col]; T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i; T.data[q].e = M.data[p].e; ++cpot[col]

  47. 分析算法FastTransposeSMatrix的时间复杂度: for (col=1; col<=M.nu; ++col) … … for (t=1; t<=M.tu; ++t) … … for (col=2; col<=M.nu; ++col) … … for (p=1; p<=M.tu; ++p) … … 时间复杂度为: O(M.nu+M.tu)

  48. 二、行逻辑联接的顺序表 三元组顺序表又称有序的双下标法,它的特点是,非零元在表中按行序有序存储,因此便于进行依行顺序处理的矩阵运算。然而,若需随机存取某一行中的非零元,则需从头开始进行查找。

  49. 修改前述的稀疏矩阵的结构定义,增加一个数据成员rpos,存放各行第一个非零元在三元组表中的位置.其值在稀疏矩阵的初始化函数中确定。修改前述的稀疏矩阵的结构定义,增加一个数据成员rpos,存放各行第一个非零元在三元组表中的位置.其值在稀疏矩阵的初始化函数中确定。 #define MAXMN 500 typedef struct { Triple data[MAXSIZE + 1]; int rpos[MAXMN + 1]; int mu, nu, tu; } RLSMatrix; // 行逻辑链接顺序表类型

More Related