数据结构 —— 第四章 字符串、数组、特殊距阵

字符串

目录

字符串

字符串的存储及其实现

顺序串:

顺序串的结构表示:

顺序串的插入

顺序串的删除:

连结运算:

求给定顺序串的子串

串的链式存储及其实现:

插入运算:

删除运算:

链式串的连结:

求给定字符串的子串:

字符串的模式匹配算法:

朴素的模式匹配算法

根据模式p组成求其对应的next数组值

快速模式匹配算法

数组

数组和数组元素

数组的定义

数组的顺序存储及其实现

存储地址求法:

三维数组顺序存储

三维数组的初始化

访问数组元素

实现对数组元素的赋值运算

特殊距阵

特殊距阵的定义:

分类:

对称矩阵的压缩存储:

稀疏矩阵

稀疏矩阵的定义:

稀疏矩阵的类型定义

稀疏矩阵的三元组表示

在三元组表示下实现系数矩阵的转置

稀疏矩阵十字链表示的类型定义

创建系数矩阵的十字链表表示

稀疏矩阵十字链表的查找


字符串的存储及其实现

字符串是一种特殊的线性表,由于链式表有顺序存储和链式存储两大数据结构,所以字符串也有顺序串和链式串

顺序串:

顺序串的结构表示:

#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);
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值