数据结构---串

news2024/11/16 15:35:32

(一)串的基本概念

串(string或字符串)是由零个或多个字符组成的有限序列,一般记为:s=′a1a2…a′n(n≥0) 

    其中,s是串的名称,用单括号括起来的字符序列是串的值; ai(1≤i≤n)ai(1≤i≤n)​​​可以是字母、数字​​或其他字符;串中字符的数目n称为串的长度。零个字符的串称为空串,它的长度为0。

       串中任意个连续的字符组成的子序列称为该串的子串包含子串的串相应的称为主串。通常称字符在序列中的序号为该字符在串中的位置子串在主串中的位置则以子串的第一个字符在主串的位置来表示

       两个串是相等时当且仅当这两个串的值相等。即只有当两个串的长度相等且各个对应位置的字符都相等时才相等。

     由一个或多个空格组成的串‘ ’叫做空格串,它的长度为串中空格字符的个数。为了清楚起见,以后我们用符号“    ”来表示空串。

 

串的表示

1.定长顺序存储表示

#define MAXSIZE 255
typedef struct

{
    char ch[MAXSIZE];
    int  length;
}SString;

这种存储方式类似于线性表的顺序存储,用地址连续的存储单元存储字符序列。串的长度可以在预定长度范围内随意取,超过预定长度的值被舍去。

2.堆分配存储表示

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

这种存储方式以一组地址连续的存储单元存放串值,但存储空间的分配是动态进行的。例如在C语言中用malloc()和free()来动态管理存储空间。

3.块链存储表示

#define CHUNKSIZE 80
typedef struct Chunk
{
    char ch[CHUNKSIZE];
    struct Chunk *next;
}Chunk;

typedef struct
{
    Chunk *head,*tail; /* 串的头和尾指针 */
    int  curlen;       /* 串的当前长度 */
}LString;

和线性表的链式存储结构类似,串值也可以用链表存储。在这里要注意的是定义的结点可存放字符的长度可不同。

(三)串的基本操作


 一般来说,就是增删查改+子串处理,子串比较,增加子串,取子串等

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 1024
typedef struct
{
	char memory[MAXSIZE];
	int curSize;			//万金油参数
}string, * LPSTR;
//创建一个串
LPSTR createStr(const char* str)
{
	LPSTR pStr = (LPSTR)malloc(sizeof(string));
	if (pStr == NULL)
	{
		return NULL;
	}
	for (int i = 0; i < MAXSIZE; i++)
	{
		pStr->memory[i] = '\0';
	}
	int count = 0;
	while (str[count] != '\0')
	{
		pStr->memory[count] = str[count];
		count++;
	}
	pStr->curSize = count;
	return pStr;
}
//串的插入 在当前串中插入多个元素
//123456
//xxx
//xxx123456
//1xxx23456
//123456xxx
void  insertStr(LPSTR pStr, const char* str, int len, int pos)
{
	//pos = pos - 1;
	if (pos < 0 || pos >= MAXSIZE)
	{
		printf("下标有误,无法插入!\n");
		return;
	}
	if (pStr->curSize + len >= MAXSIZE)
	{
		printf("太长,无法插入!\n");
		return;
	}
	if (pos > pStr->curSize)	//直接放在原来串的后面 
	{
		for (int i = 0; i < len; i++)
		{
			pStr->memory[pStr->curSize++] = str[i];
		}
	}
	else
	{
		//1.腾位置
		for (int i = pStr->curSize; i >= pos; i--)
		{
			pStr->memory[len + i] = pStr->memory[i];
		}
		//2.插入新串
		for (int i = 0; i < len; i++)
		{
			pStr->memory[pos + i] = str[i];
		}
		pStr->curSize += len;
	}

}
//串删除
//不做匹配删除,只做区间删除
void deleteStr(LPSTR pStr, int start, int end)
{
	if (start > end || end > pStr->curSize || start <= 0)
	{
		printf("区间有误\n");
		return;
	}
	int count = end - start + 1;
	for (int i = end, j = start - 1; i < pStr->curSize; i++, j++)
	{
		pStr->memory[j] = pStr->memory[i];
	}
	//把后面的东西置空
	for (int i = pStr->curSize; i >= pStr->curSize - count; i--)
	{
		pStr->memory[i] = '\0';
	}
	pStr->curSize -= count;
}
//串连接
LPSTR concatStr(LPSTR pStr, const  char* str,int len)
{
	LPSTR pstr = (LPSTR)malloc(sizeof(string));//新的串接收
	int cout = 0;//新的串长度
	for (int i = 0; i < pStr->curSize; i++)
	{
		pstr->memory[i] = pStr->memory[i];
		cout++;
	}
	for (int i =0; i < len-1; i++)
	{
		pstr->memory[cout] = str[i];
		cout++;
	}
	pstr->curSize = cout;
	return pstr;
}
//串的打印的
void printStr(LPSTR pStr)
{
	for (int i = 0; i < pStr->curSize; i++)
	{
		printf("%c", pStr->memory[i]);
	}
	printf("\n");
	/*
		%s
		puts
	*/
}
int main()
{
	char name[20] = "bbbm";
    LPSTR pStr = createStr("ILoveyou");  //8  0-7
	printStr(concatStr(pStr, name, 5));
	printf("pStr->curSize:%d\n", pStr->curSize);
	printStr(pStr);
	insertStr(pStr, "xxx", 3, 0);
	printStr(pStr);
	printf("pStr->curSize:%d\n", pStr->curSize);
	deleteStr(pStr, 1, 3);
	printStr(pStr);
	printf("pStr->curSize:%d\n", pStr->curSize);
	return 0;
}

