【图解数据结构】串全面总结

目录

 

一、基本概念

二、串的类型

1.定长顺序串

2.堆串

3.块链串

三、模式匹配

四、总结与提高

String函数:

五、附录:

 


一、基本概念

  • 串(string):由0个或多个字符组成的有序序列,称为字符串,记为s='abcdefg' 其中s是字符串的名字,a b c称为串的值,可以是字母、数字或者字符
  • 串长度:串中元素个数
  • 空串:不含任何字符的串,串长度为0
  • 子串:主串中任意连续字符组成的字符串
  • 串s1、s2相等的条件:
    1. s1、s2长度相等
    2. s1、s2对应位置的元素处处相等

二、串的类型

1.定长顺序串

  定义:用一组地址连续的存储单元存储串值的字符序列,类似于线性表的顺序存储结构。

 静态存储分布代码实现:

#define MAXLEN 30 // 用户可在255以内定义最大串长    
typedef struct 
{
    char ch[MAXLEN];
    int len;
} SString ;

动态演示: 

3dc06564b56f48ae848fd1c11ca807f1.gif

  • 其实就是依次插入

算法:

串插入:

int StrInsert(SString *s, int pos, SString t)
/*在串s中下标为pos的字符之前插入串t */
{	int i;
	if (pos<0 || pos>s->len)   /*插入位置不合法*/
		return(0); 
	if (s->len + t.len<=MAXLEN) /*插入后串长≤MAXLEN*/
	{
		for (i=s->len + t.len-1;i>=t.len + pos;i--)
			s->ch[i]=s->ch[i-t.len]; //将插入位置现有字符后移
		for (i=0;i<t.len;i++) 
			s->ch[i+pos]=t.ch[i];   //在空出的位置逐个插入字符串
		s->len=s->len+t.len;
	}	
else
	{         if (pos+t.len<=MAXLEN) 
             /*插入后串长>MAXLEN,但串t的字符序列可以全部插入*/
		{
			for (i=MAXLEN-1;i>t.len+pos-1;i--) 
				s->ch[i]=s->ch[i-t.len]; //将插入位置现有字符后移
			for (i=0;i<t.len;i++)
				s->ch[i+pos]=t.ch[i]; //在空出的位置逐个插入字符串
			s->len=MAXLEN;
		}
		else /*插入后串长>MAXLEN,并且串t的部分字符也要舍弃*/
		{ 	for (i=0;i<MAXLEN-pos;i++)
				s->ch[i+pos]=t.ch[i];
			s->len=MAXLEN;
		}
		return(1);
	}
}

串删除:

int StrDelete(SString *s, int pos, int len)
/*在串s中删除从下标pos起len个字符*/
{ 
	int i;
	if (pos<0 || pos>(s->len-len))  /*删除参数不合法*/
		return(0); 
	for (i=pos+len;i<s->len;i++)
		s->ch[i-len]=s->ch[i];   /*从pos+len开始至串尾依次向前移动,实现删除len个字符*/
	s->len=s->len - len;    /*s串长减len*/
	return(1);
}

串复制:

void StrCopy(SString *s, SString t)
/*将串t的值复制到串s中*/
{ 
	int i;
	for (i=0;i<t.len;i++)
		s->ch[i]=t.ch[i];
	s->len=t.len;
}

串比较:

int StrCompare(SString s, SString t)
/*若串s和t相等则返回0;若s>t则返回正数;若s<t则返回负数*/
{ 
	int i;
	for (i=0;i<s.len&&i<t.len;i++)
		if (s.ch[i]!=t.ch[i]) 
			return(s.ch[i] - t.ch[i]);   //按字符的字典顺序比较
	return(s.len - t.len);
}

串连接:

