数据结构之串,数组,矩阵

一 串

1.1 串的定义

串是有限序列的线性表,元素是字符构成,记为s = `a1a2a3....an`,其中s串名,单引号括起来的是串值.

1.2 串的存储结构

(1)顺序存储

串的顺序存储是指一组连续存储单元来存储串值的字符串序列,由于串值为字符,所以可以通过程序语言字符数组定义串的存储空间,也可以通过串长的需要动态申请字符串空间.
c程序演练顺序串的基本操作如 串初始化,复制,拷贝,求子串,KMP算法等

#define STRINGMAXSIZE 2

typedef struct{
// 存储空间固定
// char str[STRINGMAXSIZE];
char *str;
int length;
}SString;

// 初始化串
SString initString(){
SString s;
// 预空间存储大小
s.str =(char *) malloc(sizeof(char) *STRINGMAXSIZE);
s.length = 0;
return s;
}

// 动态增加串的长度
void increaseSize(SString  *s,int len){

char *p = s->str;
s->str =  (char *)malloc(sizeof(char *) *STRINGMAXSIZE + len);

// 需要将原来的值copy过来 开销比较大
for(int i = 0; i < s ->length;i++){
  s->str[i] = p[i];

}
s->length += len;
free(p);

}

// 赋值
void assginElem(SString *s,char addStr[] ){

int i = 0;

while(addStr[i]){
  if(i > s->length) increaseSize(s,1);

  // s->str[++s->length] = addStr[i];
    s->str[i] = addStr[i];
    ++s->length;
     i++;
}
}

// 拷贝
void copyElem(SString *s,SString copyStr){
// 调整内存
 if( s->length <  copyStr.length){

     s->str = (char *)realloc(s->str,copyStr.length *sizeof(char));
 }

  s->length = copyStr.length;

  for(int i = 0; i < copyStr.length;i++){

     s->str[i] = copyStr.str[i];

  }

}

// 查找子串 KMP 算法 复杂度 0(m + n)
// 返回子串在串的第pos个字符的后 如果没有则返回0
int KMPindex(SString *s ,SString *t ,int pos){
// abcdef  f3
if(t ->length <= 0 || pos < 0 || pos > s->length - 1 || s->length < 0) return 0;
int i = pos;
int j = 0;
 
//    printf("111i == %d %c\n",i,s->str[2]);
//    printf("1111j == %d %c\n",j,t->str[2]);

while(i < s->length && j < t->length){
    printf("i == %d %c\n",i,s->str[i]);
    printf("j == %d %c\n",j,t->str[j]);
    if(s->str[i] == t->str[j]){
        i++;
        j++;
       // printf("%s","执行\n");
    }else{
       i =  i - j  + 1;
       j = 0;
     //.printf("%s","执行0000\n");
    }

}
 
 
//printf("j ==%d\n",j);

if(j >= t->length){
   return i - t->length;
}

return 0;

}

int main(int argc,char *argv[]){

SString str =  initString();

char copyStr[]  = "abcdefcopy_indem11111";

assginElem(&str,copyStr);

printf("str长度=====%d\n",str.length);
 


SString str1 = initString();
 
//char copyStr2[]  = "copy_indem111";

assginElem(&str1,"copy_indem111");

//copyElem(&str,str1);

printf("copy后的str长度=====%d\n",str1.length);
 
printf("str1子串在str串的第%d位置后全部匹配\n",KMPindex(&str,&str1,0));

return 0;
}
(2)链式存储

串也可以使用链式存储,每个结点可以存储一个字符,也可以存储多个字符,注意链表结点大小的会影响链表存储的执行效率.

typedef struct node{

  char ch;

  node *next;


} Node, *LinkStr;

// 初始化链串
LinkStr creatLinkString(){

   node *nodeStr;

   nodeStr = (Node *)malloc(sizeof(Node));

   if(!nodeStr){
     nodeStr ->next = NULL;
   }
   
  return nodeStr;
}

二 多维数组

二维码数组A[M][N],可以看成一个线性表,它的每个元素也是一个线性表.
多维数组A[b1,b2, .... bn],设其每其没每一维的下界为1,bi是第i维的上界,从数据结构的逻辑上看,A中的每个元素都被n个关系所约束,这些关系是线性的,每个关系中,除了第一个关系和最后一个关系,其余关系都有一个直接前驱和一个直接后驱;一般来说数组不做删除和插入操作,比较适合顺序存储.

设L表示每个数组元素占用的存储单元数目,m和n表示数组的行数和列数,那么以行为主序存储数组元素地址的计算公式为:
Loc(aij) = Loc(a11) + ((i - 1) * n + (j - 1))*L
同理按照列为主序存储数组元素地址的计算公式为:
Loc(ij) = Loc(a11) + ((j - 1) *m + (i- 1))*L
注意数组下标从1 开始.

三 矩阵

矩阵在很多科学与工程运算都有广泛的应用;在一些矩阵中有许多相同的元素和零元素,为了节省空间,对矩阵进行压缩存储,压缩存储的意义是多个相同的元素只分配一个存储单元,零元素不分配存储空间.

3.1 特殊矩阵

矩阵元素分布存在一定的规律,常见的特殊矩阵有对称矩阵,三角矩阵,多角矩阵等,由于它的元素存在一定的规律,可以将其压缩在一个一维数组中,建立特殊矩阵起每个非零元素和一维数组中位置的对应关系.
An x n元素具有aij = aji特点,i >= 1 j <= n 则称为n阶对称矩阵.
如果对称矩阵的每一对元素分配存储单元,可以将n^2的元素压缩存储到能存放n*(n+1)/2存储空间中,如果以行存储Anxn,对称矩阵的元素aij 和 一维数组B[K](0<= K< n*(n+1)/2),存在一一对应关系:
当i >=j 时 k = i(i -1)/2 + j - 1
当 i < j 时 k = j(j -1)/2 + i -1
注意数组下标从0开始,矩阵的ij从1开始

对角矩阵: 非0元素集中以主对角线为中心的带状区域


对角矩阵.png

特点: 1 第一行和最后一行有2个非零元素,2-(n-2)有3个非0元素
2 使用一维数组存储,元素被压缩到3*n -2存储空间中.
3 数组下标K和A[i][j]的关系是k= 2*i + j (i >= 0 0<= j < n) (按行存储) 如果 i >= 1 ,j <=n k = 2*i+j -3

3.2 稀疏矩阵

系数矩阵非零元素没有规律,对于稀疏矩阵的非0元素存储必须存储其位置(即行号和列号),所以使用三元组(i,j,aij)唯一确定稀疏矩阵的一个元素.

稀疏矩阵.png

上图稀疏矩阵,其三元组表为(1,2,12),(1,3,9),(3,1,-3),(3,6,14),(4,3,24),(5,2,18),(6,1,15),(6,4,-7)

你可能感兴趣的:(数据结构之串,数组,矩阵)