一 串
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元素集中以主对角线为中心的带状区域
特点: 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)唯一确定稀疏矩阵的一个元素.
上图稀疏矩阵,其三元组表为(1,2,12),(1,3,9),(3,1,-3),(3,6,14),(4,3,24),(5,2,18),(6,1,15),(6,4,-7)