int StrCat(SString *s, SString t)
/*将串连接在串s的后面*/
{ 	int i, flag;
	if (s->len + t.len<=MAXLEN) 
                   /*连接后串长小于MAXLEN*/
	{ 
		for (i=s->len; i<s->len + t.len; i++)
			s->ch[i]=t.ch[i-s->len]; //t的下标从0开始
		s->len+=t.len;
		flag=1;
	}
	else 
    {
        if (s->len<MAXLEN)  
       /*连接后串长大于MAXLEN,但串s的长度小于MAXLEN,即连接后串t的部分字符序列被舍弃*/
	    { 
		    for (i=s->len;i<MAXLEN;i++)
		    	s->ch[i]=t.ch[i-s->len];
		    s->len=MAXLEN;
	    	flag=0;
	    }
	    else 
	    	flag=0;  /* 串s的长度等于MAXLEN ,串t不被连接*/
	return(flag);
    }

求子串:

int SubString(SString *sub, SString s, int pos, int len) 
/*将串s中下标pos起len个字符复制到sub中*/
{ 	int i;
	if (pos<0 || pos>s.len || len<1 || len>s.len-pos) //位置或长度不合法时
    {
		sub->len=0;
		return(0); 
	}
	else 
	{	for (i=0; i<len; i++)
			sub->ch[i]=s.ch[i+pos];
		sub->len=len;
		return(1);
	}
}

2.堆串

  • 堆:自由存储区域,malloc()实现
  • 以一组地址连续的存储单元存储串值       的字符序列,在程序执行过程中由动态分配而得到

代码:

typedef struct {  
      char *ch; // 若非空串则按串长分配存储区,否则为NULL
      int length;// 串长度
} HString;

3.块链串

  • 定义:与链表类似,但每一个结点可以存放多个字符,结尾增加尾指针

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-l5b-D5a6d6LSd,size_20,color_FFFFFF,t_70,g_se,x_16

 

 代码实现:

#define BLOCK_SIZE 4 // 可由用户定义的块大小   
typedef struct Block
 { 
     char ch[BLOCK_SIZE];
     struct Block *next;
} Block;

三、模式匹配

  • 定义:求解子串首次在主串中出现的位置
  • 模式匹配也称为子串的定位操作,用函数StrIndex(S,pos,T)实现,T被称为模式串。

代码: 

int StrIndex(SString s,int pos, SString t) 
/*求从主串s的下标pos起,串t第一次出现的位置,成功返回位置序号,不成功返回-1*/
{ 	int i, j, start;
	if (t.len==0)  return(0);   /* 模式串为空串时,是任意串的匹配串 */
	start=pos; i=start; j=0;  /* 主串从pos开始,模式串从头(0)开始 */
	while (i<s.len && j<t.len)
		if (s.ch[i]==t.ch[j]) 
		{    i++;   j++;	}   /* 当前对应字符相等时推进 */
		else 
		{   start++;        /* 当前对应字符不等时回溯 */
		     i=start;    j=0;   /* 主串从start+1开始,模式串从头(0)开始*/
		} 
		if (j>=t.len) 
			return(start);    /* 匹配成功时,返回匹配起始位置 */
		else 
			return(-1);    /* 匹配不成功时,返回-1 */
}

演示图:

923ada5f6b144ba78086b4239eb70af3.gif

 解析:

  • 设置两个指针i和k,输入目标串Hello World!,模式串orl

  • 如果i指向的值和模式串首个元素不一致,则指针i j同时向后移动

  • 如果i指向的值和模式串首个元素一致,则只是指针j向后移动

  • 如果j指向的元素和模式串后续元素一致,继续移动,直到查找完成

  • 如果j指向的元素和模式串后续元素不一致,指针i到k的位置,继续开始

四、总结与提高

在C++中,C++ 标准库提供了 string 类类型,支持上述所有的操作,另外还增加了其他更多的功能。

编程时加入头文件:

#include<string>//或者万能头文件#include<bits/stdc++.h>
using namespace std;

String函数:

用string定义s类(定义什么都可以,只要把s变成定义的字母就可以调用C++中的函数),具体使用方法为:

函数用法
                                                        常见操作
s.resize(10)设置字符串长度为10
string s("ABC")构造字符串s的值为ABC
s.empty()判断字符串是否为空
s.length()或者s.size()求解字符串长度
s.begin()开始值
s.end()结尾值
                                        查找(查找成功返回元素位置,失败返回-1)
s.find('A')查找字符A
s.find("ABC")查找字符串ABC
s.find('A',2)从位置2开始查找字符A
s.find("ABCD",1,2)从位置1开始,查找ABCD的前两个字符
s.rfind()从字符串尾部开始查找
                                                      插入
s.insert(2,3,'A')在下标为2的地方添加三个A
s.insert(2,"ABC")在下标为2的地方添加字符串ABC
s.insert(2,"ABC",1)在下标为2的地方添加ABC中的一个
s.insert(2,"ABCD", 2,2)在下标为2的地方从字符串ABCD中位置2开始的2个字符
s.push_back('A')在尾部添加字符A
                                                       替换
s.replace(2,4,"ABCD")从下标2的位置,替换4个字符为 "ABCD"
                                                       删除
s.erase(2)删除下标2以后的全部元素
s.erase(2,1)删除下标2以后的第一个元素
                                                       翻转
reverse(s.begin(),s.end())翻转所有字符串,即逆序输出
                                                        复制
s1=s.substring(2)提取字符串s从2到尾部赋值给s1
s1=s.substring(2,3)提取字符串s从2开始三个字符赋值给s1
const char*s1=s.data()将string类转为字符串数组
s.copy(s1,2,3)将s中从第3个位置拷贝2个字符到s1中
                                                      比较(假设原字符串为ABCD)
s.compare("ABCD")相等返回0,大于原字符串返回1,小于返回-1
                                                      清空
s.assign("ABC")清空字符串,并置为ABC
s.assign("ABC",2)清空字符串,并置为ABC的前2个字符AB
s.assign("ABC",2,1)清空字符串,并置为ABC的从2开始的1个字符
s.assign(5,‘A’)清空字符串,并置为5个A
s.clear()清空字符串所有字符

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

文档的具体内容可以参考:C++标准官方文档

五、附录:

几道经典的题目链接:

1.无重复的最长子串

                      
 2.最长回文串

    3.模式匹配

                           
     4.回文串

   5.最长回文子序列

附录:

 

 

 

 

 

 

 

  • 100
    点赞
  • 159
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 71
    评论
数据结构是计算机科学中非常重要的概念之一,它用于组织和存储数据以便有效地操作和访问。Java语言提供了丰富的数据结构库,包括数组、链表、栈、队列、树、图等。我将为你图解一些常见的数据结构及其在Java中的实现。 1. 数组(Array):数组是一种线性数据结构,它按照顺序存储相同类型的元素。在Java中,数组的大小在创建时就确定,并且可以通过索引访问和修改其中的元素。 2. 链表(Linked List):链表是一种动态数据结构,它由节点组成,每个节点包含数据和指向下一个节点的引用。在Java中,有单向链表和双向链表两种常见的实现方式。 3. 栈(Stack):栈是一种后进先出(LIFO)的数据结构,类似于我们生活中的一叠盘子。在Java中,可以使用Stack类或者使用LinkedList类来实现栈。 4. 队列(Queue):队列是一种先进先出(FIFO)的数据结构,类似于我们日常生活中排队等待的情况。在Java中,可以使用Queue接口或者使用LinkedList类来实现队列。 5. 树(Tree):树是一种非线性的数据结构,它由节点和边组成,每个节点可以有多个子节点。在Java中,常见的树结构包括二叉树、二叉搜索树(BST)、AVL树、红黑树等。 6. 图(Graph):图是一种由节点和边组成的数据结构,节点表示实体,边表示实体之间的关系。在Java中,可以使用邻接矩阵或邻接表来表示图,并通过深度优先搜索(DFS)或广度优先搜索(BFS)等算法来遍历图。 这些只是数据结构中的一部分,Java还提供了其他更复杂的数据结构算法库,可以根据具体需求选择合适的数据结构。希望以上图解能够帮助你更好地理解数据结构在Java中的实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 71
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知心宝贝

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值