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. #获取字符串对象值的列表,方便下面使用
  121. def get_value_list(self):
  122. l = []
  123. p = self._head
  124. while p:
  125. l.append(p.elem)
  126. p = p.next
  127. return l
  128.  
  129. def printall(self):
  130. p = self._head
  131. print("字符串结构:",end="")
  132. while p:
  133. print(p.elem, end="")
  134. if p.next:
  135. print("-->", end="")
  136. p = p.next
  137. print("")
  138.  
  139. #朴素的串匹配算法,返回匹配的起始位置
  140. def naive_matching(self, p): #self为目标字符串,t为要查找的字符串
  141. if not isinstance(self, string) and not isinstance(p, string):
  142. raise stringTypeError
  143. m, n = p.length(), self.length()
  144. i, j = 0, 0
  145. while i < m and j < n:
  146. if p.get_value_list()[i] == self.get_value_list()[j]:#字符相同,考虑下一对字符
  147. i, j = i+1, j+1
  148. else: #字符不同,考虑t中下一个位置
  149. i, j = 0, j-i+1
  150. if i == m: #i==m说明找到匹配,返回其下标
  151. return j-i
  152. return -1
  153.  
  154. #kmp匹配算法,返回匹配的起始位置
  155. def matching_KMP(self, p):
  156. j, i = 0, 0
  157. n, m = self.length(), p.length()
  158. while j < n and i < m:
  159. if i == -1 or self.get_value_list()[j] == p.get_value_list()[i]:
  160. j, i = j + 1, i + 1
  161. else:
  162. i = string.gen_next(p)[i]
  163. if i == m:
  164. return j - i
  165. return -1
  166.  
  167. # 生成pnext表
  168. @staticmethod
  169. def gen_next(p):
  170. i, k, m = 0, -1, p.length()
  171. pnext = [-1] * m
  172. while i < m - 1:
  173. if k == -1 or p.get_value_list()[i] == p.get_value_list()[k]:
  174. i, k = i + 1, k + 1
  175. pnext[i] = k
  176. else:
  177. k = pnext[k]
  178. return pnext
  179.  
  180. #把old字符串出现的位置换成new字符串
  181. def replace(self, old, new):
  182. if not isinstance(self, string) and not isinstance(old, string) \
  183. and not isinstance(new, string):
  184. raise stringTypeError
  185.  
  186. while self.matching_KMP(old) >= 0:
  187. #删除匹配的旧字符串
  188. start = self.matching_KMP(old)
  189. print("依次发现的位置:",start)
  190. for i in range(old.length()):
  191. self.delitem(start)
  192. #末尾情况下时append追加的,顺序为正;而前面的地方插入为前插;所以要分情况
  193. if start<self.length():
  194. for i in range(new.length()-1, -1, -1):
  195. self.insert(start,new.value[i])
  196. else:
  197. for i in range(new.length()):
  198. self.insert(start,new.value[i])
  199.  
  200. #self字符串里第一个属于字符串another的字符所在结点的位置
  201. def find_in(self, another):
  202. if not isinstance(self, string) and not isinstance(another, string):
  203. raise TypeError
  204. for i in range(self.length()):
  205. if self.get_value_list()[i] in another.get_value_list():
  206. return i
  207. return -1 #没有发现
  208.  
  209. # self字符串里第一个不属于字符串another的字符所在结点的位置
  210. def find_not_in(self, another):
  211. if not isinstance(self, string) and not isinstance(another, string):
  212. raise TypeError
  213. for i in range(self.length()):
  214. if self.get_value_list()[i] not in another.get_value_list():
  215. return i
  216. return -1 #没有发现
  217.  
  218. #从self里删除串another里的字符
  219. def remove(self, another):
  220. if not isinstance(self, string) and not isinstance(another, string):
  221. raise TypeError
  222. while self.find_in(another)>=0:
  223. self.delitem(self.find_in(another))
  224.  
  225. if __name__=="__main__":
  226.  
  227. a = string("aba")
  228. print("字符串长度:",a.length())
  229. a.printall()
  230. b = string("abaaaabadaba")
  231. print("字符串长度:", b.length())
  232. b.printall()
  233. print("朴素算法_匹配的起始位置:",b.naive_matching(a),end=" ")
  234. print("KMP算法_匹配的起始位置:",b.matching_KMP(a))
  235. c = string("xu")
  236. print("==")
  237. b.replace(a,c)
  238. print("替换后的字符串是:")
  239. b.printall()
  240. print(b.get_value_list())
  241. d = string("dfga")
  242. print("第一个属于another字符的位置:",b.find_in(d))
  243. e = string("ad")
  244. print("第一个不属于another字符的位置:", b.find_not_in(e))
  245. b.remove(e)
  246. b.printall()

