字符串
目录
字符串的存储及其实现
字符串是一种特殊的线性表,由于链式表有顺序存储和链式存储两大数据结构,所以字符串也有顺序串和链式串
顺序串:
顺序串的结构表示:
#define MAXSIZE 100
typedef struct
{
char str[MAXSIZE];
int length;
}seqstring;
顺序串的插入
void strinsert(seqstring *S ,int i ,seqstring T)
{
int k;
if (i<1 || i>S->length+1 || S->length + T.length>MAXSIZE-1)
printf("不能进行插入操作\n");
else
{
for (k=S->length-1;k>=i-1;k--)
S->str[T.length+k]=S->str[k];
for (k=0;k<T.length;k++)
S->str[i+k-1]=T.str[k];
S->length=S->length + T.length;
S->str[S->length]='\0';
}
}
顺序串的删除:
void strdelete(seqstring *S,int i,int len)
{
int k;
if(i <1 || i >S->length || i+len-1>S->length)
printf("不能进行插入操作/n");
else
{
for (k=i+len-1;k<S->length;k++)
S->str[k-len]=S->str[k];
S->length=S->length-len;
S->str[S->length]='\0';
}
}
连结运算:
seqstring * strconcat(seqstring S1,seqstring S2)
{
int i;
seqstring *r;
if(S1.length+S2.length>MAXSIZE-1)
{
printf("不能连接\n");
return NULL;
}
else
{
r=(seqstring*)malloc(sizeof(seqstring));
for (i=0;i<S1.length;i++)
r->str[i]=S1.str[i];
for (i=0;i<S2.length;i++)
r->str[S1.length+i]=S2.str[i];
r->length=S1.length+S2.length;
r->str[r->length]='\0';
}
return r;
}
求给定顺序串的子串
seqstring *substring (seqstring S ,int i ,int len)
{
int k;
seqstring *r;
if(i<1 || i>S.length || i+len-1>S.length)
{
printf("error!\n");
return NULL;
}
else
{
r=(seqstring*)malloc(sizeof(seqstring));
for (k=0;k<len;k++)
r->str[k]=S.str[i+k-1];
r->length=len;
r->str[r->length]='\0';
}
return r;
}
串的链式存储及其实现:
void strcreate (linkstring *S)
{
char ch;
linkstrnode *p ,*r;
*S=NULL;
r=NULL;
while((ch=getchar())!='\n')
{
p=(linkstrnode *)malloc(sizeof(linkstrnode));
p->data=ch;
if(*S==NULL)
*S=p;
else r->next=p;
r=p; //将r始终定义在串的末位
}
if(r!=NULL)
r->next=NULL;
}
插入运算:
void stribsert(linkstring *S,int i,linkstring T)
{
int k;
linkstring p,q;
p=*S,k=1;
while(p &&k<i-1)
{
p=p->next;
k++;
}
if(!p) printf("error\n");
else
{
q=T;
while(q&&q->next) q=q->next;
q->next=p->next;
p->next=T;
}
}
删除运算:
void strdelete(linkstring *S,int i,int len)
{
int k;
linkstring p,q,r;
p=*S;
q=NULL;
k=1;
while(p && k<i)
{
q=p;
p=p->next;
k++;
}
if(!p) printf("error!\n");
else
{
k=1;
while(k<len &&p)
{
p=p->next;
k++;
}
if(!p) printf("error!\n");
else
{
if(!q)
{
r=*S;
*S=p->next;
}
else
{
r=q->next;
q->next=p->next;
}
while(r!=NULL)
{
p=r;
r=r->next;
free(p);
}
}
}
}
链式串的连结:
void strconcat(linkstring *S1,linkstring S2)
{
linkstring p;
if(!(*S1))
{
*S1=S2;
return ;
}
else if(S2)
{
p=*S1;
while(p->next) p=p->next;
p->next=S2;
}
}
求给定字符串的子串:
linkstring substring(linkstring S,int i,int len)
{
int k;
linkstring p,q,r,t;
p=S,k=1;
while(p && k<i)
{
p=p->next;
k++;
}
if(!p)
{
printf("error\n");
return (NULL);
}
else
{
r=(linkstring)malloc(sizeof(linkstrnode));
r->data=p->data;
r->next=NULL;
k=1;
q=r;
while(p->next && k<len)
{
p=p->next;
k++;
t=(linkstring)malloc(sizeof(linkstrnode));
t->data=p->data;
q->next=t;
q=t;
}
if(k<len)
{
printf("error\n");
return NULL;
}
else
{
q->next=NULL;
return r;
}
}
}
字符串的模式匹配算法:
朴素的模式匹配算法
int index(seqstring p,seqstring t)
{
int i,j,succ;
i=0;
succ=1;
while((j<=p.length-1) && succ)
{
i=0;
succ=1;
while((j<=p.length-1) && succ)
{
if(p.str[j]==t.str[i+j]) j ++;
else succ=0;
}
++i;
}
if(succ) return (i-1);
else return -1;
}
根据模式p组成求其对应的next数组值
void getnext(seqstring p,int next[])
{
int i,j;
next[0]=-1;
i=0;
j=-1;
while(i,p.length)
{
if(j==-1 || p.str[i]==p.str[j])
{
++i;
++j;
next[i]=j;
}
else j=next[j];
for(i=0;i<p.length;i++)
printf("%d",next[i]);
}
}
快速模式匹配算法
int kmp(seqstring t,seqstring p,int next[])
{
int i,j;
i=0;
j=0;
while(i<t.length && j<p.length)
{
if(j==-1 || t.str[i]==p.str[j])
{
i++;
j++;
}
else j=next[j];
}
if(j==p.length) return (i-p.length);
else return (-1);
}
数组
数组和数组元素
数组本身可以看做是线性表的推广,数组的每个元素由数组中的一个值和一组下标决定。数组是线性表的一种存储方式。
数组的定义
数组是一个有固定数量数据元素的有序集合
数组的顺序存储及其实现
数组均采用顺序存储结构实现,它要求一片连续的存储空间存储。
注:多维数组数据元素的顺序存储有两种方式:
- 按行优先存储
- 按列优先存储
存储地址求法:
用首地址加上访问元素之前每个元素的地址长度
三维数组顺序存储
typedef int datatype;
typedef struct{
datatype *base;
int index[3];
int c[3];
}array;
三维数组的初始化
int initarray(array *A,int b1,int b2,int b3)
{
int elements;
if(b1<=0 || b2<=0 | b3<=0) return 0;
A->index[0]=b1;
A->index[1]=b2;
A->index[2]=b3;
elements=b1*b2*b3;
A->base=(datatype*)malloc(elements*sizeof(datatype));
if(!(A->base)) return 0;
A->c[0]=b2*b3;
A->c[1]=b3;
A->c[2]=1;
return 1;
}
访问数组元素
int value(array A, int i1 ,int i2, int i3, datatype*x)
{
int off;
if(i1<0 || i1>=A.index[0] || i2<0 || i2>=A.index[1] || i3<0 || i3>=A.index[2])
return 0;
off=i1*A.c[0]+i2*A.c[1]+i3*A.c[2];
*x=*(A.base+off);
return 1;
}
实现对数组元素的赋值运算
int assign(array *A,datatype e,int i1,int i2,int i3)
{
int off;
if(i1<0 || i1>=A->index[0] || i2<0 || i2>=A->index[1] || i3<0 || i3>=A->index[2])
return 0;
off=i1*A->c[0]+i2*A->c[1]+i3*A->c[2];
*(A->base+off)=e;
return 0;
}
特殊距阵
特殊距阵的定义:
所谓的特殊距阵是指非零元素或零元素的分布有一定规律的距阵,下面我们讨论集中特殊距阵的压缩存储。
分类:
- 对称距阵
- 三角距阵
- 带状距阵
对称矩阵的压缩存储:
多个相同值的结点只分配一个存储空间,值为零的结点不分配存储空间
地址的计算图示如下:
注:三角距阵与带状距阵类似地类比即可
稀疏矩阵
稀疏矩阵的定义:
如果一个矩阵中很多元素的值为零,即零元素的个数远远大于非零元素的个数时,称该矩阵为稀疏矩阵
稀疏矩阵的类型定义
typedef struct {
int data[100][100];
int m,n;
}matrix;
typedef int spmatrix[100][3];
稀疏矩阵的三元组表示
void compressmatrix(matrix A,spmatrix B)
{
int i,j,k=1;
for(i=0;i<A.m;i++)
{
for(j=0;j<A.n;j++)
{
if(A.data[i][j] != 0)
{
B[k][0]=i;
B[k][1]=j;
B[k][2]=A.data[i][j];
k++;
}
}
}
B[0][0]=A.m;
B[0][1]=A.n;
B[0][2]=k-1;
}
在三元组表示下实现系数矩阵的转置
void transpmatrix(spmatrix B,spmatrix C)
{
int i,j,t,m,n;
int x[100];
int y[100];
m=B[0][0];
n=B[0][1];
t=B[0][2];
C[0][0]=m;
C[0][1]=n;
C[0][2]=t;
if(t>0)
{
for(i=0;i<n;i++) x[i]=0;
for(i=1;i<=t;i++) x[B[i][1]]=x[B[i][1]]+1;
y[0]=1;
for(i=1;i<n;i++) y[i]=y[i-1]+x[i-1];
for(i=1;i<=t;i++)
{
j=y[B[i][1]];
C[j][0]=B[i][1];
C[j][1]=B[i][0];
C[j][2]=B[i][2];
y[B[i][1]]=j+1;
}
}
}
稀疏矩阵十字链表示的类型定义
typedef struct matrixnode
{
int row ,col;
struct matrixnode *right,*down;
union{
int val;
struct matrixnode *next;
}tag;
}maxtrixnode;
typedef matrixnode *spmatrix;
typedef spmatrix headspmatrix[100];
创建系数矩阵的十字链表表示
void Createspmatrx(headspmatrix h)
{
int i,n,m,t,s,r,c,v;
spmatrix p,q;
printf("矩阵的行数、列数和非零元素的个数:");
scanf("%d%d%d",&m,&n,&t);
p=(spmatrix)malloc(sizeof(matrixnode));
h[0]=p;
p->row=m;
p->col=n;
s=m>n?m:n;
for(i=1;i<s;++i)
{
p=(spmatrix)malloc(sizeof(matrixnode));
h[i]=p;
h[i-1]->tag.next=p;
p->row=p->col=0;
p->down=p->right=p;
}
h[s]->tag.next=h[0];
for(i=1;i<=t;++i)
{
printf("输出非零元素的行号、列号和值:");
scanf("%d%d%d",&r,&c,&v);
p=(spmatrix)malloc(sizeof(matrixnode));
p->row=r;
p->col=c;
p->tag.val=v;
q=h[r];
while(q->right!=h[r] && q->right->col<c) q=q->right;
q->right=p;
q=h[c];
while(q->down!=h[c] && q->down->row<r) q=q->down;
p->down=q->down;
q->down=p;
}
}
稀疏矩阵十字链表的查找
int localspmatrix(headspmatrix h,int x,int *rowx,int *colx)
{
spmatrix p,q;
p=h[0]->tag.next;
while(p!=h[0])
{
q=p->right;
while(p!=q)
{
if(q->tag.val==x)
{
*rowx=q->row;
*colx=q->col;
return (1);
}
}
p=p->tag.next;
}
return (0);
}