数据结构-串 2021/8/7 17:48
串的顺序储存
串的顺序储存(静态)
#include <iostream>
using namespace std;
#define MAXLEN 255
typedef struct {
char ch[MAXLEN];
int length;
}SString;
/*
* 串的初始化
*/
bool strInit(SString& str)
{
str.length = 0;
return true;
}
/*
* 求子串,这里的串第零位是空闲的
*/
bool SubString(SString& Sub, SString s, int pos, int len)
{
if (pos + len - 1 > s.length)//判断所求子串范围知是否越界
return false;
for (int i = pos; i < pos+len; i++)
{
Sub.ch[i-pos+1] = s.ch[i];
}
Sub.length = len;
return true;
}
/*
* 比较字符串的大小,按照字典排列中的方法比大小
*/
int StrCompare(SString S, SString T)
{
for (int i = 0; i <= S.length && i <= T.length; i++)
{
if (S.ch[i] != T.ch[i])
return S.ch[i] - T.ch[i];
}
return S.length - T.length;
}
/*
* 定位,取子串比较
*/
int Index(SString S, SString T)
{
int i = 1;
int n = S.length, m = T.length;
SString Sub;//用在暂存子串
while (i <= n - m)
{
SubString(Sub, S, i, m);//先取子串
if (StrCompare(Sub, T) == 0)//子串与待比较的串进行比较
return i;
else
i++;
}
return 0;
}
/*
* 定位,朴素模式算法
*/
int index(SString S, SString T)
{
int k = 1;
int i = 1, j = 1;
while (i <= S.length && j <= T.length)
{
if (S.ch[i] == T.ch[j])
{
i++;
j++;
}
else
{
k++;
i = k;
j = 1;
}
}
if (j > T.length)//只有当匹配成功才会出现J越界
return k;
else
return 0;
}
/*
* KMP,KMP算法的思想是:当发现当前模式串和原串不匹配时,不仅仅意味着当前不匹配,更意味着模式串前面已经比较过的部分是匹配的,我们可以利用这些信息简化分析
* 通过对模式串的分析我们可以知道当前的字符不匹配的话,指向模式串指针回退到模式串哪个位置,达到原串指针不回退的效果
*/
int indexKMP(SString S, SString T,int next[])
{
int k = 1;
int i = 1, j = 1;
while (i <= S.length && j <= T.length)
{
if (j==0||S.ch[i] == T.ch[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j > T.length)//只有当匹配成功才会出现J越界
return k;
else
return 0;
}
/*
* 求字符串对应的next数组(求前缀子串和后缀子串相等的最大长度),并优化成nextval(将next数组优化成nextval数组:当next数组中第i个元素匹配失败,
*跳转匹配第j个元素而第j个元素又和i一样时,可以直接将j的next值赋给i的next)
*/
void get_nextval(SString T, int nextval[])
{
int i = 1, j = 0;
int next[MAXLEN];
next[1] = 0;
while (i < T.length)
{
if (j == 0 || T.ch[i] == T.ch[j])
{
++i; ++j;
next[i] = j;
}
else
j = next[j];
}
//以上是求出next数组的过程,以下是转化成nextval数组的过程
nextval[1] = 0;
for (int j = 2; j < T.length; j++)
{
if (T.ch[j] == T.ch[next[j]])
{
nextval[j] = nextval[next[j]];
}
else
nextval[j] = next[j];
}
}
1.初始化:将串的长度length值赋0,这样就实现了逻辑上的初始化
2.求子串:上面的代码对应的是串的第0位空闲的情况(即S[1]就代表第一个字符)从原串中的第pos位逐个往后复制len位即可
3.比较字符串的大小:按照字典序比较字符串的大小,逐个往后比对,当字符不同时返回ASCII码值之差。
4.定位模式串位置(1):取子串比较,从原串中逐个取模式串长度的子串,比较该子串和模式串的大小关系
5.定位模式串位置(2):朴素模式算法,从原串第一个开始逐个往后比对,遇到不匹配的情况就返回到原串的下一个位置再逐一比对
6.定位模式串位置(3):KMP算法,算法思想实现方式,next数组优化成nextval的原因以及方法在上述代码注释中
串的顺序储存(动态)
#include <iostream>
using namespace std;
#define MAXLEN 255
typedef struct {
char *ch;
int length;
}HString;
/*
* 串的初始化
*/
bool strInit(HString& str)
{
str.ch = (char *)malloc(sizeof(char));
str.length = 0;
return true;
}
串的动态顺序储存和顺序表的动态储存类似
串的链式储存
#include <iostream>
using namespace std;
#define MAXLEN 255
//typedef struct StringNode{//这样的方法储存的话储存密度低,可以将储存的数据位变为多个,此时需要注意,当某信息位不满时用特殊符号标记
// char ch;
// struct StringNode* next;
//}StringNode,*String;
typedef struct StringNode {
char ch[4];
struct StringNode* next;
}StringNode, * String;
/*
* 串的初始化
*/
bool strInit(String& str)
{
str = (StringNode*)malloc(sizeof(StringNode));
str->next = NULL;
return true;
}
串的链式储存可以再数据位储存对个数据解决储存密度低的问题.
考研加油!