数据结构:单链表结构字符串(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实现数据结构单链表

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

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

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

  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. 数据结构——单链表(singly linked list)

    /* singlyLinkedList.c */ /* 单链表 */ /* 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素. */ #include <stdio ...

随机推荐

  1. 字符串匹配算法 - KMP

    前几日在微博上看到一则微博是说面试的时候让面试者写一个很简单的字符串匹配都写不出来,于是我就自己去试了一把.结果写出来的是一个最简单粗暴的算法.这里重新学习了一下几个经典的字符串匹配算法,写篇文章以巩 ...

  2. [变]C#谜题(1-10)表达式篇

    [变]C#谜题(1-10)表达式篇 最近偶然发现了<Java谜题>,很有意思,于是转到C#上研究一下. 本篇是关于表达式的一些内容. 谜题1:奇数性(负数的取模运算) 下面的方法意图确定它 ...

  3. ASP.NET MVC Routing学习笔记(一)

    Routing在ASP.NET MVC中是非常核心的技术,属于ASP.NET MVC几大核心技术之一,在使用Routing之前,得先引入System.Web.Routing,但其实不用这么麻烦,因为在 ...

  4. SSISDB5:Parameter

    Parameter 是Package 提供给外界的接口,通过传递不同的Parameter value,能够动态控制 Package 执行不同的Task或container,产生不同的结果. 一,Par ...

  5. SSIS 数据源组件的External Metadata和Advanced Property

    1,SSIS的组件属性ValidateExternalMetadata 如果一个Destination组件使用的是上游创建的staging table,那么必须设置 ValidateExternalM ...

  6. C#设计模式系列:享元模式(Flyweight)

    当频繁地从数据源读取数据时,读出的内容存在重复,那么需要使用享元模式(Flyweight)来提高内存效率,Flyweight模式将节省更多空间,共享的Flyweight越多,空间节省越大. 1.享元模 ...

  7. Android studio每次启动卡在fetching Android sdk compoment information的解决方案

    网上有人给出了方案:1)进入刚安装的Android Studio目录下的bin目录.找到idea.properties文件,用文本编辑器打开.2)在idea.properties文件末尾添加一行: d ...

  8. 深入理解DOM事件机制系列第三篇——事件对象

    × 目录 [1]获取 [2]事件类型 [3]事件目标[4]事件代理[5]事件冒泡[6]事件流[7]默认行为 前面的话 在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事 ...

  9. Android总结之json解析(FastJson Gson 对比)

    前言: 最近为了统一项目中使用的框架,发现项目中用到了两种json解析框架,他们就是当今非常主流的json解析框架:google的Gson 和阿里巴巴的FastJson,为了废除其中一个所以来个性能和 ...

  10. 从零开始编写自己的C#框架(6)——SubSonic3.0插件介绍(附源码)

    前面几章主要是概念性的东西为主,向初学者们介绍项目开始前的一些知识与内容,从本章开始将会进入实操阶段,希望跟着本系统学习的朋友认真按说明做好每一步操作(对于代码最好是直接照着文档内容在你的IDE中打一 ...