赞
踩
String串是指零个or多个任意字符串组成的有限序列。
ADT String { 数据对象: 数据关系: 基本操作: StrAssign(&T, chars); StrCompare(S, T); StrLength(s); Concat(&T, S1, S2); SubString(&Sub, S, pos, len); StrCopy(&T, S); StrEmpty(S); ClearString(&S); Index(S, T, pos);//字符串匹配算法 Replace(&S, T, V); StrInsert(&S, pos, T); StrDelete(&S, pos, len); DestroyString(&S); } ADT String
串中元素逻辑关系与线性表相同,串可以采用与线性表相同的存储结构:
#define MAXLEN 255
typedef struct{
char ch[MAXLEN + 1];//存储串的一维数组
int length;//串当前的长度
}SString;
块链结构对普通的链串进行优化,提高存储密度:
#define CHUNKSIZE 80 //块的大小
typedef struct Chunk {
char ch[CHUNKSIZE];
struct Chunk *next;
}Chunk;
typedef struct {
Chunk *head, *tail;//串的头指针和尾指针
int curlen;//串的当前长度
}LString;//字符串的块链结构
注意:在实际中相较于链串,顺序串使用更多(对字符串的插入、删除运算较少,顺序结构更利于匹配、查找操作)
Btute-Force算法(模式匹配算法)采用了穷举法的思路:从主串的每一个字符开始依次进行匹配。
j=1
、i=i-j+2
)//写法1:从主串的第一个位置开始查找 int Index_BF(SString S, SString T) { int i = 1, j = 1; while (i <= S.length && j <= T.length) { if (S.ch[i] == T.ch[j]) {//主串和子串匹配则加1继续下一个字符 ++i; ++j; } else {//主串和子串不匹配则将指针回溯重新开始下一次匹配 i = i - j + 2; j = 1; } } if (j >= T.length) {//返回匹配的第一个字符的下标 return i - T.length; } else { return 0; } }
//写法2:从主串的pos位置开始查找 int Index_BF(SString S, SString T, int pos) { int i = pos, j = 1; while (i <= S.length && j <= T.length) { if (S.ch[i] == T.ch[j]) {//主串和子串匹配则加1继续下一个字符 ++i; ++j; } else {//主串和子串不匹配则将指针回溯重新开始下一次匹配 i = i - j + 2; j = 1; } } if (j >= T.length) {//返回匹配的第一个字符的下标 return i - T.length; } else { return 0; } }
O(m)
,O(n-m)*m + m
,(n*m)
KMP算法相较于BF算法中i
指针可不必回溯、j
指针尽量减少回溯步数,算法时间复杂度可提速到O(n+m)
定义next[j]
函数,用于确定当模式中第j
个字符与主串中相应字符失配时需要回溯的位置,回溯规则如下:
int Index_KMP(SString S, SString T, int pos) { int i = pos, j = 1; while (i < S.length && j < T.legngth) { if (j == 0 || S.ch[i] == T.ch[j]) { ++i; ++j; } else { j = next[j];//根据j的值在next表中查找,获取j指针的回溯位置 } } if (j > T.length) { return i - T.length; } else { return 0; } } //next表的计算方法 void getNext(SString T, int &next[]) { int i = 1, j = 0; int 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]; } } }
针对KMP算法中的next函数进行改进:根据next值求出nextval的值
int Index_KMP(SString S, SString T, int pos) { int i = pos, j = 1; while (i < S.length && j < T.legngth) { if (j == 0 || S.ch[i] == T.ch[j]) { ++i; ++j; } else { j = next[j];//根据j的值在next表中查找,获取j指针的回溯位置 } } if (j > T.length) { return i - T.length; } else { return 0; } } //next表的计算方法 void getNext(SString T, int &next[]) { int i = 1, j = 0; int next[1] = 0; while (i < T.length) { if (j == 0 || T.ch[i] == T.ch[j]) { ++i; ++j; if (T.ch[i] != T.ch[j]) nextval[i] = j; else nextval[i] = nextval[j]; } else { j = nextval[j]; } } }
研究者将人的DNA和病毒DNA均表示成由一些字幕组成的字符串序列,
然后检测某种病毒DNA序列是否在患者的DNA序列中出现过(如果出现过则此人感染了病毒,否则没有感染病毒)
注意:人的DNA序列式线性的,而病毒的DNA序列是环状的
数组:按照一定格式排列起来的,具有相同类型的数据元素的集合。
typedef int array[m][n];
typedef int array1[n];
typedef array1 array2[m];//m行n列的二维数组
由于数组结构固定维数与界数基本不变且一般不作插入删除操作,所以很少采用链式存储结构(常采用顺序存储结构表示数组)。
因此在存储数组结构之前,需要解决将多维关系映射到一维关系的问题。
二维数组有两种顺序存储方式:
以行序为主序的顺序存储:
设数组存储位置LOC(0,0)
每个元素需要L个存储单元,则a[i][j]
的存储位置为LOC(i,j)=LOC(0,0)+(n*i+j)*L
页优先的顺序存储:
设数组存储位置LOC(0,0,0)
每个元素需要L个存储单元,且各维元素的个数为m1,m2,m3
则a[i][j][k]
的存储位置为LOC(i,j,k)=a + i*m2*m3 + j*m3 + k;
存储方式:只存储上or下三角(包括主对角线)的数据元素,以行序为主序将元素存放在一维数组arr[n(n+1)/2]
中
存储方法:重复的元素常数c可以共享一个元素存储空间,占用n(n+1)/2+1
个空间
存储方式:以对角线的顺序存储
定义:在n行m列的矩阵中有t个非零元素,当t/m*n) ≤ 0.05
时称为该矩阵为稀疏矩阵。
存储方式:只存储各个非零元素的值、行列位置和矩阵的行列数,三元组的不同表示方法可决定稀疏矩阵不同的压缩存储方法。
顺序存储结构:三元组存储
链式存储结构:十字链表存储
在十字链表中矩阵的每1个非零元素用1个结点表示,结点除了(row, col, value)
以外,还需要两个域:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。