You are on page 1of 35

第 11 讲

送分环节
( 1 )一个队列的入列序列为 1234 ,则出队序列是( )
A. 4321 B. 1234 C. 1432 D. 3241

( 2 )循环队列是( )
A. 不会产生下溢 B. 不会产生上溢
C. 不会产生假上溢 D. 以上都不对

( 3 )若用一个大小为 6 的数组来实现循环队列,且当前 r
ear 和 front 的值分别为 0 和 3 ,当从队列中删除一个元素
,再加入两个元素后, rear 和 front 的值分别为( )
A. 1 和 5 B. 2 和 4 C. 4 和 2 D. 5 和 1
送分环节
( 4 )以下不是串“ abcd321ABCD” 的子串是( )
A.“abcd” B.“321AB” C.“abcABC” D.“21AB”

( 5 )设串 s=“abcd” ,串 s1=“123” ,则执行插入


语句 s2=InsertStr(s,2,s1) 后, s2= ( )
A. “123abcd” B. “a123bcd”
C. “ab123cd” D. “abc123d”
答案与分析
( 1 ) B 。队列的特点是 FIFO ,怎样进就怎样出

( 2 ) C 。循环队列的优点是解决队列假上溢问题

( 3 ) B 。删除是移动 front ,插入是移动 rear 。按题意删


除一个,因此 front=3+1=4 ,插入两个,因此 rear=0+2=2 ,
因此 rear 和 front 分别是 2 和 4

( 4 ) C 。子串由主串连续若干个字符组成。

( 5 ) B 。在串 s 第 2 个位置前插入串 s1 。注意位置是从 1


开始算
上节回顾

线性表——具有相同类型的数据元素的有限序列。

将元素的类型进行扩充

(多维)数组——线性表中的数据元素可以是
广义线性表

线性表,但所有元素的类型相同。
广义表——线性表中的数据元素可以是线性表,
且元素的类型可以不相同。
上节回顾
 一维数组:本身就是一个采用顺序存储的线性表
 二维数组:

将每列或每行看成是一个元素,则二维数组是一个关于
一维数组(列向量或行向量)的线性表

 a11   a12   a1n  

]
 (a11 a12  a1n )  A1
       (a
a a a
 21   22   2 n    21 a22  a2 n )  A2
               


       
 am1   am 2   amn   ( am1 am 2  amn )  An

]
[ A1 A2 … An ]

列向量线性表 行向量线性表
推理: n 维数组可看成元素为 n-1 维数组的线性表
上节回顾
( 1 )一维数组的存储方式:顺序存储
假设数组 A 的下标范围为 [s,t] ,每个元素占 c 个字节的空间,
则任意元素 ai 的地址可计算为:
Loc(ai) = Loc(as) + (i - s)×c
c Loc(ai)

as as+1 …… ai-1 ai …… at

特殊地:
若数组为 A[0..n] ,则 LOC(i)=LOC(0)+i×c
若数组为 A[1..n] ,则 LOC(i)=LOC(1)+(i−1)×c
4.2 数组的存储结构
( 2 )二维数组的存储方式
 二维数组是非线性结构,但内存单元是一维的线性结
构,在进行顺序存储时,需要将多维关系映射为一维
的线性关系。

二维结构 一维结构
常用的映射方法有两种:
1) 按行存储。先行后列,先存储行号较小的元素,
行号相同者先存储列号较小的元素
2) 按列优先:先列后行,先存储列号较小的元素,
列号相同者先存储行号较小的元素
4.2 数组的存储结构
 按行存储 (Pascal 、 C++)
m
 a11 a12 a13 
a a23 
A[1..3,1..3]   21 a22
从首元素开始算 n  a31 a32 a33 
的元素个数

h 1 2 3 4 5 6 7 8 9
a11 a12 a13 a21 a22 a23 a31 a32 a33
h  (i  1) * m  j
Loc(aij )  Loc(a11 )  (h  1) * c

知道 h 如何得到 i 和 j ?
4.2 数组的存储结构
 按行存储 (Pascal 、 C++)
m
 a11 a12 a13 
a a23 
A[1..3,1..3]   21 a22
n  a31 a32 a33 

h 1 2 3 4 5 6 7 8 9
a11 a12 a13 a21 a22 a23 a31 a32 a33

m, h% m  0
i   h / m  j
h% m, else
4.2 数组的存储结构
 按行存储 (Pascal 、 C++)
