IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 串(纯C语言实现) -> 正文阅读

[数据结构与算法]串(纯C语言实现)

1. 串的存储结构

1.1 串的顺序存储

从下标为1的数组分量开始存储

当0号单元存放串的当前长度时,可以定义:(后续基本操作都使用此定义

typedef char SString[MAXSIZE+1];   //后续这样定义串SString S,T; 这样取值S[0],T[1];

但0号单位闲置不用时,可以定义:

typedef struct{
    char ch[MAXSIZE+1];
    int length;             //记录串的当前长度
}SString;

还有堆(Heap)式顺序存储结构

typedef struct{
    char *ch;
    int length;
}HString;

1.2 串的链式存储

块链结构:

#define CHUNKSIZE 80           //定义块的大小
typedef struct Chunk{
    char ch[CHUNKSIZE];
    struct Chunk *next;
}Chunk;
typedef struct{
    Chunk *head,*tail;         //头指针和尾指针,可以只要其中一个
    int length;
}LString;

2. 串的基本操作

2.1 分配StrAssign(T,*chars)

生成一个其值等于chars的串T(chars是字符串常量),如StrAssign(s1,"abcd")

Status StrAssign(SString T,char *chars)
{ 
	int i;
	if(strlen(chars)>MAXSIZE)
		return ERROR;
	else
	{
		T[0]=strlen(chars);
		for(i=1;i<=T[0];i++)
			T[i]=*(chars+i-1);
		return OK;
	}
}

2.2 复制StrCopy(T,S)

由串S复制得串T

Status StrCopy(SString T,SString S)
{ 
	int i;
	for(i=0;i<=S[0];i++)
		T[i]=S[i];
	return OK;
}

2.3 判断是否为空StrEmpty(S)

Status StrEmpty(SString S)
{ 
	if(S[0]==0)
		return TRUE;
	else
		return FALSE;
}

2.4 比较大小StrCompare(S,T)

返回长度差。若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0

int StrCompare(SString S,SString T)
{ 
	int i;
	for(i=1;i<=S[0]&&i<=T[0];++i)
		if(S[i]!=T[i])
			return S[i]-T[i];
	return S[0]-T[0];
}

2.5 求串长StrLength(S)

int StrLength(SString S)
{ 
	return S[0];
}

2.6 清空ClearString(S)

Status ClearString(SString S)
{ 
	S[0]=0;             //令串长为零 
	return OK;
}

2.7 字符串连接Concat(T,S1,S2)

用T返回S1和S2联接而成的新串。若未截断S2,则返回TRUE,否则FALSE

Status Concat(SString T,SString S1,SString S2)
{
	int i;
	if(S1[0]+S2[0]<=MAXSIZE)
	{ 
		for(i=1;i<=S1[0];i++)
			T[i]=S1[i];
		for(i=1;i<=S2[0];i++)
			T[S1[0]+i]=S2[i];
		T[0]=S1[0]+S2[0];
		return TRUE;
	}
	else                                //截断S2
	{ 
		for(i=1;i<=S1[0];i++)
			T[i]=S1[i];
		for(i=1;i<=MAXSIZE-S1[0];i++)
			T[S1[0]+i]=S2[i];
		T[0]=MAXSIZE;
		return FALSE;
	}
}

2.8 取子串SubString(Sub,S,pos,len)

用Sub返回串S的第pos个字符起长度为len的子串

Status SubString(SString Sub,SString S,int pos,int len)
{
	int i;
	if(pos<1||pos>S[0]||len<0||len>S[0]-pos+1)   //len和pos需满足len<=S[0]-pos+1
		return ERROR;
	for(i=1;i<=len;i++)
		Sub[i]=S[pos+i-1];
	Sub[0]=len;
	return OK;
}

2.9 子串的定位Index(S, T, pos) ,又称为串的模式匹配算法

返回子串T主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。其中,T非空,1≤pos≤StrLength(S)

BF算法:

方法一:

int Index(SString S, SString T, int pos) 
{
	int i = pos;	                    //i用于主串S中当前位置下标值
	int j = 1;				            //j用于子串T中当前位置下标值
	while (i <= S[0] && j <= T[0])      //若i小于S的长度并且j小于T的长度时,循环继续
	{
		if (S[i] == T[j]) 	            //两字母相等则继续
      	{
			++i;
         	++j; 
      	} 
      	else 				            //指针后退重新开始匹配
      	{  
         	i = i-j+2;		            //i退回到上次匹配首位的下一位,即i=i-j+1+1
         	j = 1; 			            //j退回到子串T的首位
      	}      
	}
	if (j > T[0])                       //子串所有字符都匹配完毕
		return i-T[0];                  //返回匹配的第一个字符的下标
	else
		return 0;                       //匹配失败
}

方法二:

int Index(SString S, SString T, int pos) 
{
	int n,m,i;
	SString sub;
	if (pos > 0) 
	{
		n = StrLength(S);	/* 得到主串S的长度 */
		m = StrLength(T);	/* 得到子串T的长度 */
		i = pos;
		while (i <= n-m+1) 
		{
			SubString (sub, S, i, m);	/* 取主串中第i个位置长度与T相等的子串给sub */
			if (StrCompare(sub,T) != 0)    /* 如果两串不相等 */
				++i;
			else 				/* 如果两串相等 */
				return i;		/* 则返回i值 */
		}
	}
	return 0;	/* 若无子串与T相等,返回0 */
}

KMP算法

/* 通过计算返回子串T的next数组。 */
void get_next(String T, int *next) 
{
	int i,k;
  	i=1;
  	k=0;
  	next[1]=0;
  	while (i<T[0])  /* 此处T[0]表示串T的长度 */
 	{
    	if(k==0 || T[i]== T[k]) 
		{
      		++i;  
			++k;  
			next[i] = k;
    	} 
		else 
			k= next[k];	/* 若字符不相同,则k值回溯 */
  	}
}

/* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
/*  T非空,1≤pos≤StrLength(S)。 */
int Index_KMP(String S, String T, int pos) 
{
	int i = pos;		/* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
	int j = 1;			/* j用于子串T中当前位置下标值 */
	int next[255];		/* 定义一next数组 */
	get_next(T, next);	/* 对串T作分析,得到next数组 */
	while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
	{
		if (j==0 || S[i] == T[j]) 	/* 两字母相等则继续,与朴素算法增加了j=0判断 */
      	{
         	++i;
         	++j; 
      	} 
      	else 			/* 指针后退重新开始匹配 */
      	 	j = next[j];/* j退回合适的位置,i值不变 */
	}
	if (j > T[0]) 
		return i-T[0];
	else 
		return 0;
}

2.10 插入StrInsert(S,pos,T)

在串S的第pos个字符之前插入串T。完全插入返回TRUE,部分插入返回FALSE。其中1≤pos≤StrLength(S)+1

Status StrInsert(SString S,int pos,SString T)
{ 
	int i,j;
	j=pos;
	if(pos<1||pos>S[0]+1)
		return ERROR;
	if(S[0]+T[0]<=MAXSIZE)
	{ /*  完全插入 */
		for(i=S[0];i>=pos;i--)
			S[i+T[0]]=S[i];
		for(i=pos;i<pos+T[0];i++)
			S[i]=T[i-pos+1];
		S[0]=S[0]+T[0];
		return TRUE;
	}
	else
	{ /*  部分插入 */
		for(i=pos+T[0];i<=MAXSIZE;i++,j++)
			S[i]=S[j];
		for(i=pos;i<pos+T[0];i++)
			S[i]=T[i-pos+1];
		S[0]=MAXSIZE;
		return FALSE;
	}
}

2.11 删除子串StrDelete(S,pos,len)

从串S中删除第pos个字符起长度为len的子串。其中1≤pos≤StrLength(S)-len+1

Status StrDelete(SString S,int pos,int len)
{ 
	int i;
	if(pos<1||pos>S[0]-len+1||len<0)
		return ERROR;
	for(i=pos+len;i<=S[0];i++)
		S[i-len]=S[i];
	S[0]-=len;
	return OK;
}

2.12 替换Replace(S,T,V)

用V替换主串S中出现的所有与T相等的不重叠的子串

Status Replace(SString S,SString T,SString V)
{ 
	int i=1;                          /* 从串S的第一个字符起查找串T */
	if(StrEmpty(T))
		return ERROR;
	do
	{
		i=Index(S,T,i);               /*  结果i为从上一个i之后找到的子串T的位置 */
		if(i)                         /*  串S中存在串T */
		{
			StrDelete(S,i,StrLength(T));       /*  删除该串T */
			StrInsert(S,i,V);                  /*  在原串T的位置插入串V */
			i+=StrLength(V);                   /*  在插入的串V后面继续查找串T */
		}
	}while(i);
	return OK;
}

2.13 打印StrPrint(T)

void StrPrint(SString T)
{ 
	int i;
	for(i=1;i<=T[0];i++)
		printf("%c",T[i]);
	printf("\n");
}

3. 串的综合实例

#include<stdio.h>
#include<string.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 40

typedef int Status; 

typedef char SString[MAXSIZE+1];

Status ClearString(SString S)
{ 
	S[0]=0;             //令串长为零 
	return OK;
}

Status StrAssign(SString T,char *chars)
{ 
	int i;
	if(strlen(chars)>MAXSIZE)
		return ERROR;
	else
	{
		T[0]=strlen(chars);
		for(i=1;i<=T[0];i++)
			T[i]=*(chars+i-1);
		return OK;
	}
}

Status StrCopy(SString T,SString S)
{ 
	int i;
	for(i=0;i<=S[0];i++)
		T[i]=S[i];
	return OK;
}

Status StrEmpty(SString S)
{ 
	if(S[0]==0)
		return TRUE;
	else
		return FALSE;
}

int StrCompare(SString S,SString T)
{ 
	return S[0]-T[0];
}

int StrLength(SString S)
{ 
	return S[0];
}

void StrPrint(SString S)
{ 
	int i;
	for(i=1;i<=S[0];i++)
		printf("%c",S[i]);
	printf("\n");
}

void menu()
{
	printf("        ********串的功能菜单********         \n");
	printf("  1.赋值(已有串T和S)  ");printf("2.复制\n");
	printf("  3.判断是否为空串    ");printf("4.比较长度\n");
	printf("  5.求串长            ");printf("6.清空\n");
	printf("  7.打印              ");printf("8.退出\n");
}

int main()
{
	int i,choice=0;
	char chars[MAXSIZE+1];
	SString S,T;
	ClearString(S);
	ClearString(T);
	menu();
	while(choice!=8)
	{
		printf("请选择功能:\n");
		scanf("%d",&choice);
		switch(choice)
		{
		case 1:
			printf("1.给串S赋值\n");
			printf("2.给串T赋值\n");
			printf("请输入1或2\n");
			scanf("%d",&i);
			printf("请输入要赋的值:\n");
			getchar();
			scanf("%s",chars);
			if(i==1){
				StrAssign(S,chars);
				printf("串S赋值完成!\n");
			}
			else if(i==2){
				StrAssign(T,chars);
				printf("串T赋值完成!\n");
			}
			else 
			    printf("序号错误,请输入正确的序号");
			break;
		case 2:
			printf("1.由串S复制得串T\n");
			printf("2.由串T复制得串S\n");
			printf("请输入1或2\n");
			scanf("%d",&i);
			if(i==1){
				StrCopy(T,S);
				printf("复制完成!\n");
			}
			else if(i==2){
				StrCopy(S,T);
				printf("复制完成!\n");
			}
			else 
			    printf("序号错误,请输入正确的序号");
			break;
		case 3:
			if(StrEmpty(S)){
				printf("S是空串\n");
			}
			else{
				printf("S不是空串\n");
			}
			if(StrEmpty(T)){
				printf("T是空串\n");
			}
			else{
				printf("T不是空串\n");
			}
			break;
		case 4:
			printf("S和T的长度差为%d\n",StrCompare(S,T));
			break;
		case 5:
			printf("串S长为%d\n",StrLength(S));
			printf("串T长为%d\n",StrLength(T));
			break;
		case 6:
			printf("1.清空串S\n");
			printf("2.清空串T\n");
			printf("请输入1或2\n");
			scanf("%d",&i);
			if(i==1){
				ClearString(S);
				printf("S已清空!\n");
			}
			else if(i==2){
				ClearString(T);
				printf("T已清空!\n");
			}
			else 
			    printf("序号错误,请输入正确的序号");
			break;
		case 7:
			printf("串S为:");
			StrPrint(S);
			printf("串T为:");
			StrPrint(T);
			break;
		case 8:
			printf("******************END**********************\n");
			break;
		}
	}
	return 0;
}

运行截图:
运行结果

补充:C语言库文件string.h中常用的基本字符串函数

char s1[]="I am a student";
char s2[20]="teacher";
char s3[]="student";
char s4[20],*p;

串长strlen

int strlen(char *str),如strlen(s1) == 14

复制strcpy

char *strcpy(char *str1,char *str2)

strcpy(s4,s2);
printf("%s\n",s4);     //输出teacher

比较strcmp

int strcmp(char *str1,char *str2),如strcmp(s2,s3)

字符定位strchr

char *strchr(char *str,char ch)

p = strchr(s1,'s');     //返回's'在s1中第一次出现的地址
printf("%s\n",p);       //输出student

子串查找strstr

char *strstr(char *s1,char *s2)

p = strstr(s1,s3);      //返回字符串s3在字符串s1中第一次出现的地址
printf("%s\n",p);       //输出student

连接strcat

char *strcat(char *s1, char *s2)

strcat(s2,s3);
printf("%s\n",s2);    //输出teacherstudent
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-04 13:41:41  更:2021-12-04 13:42:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 10:59:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码