1. #!/urs/bin/env python
  2. # -*- coding:utf-8 -*-
  3.  
  4. #异常类
  5. class stringTypeError(TypeError):
  6. pass
  7.  
  8. #节点类
  9. class Node(object):
  10. def __init__(self, elem, next_ = None):
  11. self.elem = elem
  12. self.next = next_
  13. #单链表类
  14. class single_list(object):
  15. def __init__(self):
  16. self._head = None
  17. self._num = 0
  18.  
  19. def __len__(self):
  20. return self._num
  21.  
  22. def prepend(self,elem):
  23. self._head = Node(elem, self._head)
  24. self._num += 1
  25.  
  26. def append(self,elem):
  27. if self._head is None:
  28. self._head = Node(elem)
  29. self._num += 1
  30. return
  31. p = self._head
  32. while p.next:
  33. p = p.next
  34. p.next = Node(elem)
  35. self._num += 1
  36.  
  37. def pop_last(self):
  38. if self._head is None:
  39. raise ValueError("in pop_last")
  40. p = self._head
  41. if p.next is None:
  42. e = p.elem
  43. self._head = None
  44. self._num -= 1
  45. return e
  46. while p.next.next:
  47. p = p.next
  48. e = p.next.elem
  49. p.next = None
  50. self._num -= 1
  51. return e
  52.  
  53. def delitem(self, key):
  54. if key == len(self)-1:
  55. self.pop_last()
  56. elif 0<= key < len(self) - 1:
  57. p = self._head
  58. pre = None
  59. num = -1
  60. while p is not None:
  61. num += 1
  62. if key==num:
  63. if not pre:
  64. self._head = p.next
  65. self._num -= 1
  66. else:
  67. pre.next = p.next
  68. self._num -= 1
  69. break
  70. else:
  71. pre = p
  72. p = p.next
  73. else:
  74. raise IndexError
  75.  
  76. def insert(self, key, elem):
  77. if key>=len(self)-1:
  78. self.append(elem)
  79. elif 0<=key<len(self)-1:
  80. p = self._head
  81. pre = None
  82. num = -1
  83. while p:
  84. num += 1
  85. if num==key:
  86. if not pre:
  87. self._head = Node(elem, self._head)
  88. self._num += 1
  89. else:
  90. pre.next = Node(elem, pre.next)
  91. self._num += 1
  92. break
  93. else:
  94. pre = p
  95. p = p.next
  96. else:
  97. raise IndexError
  98.  
  99. # 打印显示
  100. def printall(self):
  101. p = self._head
  102. while p:
  103. print(p.elem, end="")
  104. if p.next:
  105. print(", ", end="")
  106. p = p.next
  107. print("")
  108.  
  109. #单链表字符串类
  110. class string(single_list):
  111. def __init__(self, value):
  112. self.value = str(value)
  113. single_list.__init__(self)
  114. for i in range(len(self.value)-1,-1,-1):
  115. self.prepend(self.value[i])
  116.  
  117. def length(self):
  118. return self._num
  119.  
  120. def printall(self):
  121. p = self._head
  122. print("字符串结构:",end="")
  123. while p:
  124. print(p.elem, end="")
  125. if p.next:
  126. print("-->", end="")
  127. p = p.next
  128. print("")
  129.  
  130. #朴素的串匹配算法,返回匹配的起始位置
  131. def naive_matching(self, p): #self为目标字符串,t为要查找的字符串
  132. if not isinstance(self, string) and not isinstance(p, string):
  133. raise stringTypeError
  134. m, n = p.length(), self.length()
  135. i, j = 0, 0
  136. while i < m and j < n:
  137. if p.value[i] == self.value[j]:#字符相同,考虑下一对字符
  138. i, j = i+1, j+1
  139. else: #字符不同,考虑t中下一个位置
  140. i, j = 0, j-i+1
  141. if i == m: #i==m说明找到匹配,返回其下标
  142. return j-i
  143. return -1
  144.  
  145. #kmp匹配算法,返回匹配的起始位置
  146. def matching_KMP(self, p):
  147. j, i = 0, 0
  148. n, m = self.length(), p.length()
  149. while j < n and i < m:
  150. if i == -1 or self.value[j] == p.value[i]:
  151. j, i = j + 1, i + 1
  152. else:
  153. i = string.gen_next(p)[i]
  154. if i == m:
  155. return j - i
  156. return -1
  157.  
  158. # 生成pnext表
  159. @staticmethod
  160. def gen_next(p):
  161. i, k, m = 0, -1, p.length()
  162. pnext = [-1] * m
  163. while i < m - 1:
  164. if k == -1 or p.value[i] == p.value[k]:
  165. i, k = i + 1, k + 1
  166. pnext[i] = k
  167. else:
  168. k = pnext[k]
  169. return pnext
  170.  
  171. #把old字符串出现的位置换成new字符串
  172. def replace(self, old, new):
  173. if not isinstance(self, string) and not isinstance(old, string) \
  174. and not isinstance(new, string):
  175. raise stringTypeError
  176.  
  177. #删除匹配的旧字符串
  178. start = self.matching_KMP(old)
  179. for i in range(old.length()):
  180. self.delitem(start)
  181. #末尾情况下时append追加的,顺序为正;而前面的地方插入为前插;所以要分情况
  182. if start<self.length():
  183. for i in range(new.length()-1, -1, -1):
  184. self.insert(start,new.value[i])
  185. else:
  186. for i in range(new.length()):
  187. self.insert(start,new.value[i])
  188.  
  189. if __name__=="__main__":
  190.  
  191. a = string("abcda")
  192. print("字符串长度:",a.length())
  193. a.printall()
  194. b = string("abcabaabcdabdabcda")
  195. print("字符串长度:", b.length())
  196. b.printall()
  197. print("朴素算法_匹配的起始位置:",b.naive_matching(a),end=" ")
  198. print("KMP算法_匹配的起始位置:",b.matching_KMP(a))
  199. c = string("xu")
  200. print("==")
  201. b.replace(a,c)
  202. print("替换后的字符串是:")
  203. b.printall()

