本文主要是描述数据结构中串的数据类型,并且通过Python语言对其实现。并且撰写了简单的模式匹配算法Brute force模式匹配算法;下篇有关的文章将书写KMP算法的实现过程,但数据结构仍然沿用本篇文章的代码。
# 1、串的抽象数据类型 #
from abc import ABCMeta,abstractmethod,abstractproperty
class IString(metaclass = ABCMeta):
@abstractmethod
def clear(self):
'''将字符串置成空串'''
pass
@abstractmethod
def isEmpty(self):
'''判断是否为空串'''
pass
@abstractmethod
def length(self):
'''返回串的长度'''
pass
@abstractmethod
def charAt(self,i):
'''读取并返回串中的第i个数据元素'''
pass
@abstractmethod
def subString(self,begin,end):
'''返回位序号从begin到end-1的子串'''
pass
@abstractmethod
def insert(self,i,str):
'''在第i个字符之前插入子串str'''
pass
@abstractmethod
def delete(self,begin,end):
'''删除位序号从begin到end-1的子串'''
pass
@abstractmethod
def compareTo(self,str):
'''比较str和当前字符串的大小'''
pass
@abstractmethod
def indexOf(self,str,begin):
'''从位序号为begin的字符开始搜索与str相等的子串'''
pass
@abstractmethod
def display(self):
'''打印字符串'''
pass
# 2、顺序串的实现 #
from IString import *
import time
'''
顺序串,其逻辑结构与顺序表类似
存储结构选用数组;
这里拿顺序串举例而不用链串的原因为:
链串可以分为单字符链表和块链(即一个子串占一个节点),单字符链串存储效率低,而块链操作十分复杂。博主也未深究;
'''
class SqString(IString):
'''
初始化
'''
def __init__(self,obj=None):
if obj is None:
self.strValue = [] #用数组来存放串的值
self.curLen = 0 #长度
elif isinstance(obj,str): #以字符串构造串 isinstance() 该函数用来判断是否是已知类型 如 >>isinstance (a,int) // 判断a是否是int类型 返回布尔值 True 或者 False
self.curLen = len(obj) # 以字符列表构造串
self.strValue = [None] * self.curLen
for i in range(self.curLen):
self.strValue[i] = obj[i]
elif isinstance(obj,list): #以字符列表构造串
self.curLen = len(obj)
self.strValue = [None] * self.curLen
for i in range(self.curLen):
self.strValue[i] = obj[i]
def clear(self):
'''
将字符串置成空串
'''
self.curLen = 0
def isEmpty(self):
'''
判断是否为空串
'''
return self.curLen == 0
def length(self):
'''
返回串的长度
'''
return self.curLen
def charAt(self,i):
'''
读取并返回串中的第i个位置数据元素
'''
if i<0 or i>=self.curLen:
raise IndexError("String index out of range")
return self.strValue[i]
def allocate(self,newCapacity):
'''
将串的长度扩充为newCapacity
'''
tmp = self.strValue
self.strValue = [None] * newCapacity #顺序表是预分配,所以扩充长度需要重新填入元素
for i in range(self.curLen):
self.strValue[i] = tmp[i]
#return self.strValue
def subString(self,begin,end):
'''
返回位序号从begin到end-1的子串
1、判断参数是否合法(越界)
2、构建一个空列表
3、循环赋值
5、返回字符串
'''
if begin<0 or begin>=end or end>self.curLen:
raise IndexError("参数不合法")
tmp = [None] * (end - begin) # 空列表
for i in range(begin,end):
tmp[i-begin] = self.strValue[i] #复制子串
return SqString(tmp)
def insert(self,i,str):
'''
在第i个字符之前插入子串str
判断插入位置是否合法
元素后移
字符串插入
长度增加
'''
if i<0 or i>self.curLen:
raise IndexError("插入位置不合法")
length = str.length()
newCapacity = self.curLen + length
self.allocate(newCapacity)
for j in range(self.curLen-1,i-1,-1):
self.strValue[j+length] = self.strValue[j]
for j in range(i,i+length):
self.strValue[j] = str.charAt(j-i)
self.curLen = newCapacity
def delete(self,begin,end):
'''
删除位序号从begin到end-1的子串
1、判断删除位置是否合法;{例如: begin<0 , begin>end ,end > curLen}
2、交换删除位置的值
3、缩短长度
'''
if begin<0 or begin>=end or end>self.curLen:
raise IndexError("删除不合法")
for i in range(begin,end):
self.strValue[i] = self.strValue[i+end-begin]
self.curLen = self.curLen-(end - begin)
def compareTo(self,str):
'''
比较str和当前字符串的大小
字符串比较需要逐字比较
'''
n = self.curLen if self.curLen<str.length() else str.length()
for i in range(n):
if self.strValue[i]>str.charAt(i):
return 1
if self.strValue[i] < str.charAt(i):
return -1
if self.curLen > str.length():
return 1
elif self.curLen < str.length():
return -1
return 0
def indexOf(self,str,begin):
'''
从位序号为begin的字符开始搜索与str相等的子串
'''
pass
def display(self):
'''打印字符串'''
for i in range(self.curLen):
print(self.strValue[i],"\t",end='')
print("\n")
# 3、简单模式匹配算法 #
def BF(self,str,begin):
'''
Brute force模式匹配算法
逐一匹配,每次只移动一个位置 匹配失败后从开始匹配的下一个位置开始从新匹配
这么一看时间复杂度为 : O(n*m)
'''
if str.length()<=self.curLen and str is not None and self.curLen>0:
i = begin
length = str.length()
while (i<=self.curLen-length):
for j in range(length):
if str.charAt(j)!=self.strValue[j+i]:
i+=1
break
elif j == length-1:
return i
return -1
本文的一些想法摘自天勤辅导书和王道辅导书;以及一些Python相关的数据结构辅导书