1 / 38

DATA STRUCTURE

DATA STRUCTURE. 第 5 章 数组和广义表. 第 5 章 数组和广义表. 前述线性结构 其中的数据元素是非结构的原子类型 (值不可分解) 数组、广义表 是线性表的扩展: 数据元素本身也是一种数据结构 ( 线性表 ). §1 数组的定义和操作. 数组是所有程序设计语言都设定的固有类型 数组的基本概念和运算已在 C 程序设计中熟悉 从数据结构的观点讨论 ●逻辑结构 ●存储方式. 一、逻辑结构. 以二维数组为例

shaina
Download Presentation

DATA STRUCTURE

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. DATA STRUCTURE 第5章 数组和广义表

  2. 第5章 数组和广义表 • 前述线性结构 其中的数据元素是非结构的原子类型 (值不可分解) • 数组、广义表 是线性表的扩展: 数据元素本身也是一种数据结构(线性表)

  3. §1 数组的定义和操作 • 数组是所有程序设计语言都设定的固有类型 • 数组的基本概念和运算已在C 程序设计中熟悉 • 从数据结构的观点讨论 ●逻辑结构 ●存储方式

  4. 一、逻辑结构 以二维数组为例 1. 形式表示:2_Array=( D,R) 其中D={ aij | i =1…m, j =1…n, aij∈D0} integer 某数据对象 R={ROW,COL} ROW={<aij,ai,j+1>|1≤i≤m, 1≤j≤n-1,aij,ai,j+1∈D} COL={<aij,ai+1,j>|1≤i≤m-1, 1≤j≤n, aij,ai+1,j∈D} 共有 m×n个数据元素

  5. 一、逻辑结构 2.每个元素受两个关系ROW(行关系)和COL(列关系)的约束。 即每个元素有两个前趋元素和两个后继元素。 数据元素 一组下标(i, j) 3.(1,m ),(1,n) 分别为下标 i,j的一对界偶(上、下界)。 4.上述定义可推广到n 维数组

  6. 二、数组的特点 1. 数据元素个数固定 2. 数据元素属同一种数据类型 3. 二维数组是多个线性表组成的线性表 C中二维数组类型说明: typedef ElemType array2[m][n]; 或: typedef ElemType array1[n]; typedef array1 array2[m];

  7. 3. 二维数组是多个线性表组成的线性表 例如: A= • 则A=(α1α2 … αn) 其中: αj= (1≤j≤n) 或A= ,其中:

  8. 三、数组的操作 • 通常只有三种操作: 存、取元素值和给元素赋值

  9. §2 数组的存储结构 • 顺序存储结构 数组一旦建立,则元素个数和元素间关系不变动,故采用顺序存储结构。 • 用一维存储单元存储二维数组 两种方式: · 以列序为主序 (column major order) · 以行序为主序 (row major order)

  10. §2 数组的存储结构 1、确定维数及各维界偶,便可分配存储空间 2、给定一组下标,可求相应数组元素存储位置 LOC[i,j]=LOC[1,1] + [ n (i-1) + (j-1) ] l 基地址 按行为主 C语言:LOC(i,j)=LOC(0,0) + ( n  i + j ) l 随机存储结构:存取任一元素时间相等。 每个元素所占存储单元

  11. n维数组元素存储位置的计算公式: LOC(j1,j2,…,jn)=LOC(0,0,…,0)+(b2 …bn j1+b3 … bn j2+…+bn jn-1+jn) l

  12. §3 矩阵的压缩存储 • 矩阵是工程计算中研究的主要对象。 • 一般情况: 用二维数组来存储矩阵。 特殊矩阵: 对称、三角、对角 • 特殊情况 稀疏矩阵:非零元素个数<<零元素个数 多个值相同的元素,分配同一存储单元 • 压缩存储 零元素不存储

  13. 一、特殊矩阵 1.对称矩阵 (1)定义: 若Ann满足aij=aji(1≤i, j≤n)则称A为n阶对称矩阵。

  14. (2) 压缩存储 共n2个元,只需存储个 元, 以行为主序存储下三角中的元素 用一维数组 s[0 .. -1]存储对称矩阵A a11 a21 a22 a31 … an1 … ann k= 0 1 2 3 s[k]与aij一一对应, k与( i , j )的对应关系?

  15. k与( i, j )的对应关系: 当i≥j k= 0≤k≤ 当i<j

  16. 2.三角矩阵 (1)定义: 上(下)三角矩阵指矩阵的下(上)三角(不包括对角线)中的元均为0的n阶矩阵。 (2)压缩存储: 只存储上(下)三角中的元。 k与 (i, j) 的对应关系: k = ? 1≤ i ≤ j ≤n

  17. 二、稀疏矩阵(sparse matrix) ●条件:m*n 阶矩阵 ⑴非零元素个数<<零元素个数 ⑵非零元素在矩阵中分布无规律 ●压缩存储:只存储非零元素 三元组表 十字链表

  18. (一)三元组表 1.示例: 三元组( i, j, aij ) 以行序为主序 三元组表 ⑴ a.data i j v 0 1 1 2 12 2 1 3 9 3 3 1 -3 4 3 6 14 5 4 3 24 6 5 2 18 7 6 1 15 8 6 4 -7 ⑵a.mu a.nu a.tu 6 7 8

  19. 2.三元组表类型定义 #define Maxn <非零元素个数的最大值> typedef struct { int i, j; /* 非零元素行、列号 */ ElemType v; /* 元素值 */ }Triple; typedef struct { Triple data[Maxn+1]; /*三元组表,data[0]不用 */ int mu,nu, tu; /*矩阵的行、列数和非零元个数 */ }TSMatrix;

  20. 3.求转置矩阵——最简单的矩阵运算

  21. 求转置矩阵算法 TransposeSMatrix (TSMatrix a, TSMatrix *b) { b->mu=a.nu; b->nu=a.mu; b->tu=a.tu; if( a.tu) { q=1; /*指向b中三元组序号*/ for(col=1; col<=a.nu; ++col)/*按a的列序扫描a a.nu遍*/ for( p=1; p<=a.tu; ++p) /*p指向a中三元组序号*/ if(a.data[p].j==col) { b->data[q].i=a.data[p].j; /*置换*/ b->data[q].j=a.data[p].i; b->data[q].v=a.data[p].v; q++; } } } 算法思想 按b中三元组次序在a中找到相应三元组进行转置 若第p个三元组中列号j为所寻列号

  22. 转置算法时间复杂度分析 ●时间复杂度: T(n)=O(nt) 当 t 与 mn 同数量级时,为 O (mn2) ●一般矩阵的转置算法: for( col=1; col<=n; ++col) for(row=1; row<=m; ++row) B[col][row]=A[row][col]; 其 T (n)=O(m*n) 故本算法仅适合于 t<<m*n的情形。

  23. 快速转置 A中第col列第一个非零元素在b中的恰当位置(序号) 按照A中三元组的次序进行转置, 并将转置后的三元组置入b中恰当的位置。 附设两个一维数组: num[col] 和 pot[col] 显然有:pot[1] = 1 pot[col] = pot[col-1] + num[col-1] 2≤col≤n 例: 矩阵A的pot值 col 1 2 3 4 5 6 7 num[col] 2 2 2 1 0 1 0 pot[col] 1 3 5 7 8 8 9 A中第col列中非零元素个数

  24. 快速转置算法Fast_TransposeSMatrix (TSMatrix a, TSMatrix *b) { b->mu=a.nu; b->nu=a.mu; b->tu=a.tu; if( a.tu) { for(col=1; col<=a.nu; col++) num[col]=0; /*初始化*/ for( p=1; p<=a.tu;p++) /*求A中每一列含非零元素个数*/ num[a.data[p].j]++; pot[1]=1; /*统计第col 列第一个非零元素在b中的序号*/ for(col=2;col<=a.nu;col++) pot[col]=pot[col-1]+num[col-1]; for( p=1; p<=a.tu; p++) /*转置*/ { col=a.data[p].j; q=pot[col]; b->data[q].i=a.data[p].j; b->data[q].j=a.data[p].i; b->data[q].v=a.data[p].v; pot[col]++; } } }

  25. 算法分析: 算法2比算法1多用两个辅助向量; 算法2采用4个并列单循环,循环次数分别为n和t; 故T(n)=O(n+t),当t与mn同级时,为O(mn)与经典算法同。

  26. (二)十字链表 • 适用于稀疏矩阵中非零元的个数及位置变动频繁的运算(如矩阵加法)。

  27. 十字链表的类型说明: typedef struct OLnode /*非零元素结点*/ { int i,j; Elemtype v; struct lnode *right, *down; }OLnode; Typedef struct /*表头结点*/ { Olnode *rhead[MAX], *chead[MAX]; int mu,nu,tu; }

  28. §4 广义表 • 线性表的推广,又称列表(Lists)。 • 广泛用于人工智能领域的表处理语言(LISP语言), LISP把广义表作为基本数据结构,其程序也表示为一系列广义表。

  29. 一、广义表的定义 1、定义 广义表是n(n≥0)个元素的有限序列,记作: LS=(d1,d2,…,dn) 其中: LS是广义表(d1,d2,…,dn)的名称 n是广义表的长度 di (1≤i≤n)是广义表的数据元素 单元素(原子):若di是单个元素 di 子表:若di是广义表

  30. 2、表头与表尾 ● head 当LS非空时(n>0),第一个元素d1称为表头( head ) ● tail 去除表头元素后,其余元素组成的表(d2,…,dn)称为LS的表尾 (tail);

  31. 3、例 长度 head tail A=(a) 1 a () B=(a,(x,y)) 2 a ((x,y)) C=(A,B,()) 3 A (B,()) D=(a,D)=(a, (a,…)) 2 a (D) E=() 0 F=(E)=(()) 1 E () ef. () 空表,长度为 0 (())长度为1,可分解为表头、表尾皆为空表()

  32. 4、三个结论 (1)广义表可为其它广义表所共享。 如上例中,子表A,B与C共享数据。 (2)广义表可以是一个递归的表, 即广义表可以是其自身的一个子表。如上述中D就是一个递归的表。 (3)广义表是一个多层次的表, 可用图形表示,如广义表C的图形表示如下:

  33. 广义表C的图形表示: 概念: • 层次 • 广义表的深度:最大层次数,如C的深度为3 A=(a) B=(a,(x,y)) C=(A,B,())

  34. 二、广义表的存储结构 采用链表存储结构 其中:tag为标志域, tag=0为原子结点; tag=1为表结点。 sublist为指向子表的指针域; value 域存储结点的值; link 域指向下一数据元素的结点。

  35. 例: A=(a) , B=(a,(x,y)),C=(A,B,())

  36. D=(a,D)=(a, (a,…)) E=() F=(E)=(()) 从链表中,可以很方便地看出表的长度和深度。 在链表中,广义表各元素间的次序关系被表示得更为清晰。 例 横向箭头表示元素间的次序,竖向箭头表示元素间的层次关系。

More Related