(三)串的各种匹配模式BF算法和KMP算法

BF算法 

相关知识点:

  BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。一力破百巧

实例如下:

具体代码:

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 1024
typedef struct
{
	char memory[MAXSIZE];
	int curSize;			//万金油参数
}string, * LPSTR;
//创建一个串
LPSTR createStr(const char* str)
{
	LPSTR pStr = (LPSTR)malloc(sizeof(string));
	if (pStr == NULL)
	{
		return NULL;
	}
	for (int i = 0; i < MAXSIZE; i++)
	{
		pStr->memory[i] = '\0';
	}
	int count = 0;
	while (str[count] != '\0')
	{
		pStr->memory[count] = str[count];
		count++;
	}
	pStr->curSize = count;
	return pStr;
}
bool Index(LPSTR Str, LPSTR  str )
{
	int i = 0, j = 0;//用来保存Str和str长度的
	
	while (i<Str->curSize&& j<str->curSize)
	{
		if (Str->memory[i] == str->memory[j])
		{
			i++;
			j++;//比较第二个元素
		}
		else
		{
			i = i - j + 1;//主串从头开始匹配
			j = 0;//子串从头开始
		}
	 }
	if (j >= str->curSize)  return true;
	else
	{
       return  false;
	}
}
//普通的串要传长度
bool Index1(LPSTR* Str, const char* str,int len)
{
	return false;
}
int main()
{
	 
    LPSTR pStr = createStr("ababcababa");   
	LPSTR pstr = createStr("abacc");
	LPSTR pstr1 = createStr("ababa");
	printf("匹配%s\n", Index(pStr, pstr) ? "成功" : "不成功");
	printf("匹配%s\n", Index(pStr, pstr1) ? "成功" : "不成功");
	return 0;
}

 

KMP算法

相关知识点:

    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度为O(m+n)。

详解KMP:第一次应用到BF算法,一个一个第比较。

 

具体代码:

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 1024
typedef struct
{
	char memory[MAXSIZE];
	int curSize;			//万金油参数
}string, * LPSTR;
//创建一个串
LPSTR createStr(const char* str)
{
	LPSTR pStr = (LPSTR)malloc(sizeof(string));
	for (int i = 0; i < MAXSIZE; i++)
	{
		pStr->memory[i] = '\0';
	}
	int count = 0;
	while (str[count] != '\0')
	{
		pStr->memory[count] = str[count];
		count++;
	}
	pStr->curSize = count;
	return pStr;
}
//求相应的部分匹配值 就是找某串的共同前缀和后缀 如 ABCA 的前缀为A,AB,ABC ;后缀为A,AC,ACB,共同元素为A,故相应的部分匹配值为1
void getNext(LPSTR pstr, int next[])
{
	int len = pstr->curSize;
	int i = 0;
	int j = -1;
	next[0] = -1;		//第一个位置为0,或者-1都行
	while (i < len)
	{
		if (j == -1 || pstr->memory[i] == pstr->memory[j])
		{
			i++;
			j++;
			next[i] = j;	//部分匹配元素的长度
		}
		else
		{
			j = next[j];	 //重置j为-1
		}
	}
}

