串,数组和广义表 

53 阅读2分钟

  • 串的基本操作

1.串的结构

typedef struct
{
    char *data;
	int length;
}String;

2.给串赋值:StrAssign(&T,chars):赋值操作。把串T赋值为chars。

bool StrAssign(String *S,char *t)
{
	int len=strlen(t);
    if(S==NULL||len==0)return false;
    
	for(int i=0;i<len;i++)
	    S->data[i]=t[i];
	S->length=len;
	return true;
}

3.串的复制   StrCopy(&T,S):复制操作。由串S复制得到串T。

bool StrCopy(String *T,String S)
{
   if(T==NULL)return false;
   T->data=S.data;
   T->length=S.length;
   return true;
}
 

4.求串长  StrLength(S):求串长。返回串S的元素个数。

int StrLength(String S)
{
   return S.length;
}
 

5.串的插入  在串str1的pos位置插入串str2

SString strInsert(SString str1,int pos,SString str2)
{
      if(pos<1||pos>str1->length)
      {
             printf("插入位置错误!\n");
             exit(0);
      }
      int i;
      for(i=pos;i<=str1->length;i++)
      {
            str1->ch[i+str2->length]=str1->ch[i];
      }
      for(i=1;i<=str2->length;i++)
      {
            str1->ch[i+pos-1]=str2->ch[i];
      }
      str1->length=str2->length+str1->length;
      return str1;
}

6.串的删除  删除指定位置的字符

SString strDelete(SString str,int pos,int len)
{
      if(pos<1||pos>str->length||len+pos-1>str->length)
      {
             printf("删除位置错误!\n");
             exit(0);
      }
 
      int i;
      for(i=pos+len;i<=str->length;i++)
      {
 
            str->ch[i-len]=str->ch[i];
      }
      str->length=str->length-len;
      return str;
 
}

7.串的比较

 
Status StrCmp(HString S,HString T)
{
	int i;
	for(i=0;i<S.length&&i<T.length;i++)
	{
		if(S.ch[i]!=T.ch[i])
			return S.ch[i]-T.ch[i];
	}
	return 0;
}

8.串的连接     串拼接,将S1,S2拼接后用T返回

 
Status Concat(HString &T,HString S1,HString S2)
{
	int i;
	InitString(T);
	T.length=S1.length+S2.length;
	T.ch=(char*)malloc(T.length*sizeof(char));
	if(!T.ch)
		exit(overflow);
		
	for(i=0;i<S1.length;i++)
		T.ch[i]=S1.ch[i];
	for(i=0;i<S2.length;i++)
		T.ch[S1.length+i]=S2.ch[i];
		
	return ok;
}
  • 子串

长度为n的字符串:

                     1.子串:n(n+1)/2+1

                     2.非空子串与真子串:n(n+1)/2

                     3.非空真子串:n(n+1)/2-1

广义表

广义表的长度

  • 广义表的长度就是广义表中第一层的元素个数。
  • 例如:(a,(b,c,d))的长度:因为包含一个原子a与一个字表(b,c,d),所以长度 = 2。
  • 例如:((a,(a,b),((a,b),c)))的长度:因为只包含一个字表(a,(a,b),((a,b),c)),所以长度 = 1。

广义表的深度

  • 广义表的深度就是广义表中最大的嵌套次数

例如:((a,(a,b),((a,b),c)))的深度:
第一层:(a,(a,b),((a,b),c))
第二层:a,(a,b),((a,b),c)
第三层:(a,b),c
第四层:a,b。
所以深度 = 4。

矩阵的压缩存储