今天早上在继续实现replace时,发现一个严重的问题。在我初始化字符串string对象时,使用了self.value = str(value),而我在后面使用匹配算法时,无论是朴素匹配还是KMP匹配

都使用的对象的value值作为比较。所以对象实现replace方法后的start =b.mathcing_KMP(a)后依旧不变,会一直为6.原因在于我使用的是self.value在进行匹配。所以replace后的

链表字符串里的值并没有被利用到,从而发生严重的错误。

改进篇见下一篇博客

数据结构:单链表结构字符串(python版)的更多相关文章

  1. 数据结构:单链表结构字符串(python版)改进

    此篇文章的replace实现了字符串类的多次匹配,但依然有些不足. 因为python字符串对象为不变对象,所以replace方法并不修改原先的字符串,而是返回修改后的字符串. 而此字符串对象时用单链表 ...

  2. 数据结构:单链表结构字符串(python版)添加了三个新功能

    #!/urs/bin/env python # -*- coding:utf-8 -*- #异常类 class stringTypeError(TypeError): pass #节点类 class ...

  3. 数据结构:栈 顺序表方法和单链表方法(python版)

    #!/usr/bin/env python # -*- coding:utf-8 -*- class StackUnderflow(ValueError): pass #链表节点 class Node ...

  4. python算法与数据结构-单链表(38)

    一.链表 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括 ...

  5. python实现数据结构单链表

    #python实现数据结构单链表 # -*- coding: utf-8 -*- class Node(object): """节点""" ...

  6. 数据结构之线性表(python版)

    数据结构之线性表(python版) 单链表 1.1  定义表节点 # 定义表节点 class LNode(): def __init__(self,elem,next = None): self.el ...

  7. C语言数据结构-单链表的实现-初始化、销毁、长度、查找、前驱、后继、插入、删除、显示操作

    1.数据结构-单链表的实现-C语言 typedef struct LNode { int data; struct LNode* next; } LNode,*LinkList; //这两者等价.Li ...

  8. 数据结构——单链表java简易实现

    巩固数据结构 单链表java实现 单链表除了表尾 每个几点都有一个后继 结点有数据和后继指针组成  通过构建表头和表尾(尾部追加需要)两个特殊几点 实现单链表的一些操作,代码如下 package co ...

  9. C# 数据结构--单链表

    什么是单链表 这两天看到很多有关单链表的面试题,对单链表都不知道是啥的我.经过学习和整理来分享一下啥是单链表和单链表的一些基本使用方法.最后看些网上有关单链表的面试题代码实例. 啥是单链表? 单链表是 ...

随机推荐

  1. 利用Hexo搭建个人博客-博客初始化篇

    上一篇博文 <利用Hexo搭建个人博客-环境搭建篇> 中,我们讲解了利用Hexo搭建个人博客应该要配置哪些环境.相信大家已经迫不及待的想要知道接下来应该要怎么把自己的博客搭起来了,下面,让 ...

  2. 七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL

    本节又带了一些常用的,却很难理解的问题,本节从文件上传功能的实现引出了线程使用,介绍了线程饥饿的解决方法,异常处理方法,了解RouteTable自定义路径 . 系列文章 七天学会ASP.NET MVC ...

  3. TODO:小程序的春天你想做什么

    TODO:小程序的春天你想做什么 微信小程序是一种全新的连接用户与服务的方式,它可以在微信内被便捷地获取和传播,同时具有出色的使用体验. 初步了解小程序的特点 导航明确,来去自如 统一稳定, 视觉规范 ...

  4. edit

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. iOS-网络基础

    概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博.微信等,这些应用本身可能采用iOS开发,但是所有的数据支撑都是基于后台网络服务器的.如今,网络编程越来越普遍,孤立的应用通常是没有生命力 ...

  6. Nginx与Apache比较

    Nginx特点:高性能epoll 异步非阻塞多个连接(万级别)可以对应一个进程 支持反向代理支持7层负载均衡静态文件.反向代理.前端缓存等处理方便支持高并发连接,每秒最多的并发连接请求理论可以达到 5 ...

  7. Vue脚手架工具vue-cli和调试组件vue-devtools

    https://github.com/vuejs/vue-cli npm install vue-cli -g vue init webpack my-project cd my-project // ...

  8. Sublime 快捷键

    语法快捷键: 后代:> 缩写:nav>ul>li <nav> <ul> <li></li> </ul> </nav& ...

  9. WPF 后台读取样式文件

    ResourceDictionary dic = new ResourceDictionary { Source = new Uri("Styles.xaml",UriKind.R ...

  10. Minor【 PHP框架】6.代理

    框架Github地址:github.com/Orlion/Minor (如果觉得还不错给个star哦(^-^)V) 框架作者: Orlion 知乎:https://www.zhihu.com/peop ...