m
 a00 a01 a02 
a a12 
A[0..2, 0..2]   10 a11
n  a20 a21 a22 

h 1 2 3 4 5 6 7 8 9
a00 a01 a02 a10 a11 a12 a20 a21 a22

h  i * m  j 1 i   (h  1) / m 
Loc(aij )  Loc(a00 )  (h  1) * c j  (h  1)% m
4.2 数组的存储结构
 按列存储 (FORTRAN)
m

 a11 a12 a13 


a a23 
A[1..3,1..3]   21 a22
n  a31 a32 a33 

h 1 2 3 4 5 6 7 8 9
a11 a21 a31 a12 a22 a32 a13 a23 a33

h  ( j  1) * n  i
Loc(aij )  Loc(a11 )  (h  1) * c
4.2 数组的存储结构
 按列存储 (FORTRAN)
m

 a11 a12 a13 


a a23 
A[1..3,1..3]   21 a22
n  a31 a32 a33 

h 1 2 3 4 5 6 7 8 9
a11 a21 a31 a12 a22 a32 a13 a23 a33

n, h% n  0
i j   h / n 
h% n, else
4.2 数组的存储结构
 按列存储 (FORTRAN)
m

 a00 a01 a02 


a a12 
A[0..2, 0..2]   10 a11
n  a20 a21 a22 

h 1 2 3 4 5 6 7 8 9
a00 a10 a20 a01 a11 a21 a02 a12 a22

h  j * n  i 1
Loc(aij )  Loc(a00 )  (h  1) * c

i  (h  1)%n j  (h  1) / n 
4.2 数组的存储结构
r-q+1
 一般形式的按行存储
 as , q as ,q 1  as , r 
a as 1,q 1  as 1,r 
i-s
A[ s..t , q..r ]   s 1, q
t-s+1
   aij  
 j-q 
 at ,q at ,q 1  at ,r 
(t-s) *(r- (t-s+1)
r- 2(r-
h 1 2 … r-q+2 r-q+3 … q+1)+1 *(r-q+1)
q+1 q+1)
as,q as,q+1 … as,r as+1,q as+1,q+1 … as+1,r … at,q at,q+1 … at,r

h  (i  s ) *(r  q  1)  ( j  q  1)
Loc(aij )  Loc(as ,t )  (h  1) * c
i  (h  1) / (r  q  1)   s j  (h  1)%(r  q  1)  q
4.2 数组的存储结构
r-q+1
 一般形式的按列存储
 as , q as ,q 1  as , r 
a as 1,q 1  as 1,r 
i-s
A[ s..t , q..r ]   s 1, q
t-s+1
   aij  
 j-q 
 at ,q at ,q 1  at ,r 
(t-s) *(r- (t-s+1)
r- 2(r-
h 1 2 … r-q+2 r-q+3 … q+1)+1 *(r-q+1)
q+1 q+1)
as,q as+1,q … at,q as,q+1 as+1,q+1 … at,q+1 … as,r as+1,r … at,r

h  ( j  q ) *(t  s  1)  (i  s  1)
Loc (aij )  Loc (as ,t )  (h  1) * c
i  (h  1)%(t  s  1)  s j  (h  1) / (t  s  1) 
4.2 数组的存储结构
多维数组的按行存储
对每一个下标,逐个变动其右边的下标(右下标先动),
或说,先排最右的下标,从右到左,最后排最左下标。

如三维数组 A[2..3,0..1,1..3] ,按行存储:


a201,a202,a203,a211,a212,a213,a301,a302,a303,a311,a312,a313

三维数组 A[1..m,1..n,1..p] ,按行存储:


LOC(i,j,k)=LOC(1,1,1)
+[(i−1)×n×p+(j−1)×p+(k−1)]×c
4.2 数组的存储结构
多维数组的按列存储
对每一个下标,逐个变动其左边的下标(左下标先动),
或说,先排最左的下标,从左向右,最后排最右下标。

如三维数组 A[2..3,0..1,1..3] ,按列存储:


a201,a301,a211,a311,a202,a302,a212,a312,a203,a303,a213,a313

三维数组 A[1..m,1..n,1..p] ,按列存储:


LOC(i,j,k)=LOC(1,1,1)
+[(k−1)×m×n+(j−1)×m+(i−1)]×c
数组元素的地址都是其下标的线性函数,任一元素都可在相同的
(逻辑)时间内存取,故数组是一种随机存取结构。
下面描述默认首元
4.3 矩阵压缩存储 素下标为 1 , 1

 对于某性特殊矩阵(数据具有对称性;有一个数重复
较多;只有很少元素非零),不需要全部数据都进行
存储,可进行压缩存储
1 2 3 4 1 2 3 4 1 0 0 0
2 5 6 7  0 5 6 7  2 5 0 0 
  
3 6 8 9 0 0 8 9 3 6 8 0
     
4 7 9 10  0 0 0 0 4 7 9 10 
对称矩阵 上三角矩阵 下三角矩阵

1 0 3 0 1 2 00
0 5 0 0  3 5 4 0 
 
0 0 0 9 0 8 7 6
   
0 0 9 0 0 0 10 9 
稀疏矩阵 对角矩阵
4.3.1 特殊矩阵
( 1 )对称矩阵: n 阶方阵 A[n][n] ,满足 aij=aji

1 2 3 4
2 5 6 7 
 有用信息
3 6 8 9
  只有一半
4 7 9 10 

压缩策略:只存三角部分数据
( 1 )按行存储下三角
( 2 )按行存储上三角
( 3 )按列存储下三角
( 4 )按列存储上三角
4.3.1 特殊矩阵
( 1 )对称矩阵: n 阶方阵 A[n][n] ,满足 aij=aji
1 
2 5 
 
3 6 8 
 
 4 7 9 10 

h 1 2 3 4 5 6 7 8 9 10
1 2 5 3 6 8 4 7 9 10
i (i  1)
h  [1  2    (i  1)]  j   j, i  j
2
Loc(aij )  Loc (a11 )  (h  1) * c
4.3.1 特殊矩阵
( 1 )对称矩阵: n 阶方阵 A[n][n] ,满足 aij=aji
1 
2 5 
 
 3 ai , j 8 
 
4 7 9 10 
同一行的第一个 同一行的最后一
由于 1≤j≤i ,所以 元素 个元素
i(i−1)/2+1 ≤ h ≤ i(i−1)/2+i = i(i+1)/2
即 i2−i−2k+2≤0 且 i2+i−2k≥0 ,解该不等式组,得
1 8h 1 1 8h  8 1 1 8h 1 1 8h 1
i    1
2 2 2 2
求出 i 后便可得 j=h−i(i−1)/2
4.3.1 特殊矩阵
( 2 )三角矩阵
下三角(上三角)矩阵:矩阵 A[n][n] 主对线上方(或
下方)的元素全部相同,均为常数 c 。多数情况下,常
数 c 为零。
1 c c c 1 2 3 4
2 5 c c  c 5 6 7 
 
3 6 8 c c c 8 9
   
4 7 9 10  c c c c
下三角矩阵 上三角矩阵

压缩策略:与对称矩阵类似,只是在最后一个单元中保
存重复的元素 c
4.3.1 特殊矩阵
( 2 )三角矩阵
下三角矩阵的按行存储方式:

1 c c c 
 [1  2    (i  1)]  j 
i (i  1)
 j, i  j
2 5 c c  h
n(n  1)
2

 
 2
1 i j
3 6 8 c Loc(aij )  Loc (a11 )  (h  1) * c
 
4 7 9 10 

h 1 2 3 4 5 6 7 8 9 10 11
1 2 5 3 6 8 4 7 9 10 c
4.3.1 特殊矩阵
( 3 )对角矩阵
除了主对角线及其邻近的上下若干条次对角线上的元素
外,其余元素皆为零。非零元素集中在以主对角线为中
心的带状区域中,是带状矩阵中的一种。
a 11 a 12 0  0 0 
a a 22 a 23  0 0  首行和末行非
 21 零元素个数较
0 a 32 a 33 a 34 0 0 
A n n   其它行少 1
       
0 0 0 a n 1, n 2 a n 1,n 1 a n 1,n 
 
 0 0 0 0 a n, n 1 a n,n 

压缩策略:将对角矩阵首、末行各补一个虚元素,则每
行的非零元素个数都相同,可压缩到二维数组 Bn×w 中
( w 为带宽)
4.3.1 特殊矩阵
( 3 )对角矩阵 W=3

 a11 a12 x  0 0   x a 11 a 12 
a 0   a a 23 
 21 a 22 a 23  0  21 a 22
 0 a 32 a 33 a 34 0 0   a 32 a 33 a 34 
