数据结构:单链表结构字符串(python版)
#!/urs/bin/env python
# -*- coding:utf-8 -*- #异常类
class stringTypeError(TypeError):
pass #节点类
class Node(object):
def __init__(self, elem, next_ = None):
self.elem = elem
self.next = next_
#单链表类
class single_list(object):
def __init__(self):
self._head = None
self._num = 0 def __len__(self):
return self._num def prepend(self,elem):
self._head = Node(elem, self._head)
self._num += 1 def append(self,elem):
if self._head is None:
self._head = Node(elem)
self._num += 1
return
p = self._head
while p.next:
p = p.next
p.next = Node(elem)
self._num += 1 def pop_last(self):
if self._head is None:
raise ValueError("in pop_last")
p = self._head
if p.next is None:
e = p.elem
self._head = None
self._num -= 1
return e
while p.next.next:
p = p.next
e = p.next.elem
p.next = None
self._num -= 1
return e def delitem(self, key):
if key == len(self)-1:
self.pop_last()
elif 0<= key < len(self) - 1:
p = self._head
pre = None
num = -1
while p is not None:
num += 1
if key==num:
if not pre:
self._head = p.next
self._num -= 1
else:
pre.next = p.next
self._num -= 1
break
else:
pre = p
p = p.next
else:
raise IndexError def insert(self, key, elem):
if key>=len(self)-1:
self.append(elem)
elif 0<=key<len(self)-1:
p = self._head
pre = None
num = -1
while p:
num += 1
if num==key:
if not pre:
self._head = Node(elem, self._head)
self._num += 1
else:
pre.next = Node(elem, pre.next)
self._num += 1
break
else:
pre = p
p = p.next
else:
raise IndexError # 打印显示
def printall(self):
p = self._head
while p:
print(p.elem, end="")
if p.next:
print(", ", end="")
p = p.next
print("") #单链表字符串类
class string(single_list):
def __init__(self, value):
self.value = str(value)
single_list.__init__(self)
for i in range(len(self.value)-1,-1,-1):
self.prepend(self.value[i]) def length(self):
return self._num def printall(self):
p = self._head
print("字符串结构:",end="")
while p:
print(p.elem, end="")
if p.next:
print("-->", end="")
p = p.next
print("") #朴素的串匹配算法,返回匹配的起始位置
def naive_matching(self, p): #self为目标字符串,t为要查找的字符串
if not isinstance(self, string) and not isinstance(p, string):
raise stringTypeError
m, n = p.length(), self.length()
i, j = 0, 0
while i < m and j < n:
if p.value[i] == self.value[j]:#字符相同,考虑下一对字符
i, j = i+1, j+1
else: #字符不同,考虑t中下一个位置
i, j = 0, j-i+1
if i == m: #i==m说明找到匹配,返回其下标
return j-i
return -1 #kmp匹配算法,返回匹配的起始位置
def matching_KMP(self, p):
j, i = 0, 0
n, m = self.length(), p.length()
while j < n and i < m:
if i == -1 or self.value[j] == p.value[i]:
j, i = j + 1, i + 1
else:
i = string.gen_next(p)[i]
if i == m:
return j - i
return -1 # 生成pnext表
@staticmethod
def gen_next(p):
i, k, m = 0, -1, p.length()
pnext = [-1] * m
while i < m - 1:
if k == -1 or p.value[i] == p.value[k]:
i, k = i + 1, k + 1
pnext[i] = k
else:
k = pnext[k]
return pnext #把old字符串出现的位置换成new字符串
def replace(self, old, new):
if not isinstance(self, string) and not isinstance(old, string) \
and not isinstance(new, string):
raise stringTypeError #删除匹配的旧字符串
start = self.matching_KMP(old)
for i in range(old.length()):
self.delitem(start)
#末尾情况下时append追加的,顺序为正;而前面的地方插入为前插;所以要分情况
if start<self.length():
for i in range(new.length()-1, -1, -1):
self.insert(start,new.value[i])
else:
for i in range(new.length()):
self.insert(start,new.value[i]) if __name__=="__main__": a = string("abcda")
print("字符串长度:",a.length())
a.printall()
b = string("abcabaabcdabdabcda")
print("字符串长度:", b.length())
b.printall()
print("朴素算法_匹配的起始位置:",b.naive_matching(a),end=" ")
print("KMP算法_匹配的起始位置:",b.matching_KMP(a))
c = string("xu")
print("==")
b.replace(a,c)
print("替换后的字符串是:")
b.printall()
今天早上在继续实现replace时,发现一个严重的问题。在我初始化字符串string对象时,使用了self.value = str(value),而我在后面使用匹配算法时,无论是朴素匹配还是KMP匹配
都使用的对象的value值作为比较。所以对象实现replace方法后的start =b.mathcing_KMP(a)后依旧不变,会一直为6.原因在于我使用的是self.value在进行匹配。所以replace后的
链表字符串里的值并没有被利用到,从而发生严重的错误。
改进篇见下一篇博客
数据结构:单链表结构字符串(python版)的更多相关文章
- 数据结构:单链表结构字符串(python版)改进
此篇文章的replace实现了字符串类的多次匹配,但依然有些不足. 因为python字符串对象为不变对象,所以replace方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...
- 数据结构:单链表结构字符串(python版)添加了三个新功能
#!/urs/bin/env python # -*- coding:utf-8 -*- #异常类 class stringTypeError(TypeError): pass #节点类 class ...
- 数据结构:栈 顺序表方法和单链表方法(python版)
#!/usr/bin/env python # -*- coding:utf-8 -*- class StackUnderflow(ValueError): pass #链表节点 class Node ...
- python算法与数据结构-单链表(38)
一.链表 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括 ...
- python实现数据结构单链表
#python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" ...
- 数据结构之线性表(python版)
数据结构之线性表(python版) 单链表 1.1 定义表节点 # 定义表节点 class LNode(): def __init__(self,elem,next = None): self.el ...
- C语言数据结构-单链表的实现-初始化、销毁、长度、查找、前驱、后继、插入、删除、显示操作
1.数据结构-单链表的实现-C语言 typedef struct LNode { int data; struct LNode* next; } LNode,*LinkList; //这两者等价.Li ...
- 数据结构——单链表java简易实现
巩固数据结构 单链表java实现 单链表除了表尾 每个几点都有一个后继 结点有数据和后继指针组成 通过构建表头和表尾(尾部追加需要)两个特殊几点 实现单链表的一些操作,代码如下 package co ...
- C# 数据结构--单链表
什么是单链表 这两天看到很多有关单链表的面试题,对单链表都不知道是啥的我.经过学习和整理来分享一下啥是单链表和单链表的一些基本使用方法.最后看些网上有关单链表的面试题代码实例. 啥是单链表? 单链表是 ...
随机推荐
- Web3DGame之路,Babylonjs 和TypeScript学习笔记(二)
先来认识一下Babylonjs,由于基于webgl来开发,所以先介绍一下基础知识. Webgl是一个html标准,他要在canvas元素上初始化. Html页面上的准备 所以我们先从html页面开始看 ...
- 老司机学新平台 - Xamarin Forms开发框架二探 (Prism vs MvvmCross)
在上一篇Xamarin开发环境及开发框架初探中,曾简单提到MvvmCross这个Xamarin下的开发框架.最近又评估了一些别的,发现老牌Mvvm框架Prism现在也支持Xamarin Forms了, ...
- [备忘]检索 COM 类工厂中 CLSID 为 {91493441-5A91-11CF-8700-00AA0060263B} 的组件时失败解决方法
检索 COM 类工厂中 CLSID 为 {91493441-5A91-11CF-8700-00AA0060263B} 的组件时失败,原因是出现以下错误: 80070005 在CSDN上总是有网友问这个 ...
- css水平居中那点事
昨晚深夜写了css垂直居中那点事,今晚该写他的兄弟篇:css水平居中那点事了..…^^ 其实本来这两个可以连在一起写,可是为了不要搞混,为了让思路更清晰,最后决定还是分开来些比较好...这样以后也有利 ...
- Spark读取HBase
背景:公司有些业务需求是存储在HBase上的,总是有业务人员找我要各种数据,所以想直接用Spark( shell) 加载到RDD进行计算 摘要: 1.相关环境 2.代码例子 内容 1.相关环境 Spa ...
- 2013 duilib入门简明教程 -- 简单控件介绍 (12)
前面的教程应该让大家对duilib的整体有所映像了,下面就来介绍下duilib具体控件的使用. 由于官方没有提供默认的控件样式,所以我就尽量使用win7或者XP自带的按钮样式了,虽然界 ...
- java IO流 之 字节流
一.file类的常用操作 File file=new File("E:\\test\\javaIo"); System.out.println(file.isDirectory() ...
- SQL Server 创建数据库邮件
一. 背景 数据库发邮件通知数据库的运行状态(状态可以通过JOB形式获取)和信息,达到预警的效果. 二. 基础知识 msdb系统数据库保存有关Job,Database Mail,Nodifyicati ...
- C#设计模式系列:备忘录模式(Memento)
1.备忘录模式简介 1.1>.定义 备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可以将该对象恢复到原先保存的状态. 1.2>.使用频率 ...
- WPF绘制折线
WPF后台绘制折线,填充到一个GRID下 private void btnPreview_Click(object sender, RoutedEventArgs e) { GridImg.Child ...