int KMP(LPSTR pStr1, LPSTR pStr2, int next[])
{
	//KMP 第一个得到表
	getNext(pStr2, next);
	int i = 0;
	int j = 0;
	while (i < pStr1->curSize && j < pStr2->curSize)
	{
		if (j == -1 || pStr1->memory[i] == pStr2->memory[j])
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];		//重置
		}
	}
	if (j == pStr2->curSize)
	{
		return i - j;
	}
	return 0;
}

int main()
{
	
	int next[11];//字符串长度
	LPSTR pStr = createStr("ababcababa");
	getNext(pStr, next);
	for (int i = 0; i < 10; i++)//‘\0’不算
	{
		printf(" %d ", next[i]);//打印字符串前缀和后缀相同元素的长度
	}
	printf("\n");
		LPSTR pstr = createStr("abacc");
		LPSTR pstr1 = createStr("ababa");
		int next1[6];//
		printf("匹配%s\n", KMP(pStr, pstr,next) ? "成功" : "不成功");
		printf("匹配%s\n", KMP(pStr, pstr1,next1) ? "成功" : "不成功");
	  
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/113793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS优先级CSS盒子模型

1、CSS继承 文字相关的样式可以被继承【作用在父元素上面&#xff0c;子元素可以继承】布局相关的样式不可以被继承【可以通过inherit值进行继承】 2、CSS优先级 书写了相同样式时&#xff0c;后写的样式优先级较高当内部样式和外部样式有相同的样式时&#xff0c;后写的样式…

操作符(8)

目录 1、算术操作符 2、移位操作符 3、位操作符 1、不能创建临时变量&#xff08;第三个变量&#xff09;&#xff0c;实现两个数的交换 4、赋值操作符 5、单目操作符 6、关系操作符 7、逻辑操作符 8、条件操作符 9、逗号表达式 10、下标引用、函数调用和结构成员 …

WPF开发之Prism详解【内附源码】

在实际应用开发中&#xff0c;随着项目业务逐渐复杂&#xff0c;耦合度会越来越高&#xff0c;维护成本也会直线上升&#xff0c;所以解耦也变得越来越重要。Prism框架为WPF开发中解耦提供了非常便捷的应用。今天主要以一个简单的小例子&#xff0c;简述WPF开发中Prism框架的简…

基于Arch Linux的SystemRescue 9.06工具包新特性

导读在上次发布两个月后&#xff0c;SystemRescue&#xff08;原名SystemRescueCd&#xff09;Linux系统救援工具包今天更新到了9.06版本&#xff0c;这个版本在启动菜单中增加了新的选项&#xff0c;更新了组件和新工具。 SystemRescue 9.06在这里采用了最新、最棒的Xfce 4.18…

【三年面试五年模拟】算法工程师的独孤九剑秘籍(第十一式)

Rocky Ding公众号&#xff1a;WeThinkIn写在前面 【三年面试五年模拟】栏目专注于分享CV算法与机器学习相关的经典&&必备&&高价值的面试知识点&#xff0c;并向着更实战&#xff0c;更真实&#xff0c;更从容的方向不断优化迭代。也欢迎大家提出宝贵的意见或优…

我是真没想道,这个面试题居然从11年前就开始讨论了,而官方今年才表态。

大家好 这期给大家盘一个面试题啊&#xff0c;就是下面的第二题。 这个面试题的图片都被弄的有一点“包浆”了。 所以为了你的观感&#xff0c;我还是把第二道题目手打一遍。 啧啧啧&#xff0c;这行为&#xff0c;暖男作者实锤了&#xff1a; spring 在启动期间会做类扫描&…

前端css样式小知识点(2)

文章目录前言图文实操讲解1、微信小程序之页面跳转方法页面跳转有很多种方式&#xff0c;先简单说一下它们的区别吧简单实现2、微信小程序this.setData修改对象、数组中的值3、微信小程序-获取input值的方法4、微信小程序-常用的三种弹窗5、dataset 简单小知识 误区6、that.set…

git status查看本地库状态、git add添加暂存区

假设目前我处于我的项目之下。 查看状态命令 git status 可以看到如下的状态 现在我新建一个文件hello.txt 在里面写了16行的内容。&#xff08;这个vim之前也没有使用过&#xff0c;在最后记录一下。&#xff09; 再看一下状态 那我们现在就add一下&#xff0c;使用命令&…

新冠确诊阳性的第六篇博客,Linux防火墙管理

Linux防火墙管理1.防火墙的下载2.演示&#xff1a;关闭防火墙3.防火墙端口管理4.防火墙的其他命令1.防火墙的下载 Centos7下默认的防火墙是 Firewall 如果提示&#xff1a;Unit firewalld.service could not be found. 说明防火墙没有安装&#xff0c;需要安装 sudo yum ins…

redux及react-redux

redux 这篇文章谈一谈仓库redux。 首先&#xff0c;学习任何东西都离不开官网。在此附上官网网址 Redux - A predictable state container for JavaScript apps. | Redux 1.什么是redux&#xff1f; 从如下几个方面&#xff1a; redux在一个项目中可集中管理状态(数据)和逻…

【Pandas入门教程】如何操作文本数据

如何操作文本数据 来源&#xff1a;Pandas官网&#xff1a;https://pandas.pydata.org/docs/getting_started/intro_tutorials/index.html 笔记托管&#xff1a;https://gitee.com/DingJiaxiong/machine-learning-study 文章目录如何操作文本数据导包数据准备【小结】导包 imp…

怎么录屏?5 款免费无水印的录屏神器

无论您是想记录游戏中令人难忘的时刻、与他人分享视频教程&#xff0c;还是做更多类似的事情&#xff0c;都必须使用屏幕录像机。从 Internet 上很容易获得屏幕录像机&#xff1b;然而&#xff0c;找到一个“好”的并不是那么简单。当我们试用一些免费的屏幕录像机来捕捉电脑屏…

springboot整合之版本号统一管理

特别说明&#xff1a;本次项目整合基于idea进行的&#xff0c;如果使用Eclipse可能操作会略有不同&#xff0c;不过总的来说不影响。 springboot整合之如何选择版本及项目搭建 springboot整合之版本号统一管理 springboot整合mybatis-plusdurid数据库连接池 springboot整合…

华舞依旧,未来不远:智能光伏十大趋势告诉我们什么?

在“碳中和”时代&#xff0c;光伏正在日渐成为能源舞台的主角。我们知道&#xff0c;想要实现“碳中和”目标就需要降低能源带来的碳排放。而在能够实现这个目标的能源体系中&#xff0c;水电、风电受到环境限制较强&#xff0c;而氢能、核聚变为代表的下一代能源体系还不够成…

D59|单调栈进阶版

503.下一个更大元素II 1.题目 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&#xff09;&#xff0c;输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数&#xff0c;这意味…

node.js+uni计算机毕设项目“宠到家”宠物领养小程序(程序+小程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等…

“千万别奶睡,以后很难戒”,宝宝为啥喜欢奶睡,真有这么可怕?

我还记得懒妈妈哺乳的时候&#xff0c;身边有一个“过来人”提醒&#xff1a;不要奶睡&#xff0c;否则以后就戒不掉了&#xff0c;宝宝会一直吃着睡觉。事实上&#xff0c;当时懒惰的母亲更抗拒这种说法&#xff0c;主要原因是哄睡更困难&#xff0c;每天花更多的时间哄睡觉&a…

《C++程序设计原理与实践》笔记 第8章 函数相关的技术细节

在本章和下一章中&#xff0c;我们将注意力从程序设计转移到主要的编程工具——C语言上。我们会介绍一些语言的技术细节&#xff0c;来给出一个C的基本功能的稍宽的视角&#xff0c;并从更系统化的角度讨论这些功能。 8.1 技术细节 程序设计(programming)&#xff08;即如何用…

Podman QuickStart

Install Install Link brew install podman podman machine init podman machine startpodman machine init --cpus4 --disk-size64 --memory6144 podman machine start podman-machine-default开启和关闭root 权限 Tips: 切换root 模式前后&#xff0c;相互看不到对方模式下…

vue学习笔记(七)-vue3新特性

概念 vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;https://github.com/vuejs/vue-next/releases/tag/v3.0…