A nn  B n3  
     
       
a n 1, n  2 a n 1, n 1 a n 1,n 
0 0 0 a n 1,n  2 a n 1,n 1 a n 1,n   
   a n, n 1 a n, n x 
 0 0 0 x a n,n 1 a n,n 

 iB  i A
 1  i,j  n
 jB  jA  i A  2
4.3.2 稀疏矩阵
为节省存储单元,只存非零元。非零元分布一般没有规律,存
储次序无法反映逻辑关系,必须显式存储行列逻辑次序。
1 0 3 0
0 5 0 0 

0 0 0 9
 
0 0 9 0
压缩策略:
( 1 )三元组:将非零元的值和行号、列号作为一个结点存放
( 2 )十字链表:每个结点存放三元组、行、列指针
( 3 )行链表:每行的非零元做成链表
4.3.2 稀疏矩阵
( 1 )三元组
 三元组按行序(或列序)排列的顺序存储结构
 三元组表是稀疏矩阵的一种顺序存储结构。

const int maxsize=100; // 三元组表的容量


typedef struct {
int i,j; // 行号、列号
datatype val; // 元素值
} nodetype; // 三元组结点类型
typedef struct {
int m,n; // 行数、列数
int t; // 当前表长,非零元素个数
nodetype data[maxsize];// 三元组表
} spmatrix; // 稀疏矩阵类型
4.3.2 稀疏矩阵
( 1 )三元组

m n t
1 0 3 0
1 1 1
0 5 0 0 
 1 3 3
0 0 0 9
  2 2 5
0 0 9 0
3 4 9
4 3 9
4.3.2 稀疏矩阵
( 1 )三元组
 利用三元组实现数组转置:交换 m,n 位置

1 0 3 0 1 0 0 9
0 5 0 0  0 5 0 0 
 转置 
0 0 0 9 3 0 0 0
   
9 0 0 0 0 0 9 0
m n t m n t
1 1 1 1 1 1
1 3 3 3 1 3
2 2 5 交换 m,n 2 2 5
3 4 9 4 3 9
4 1 9 1 4 9
4.3.2 稀疏矩阵
( 1 )三元组
 利用三元组实现数组转置:交换 m,n 位置

1 0 3 0 1 0 0 9
0 5 0 0  0 5 0 0 
 转置 
0 0 0 9 3 0 0 0
   
9 0 0 0 0 0 9 0
m n t m n t
1 1 1 1 1 1
按m
1 3 3 1 4 9
排序
2 2 5 交换 m,n 2 2 5
3 4 9 3 1 3
4 1 9 4 3 9
4.3.2 稀疏矩阵
( 2 )十字链表
三元组表是一种顺序存储方法,对插入和删除运算是
不合适的,因为会引起大量结点的移动,此时采用链式
存储结构就比较合适。

链式存储结构
每个结点存放三元组、行、列指针:
 行指针指向本行的下一个非零元,组成行链表;
 列指针指向本列的下一个非零元,组成列链表。

每个元素 aij 既是第 i 行链表上的结点,又是第 j 列


链表上的结点,就好像处在一个十字路口上 。
4.3.2 稀疏矩阵
( 2 )十字链表
 行链表、列链表都设头结点;并组成带头结点的循环
链表。
 行链表和列链表共享表头结点。
 表头结点组成链表(通过值域 val 链接)。
 表头结点链表设头结点 *H ;并组成带头结点的循环链
表。
 *H 是整个十字链表的表头结点。
*H H1 H2 H3 H4 H5
H 4 5 6

H1 1 1 7 1 4 8

H2 2 5 1

H3 3 2 -5 3 4 2

H4 4 5 -1

7 0 0 8 0
H5 0 0 0 0 1 
A 45 
0  5 0 2 0
 
• 多重链表结构。 0 0 0 0  1
• 3 种结点:总表头结点、行(列)表头结点、非零元结点;
• 3 种循环链表:表头结点循环链表,行循环链表和列循环链表。
7 0 0 8 0
4.3.2 稀疏矩阵 
0 0 0 0 1

A 45  
( 3 )行链表 0  5 0 2 0
 每行的非零元做成链表
 
0 0 0 0  1

1 1 7 1 4 8 ∧

2 5 1 ∧
12345

3 2 -5 3 4 2 ∧
4 5 -1 ∧

• 找同一列上的非零元不方便。
• 类似,可建列链表;找列元素方便,找行元素不方便。

You might also like