1、【2016统考真题】有一个 100 阶的三对角矩阵 M,其元素 (1i, j100)按行优先依次压缩存入标从 0 开始的一维数组中 N。元素  在 N 中的下标是(    BA.  86                         B. 87                         C. 88                         D. 89
解:三对角矩阵 A 如下所示:

(在三对角矩阵中,所有非零元素都集中在以主对角线为中心的 3 条对角线的区域,其他区域的元素都为零。)



采用压缩存储,将 3 条对角线上的元素,按行优先方式存放在一维数组 B 中,且  存放于 B[0]中,其存储形式如下所示:



可以计算矩阵 A3 条对角线上的元素 (1i, j100, |i - j| <= 1)在一维数组 B 中存放的下标为 k = 2i + j - 3。(下标从 0 开始)

解法一:针对该题,仅需将数字逐一代入公式: k = 2 x 30 + 30 - 3 = 87,结果为87。
解法二:观察上图的三对角矩阵不难发现,第一行有两个元素,剩下的在元素  所在行之
前的 28 行(注意下标 1ij100)中,每行都有 3 个元素,而  之前仅有一个元素 , 不难发现元素  在数组 N 中的下标是 2 + 28x3 + 2 - 1 = 87。

(解法二中,减一是因为一维数组 B 的下标是从 0 开始。)

2、将三对角矩阵 A[1..100] 按行优先存入一维数组 B[1..298] 中,A 中元素 A[66][65] 在数组B 中的位置 k 为( B ) A. 198 B. 195 C.197 D.196 解:一维数组 B[k] 的下标是从 1 开始。由公式 k = 2i + j - 2,得 k = 2*66 + 65 - 2 = 195。

【另】反过来推导:已知 k 为 195 , 求 i , j:

1、若将 n 阶上三角矩阵 A 按列优先级压缩存放在一维数组 B[1...n(n+1)/2+1] 中, 则存放到B[k] 中的非零元素  (1i, j ≤ n) 的下标 i, j 与 k 的对应关系是(    C   )。
A. i ( i + 1 ) / 2 + j
B. i ( i - 1 ) / 2 + j - 1
C. j ( j - 1 ) / 2 + i
D. j ( j - 1 ) / 2 + i - 1
解:按列优先存储,故元素 a_{i,j} 前面有 j - 1 列,

共有 1 + 2 + 3 + ... +j -1 = j ( j - 1 ) / 2 个元素,元素 a_{i,j} 在第 j 列上是第 i 个元素,

数组 B 的下标是从 1 开始,因此 k = j ( j - 1 ) / 2 + i

2、若将 n 阶下三角矩阵 A 按列优先顺序压缩存放在一维数组 B[1...n(n+1)/2+1] 中,则存放到 B[k] 中的非零元素 (1 ≤ i, j ≤ n) 的下标 i, j 与 k 的对应关系是( B )。 A. (j - 1) (2n - j + 1) / 2 + i - j B. (j - 1) (2n - j + 2) / 2 + i - j + 1 C. (j - 1) (2n - j + 2) / 2 + i - j D. (j - 1) (2n - j + 1) / 2 + i - j + 1 解:按列优先存储,故元素 之前有 j - 1 列,

共有 n + (n - 1) + ... + (n - j + 2) = (j-1)(2n - j + 2) / 2 个元素,

元素 是第 j 列上第 i - j + 1 个元素,

数组 B 下标从 1 开始,k = (j - 1) (2n - j + 2) / 2 + i - j + 1。

3、【2018统考真题】设有一个 12*12 对称矩阵 M 的上三角部分的元素  (1i ≤ j ≤ 10) 按行优先存入 C 语言的一维数组 N 中, 元素  在 N 中的下标是(     A     )。
A. 50                            B. 51                        C. 55                            D. 66
解: 在 C 语言中,数组 N 的下标从 0 开始。

第一个元素  对应存入 ,矩阵 M 的第一行有 12 元素,第二行有 11 个,第三行有 10 个,第四行有 9 个,第五行有 8 个,所以  是第 12 + 11 + 10 + 9 + 8 + 1 = 51 个元素。

下标应为 50

4、【2020统考真题】将一个10*10 对称矩阵 M 的上三角部分的元素 (1 ≤ i ≤ j ≤ 12) 按列优先存入 C 语言的一维数组 N 中, 元素 在 N 中的下标是( C )。 A. 15 B. 16 C. 22 D. 23 解: 因为是对称矩阵,要求元素 在 N 中的下标,即求元素 在 N 中的下标。

在 C 语言中,数组 N 的下标从 0 开始。

上三角矩阵按列优先存储,先存储只有 1 个元素的第一列, 再存储有 2 个元素的第二列,以此类推。在 之前存有 第 1 列: 1

第 2 列: 2

....

第 6 列: 6

第 7 列: 1

前面共存储有 1 + 2 + 3 + 4 + 5 + 6 + 1 = 22 个元素 ( 数组下标范围为0 ~ 21 ),注意数组下标从 0 开始,故 在数组N中的下标为 22,即 在数组 N 中的下标为 22。

1、【2017统考真题】适用于压缩存储稀疏矩阵的两种存储结构是(     A     )。
A. 三元组表和十字链表                         B. 三元组表和邻接矩阵
C. 十字链表和二叉链表                         D. 邻接矩阵和十字链表
解:稀疏矩阵:矩阵中非零元素的个数 t,相对矩阵元素的个数 s 来说非常少,即 s >> t 的矩阵。

(1)非零元素及其相应的行和列构成个三元组(行标,列标,值),即三元组表的结点存储了行 row、列 col、值 value 三种信息,是主要用来存储稀疏矩阵的一种数据结构。

(2)十字链表将行单链表和列单链表结合起来存储稀疏矩阵。邻接矩阵空间复杂度达 ,不适合于存储稀疏矩阵。

(3)二叉链表又名左孩子右兄弟表示法,可用于表示树或森林。

所以,A正确。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天,点击查看活动详情