Skip to content

Commit 61c7b01

Browse files
author
ssjssh
committed
1,完成leecode的第三题,第四题还有bug
2,把所有的代码放在ssj包下,因为一些包的命名跟python自带库明名重复,可能会出现一些意想不到的问题。
1 parent 3a21bea commit 61c7b01

14 files changed

+2070
-0
lines changed

src/ssj/string/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env python
2+
# -*- coding:UTF-8
3+
__author__ = 'shenshijun'

src/ssj/string/kmp.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python
2+
# -*- coding:UTF-8
3+
__author__ = 'shenshijun'
4+
5+
6+
def match(origin, pattern):
7+
origin_len = len(origin)
8+
pattern_len = len(pattern)
9+
10+
def build_next():
11+
_next_list = [0 for x in xrange(pattern_len)]
12+
last_match = 0
13+
for cur_index in xrange(1, pattern_len):
14+
while last_match > 0 and pattern[last_match] != pattern[cur_index]:
15+
last_match = _next_list[last_match]
16+
if pattern[last_match] == pattern[cur_index]:
17+
last_match += 1
18+
_next_list[cur_index] = last_match
19+
return _next_list
20+
21+
origin_index, pattern_index = 0, 0
22+
next_list = build_next()
23+
while origin_index < origin_len:
24+
# while需要放在前面,如果放在后面的话且有匹配的情况下pattern[pattern_index]就会越界
25+
while pattern_index > 0 and origin[origin_index] != pattern[pattern_index]:
26+
pattern_index = next_list[pattern_index]
27+
if pattern[pattern_index] == origin[origin_index]:
28+
pattern_index += 1
29+
origin_index += 1
30+
31+
if pattern_index == pattern_len:
32+
return origin_index - pattern_len
33+
34+
35+
def main():
36+
print match("assssbsss", 'sb')
37+
38+
39+
if __name__ == "__main__":
40+
main()

src/ssj/string/rabin-karp.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python
2+
# -*- coding:UTF-8
3+
__author__ = 'shenshijun'
4+
"""
5+
首先计算pattern字符串的hash值,然后在从目标字符串的开头,计算相同长度字符串的hash值。若hash值相同,则表示匹配,若不同,则向右移动一位,计算新的hash值。整个过程,与暴力的字符串匹配算法很相似,
6+
但由于计算hash值时,可以利用上一次的hash值,从而使新的hash值只需要加上新字母的计算,并减去上一次的第一个字母的计算,即可。
7+
Rabin-Karp算法的预处理时间为O(m),最坏情况下该算法的匹配时间为O((n-m+1)m),期望复杂度O(m+n)
8+
"""
9+
10+
11+
def match(origin, pattern):
12+
pattern_len = len(pattern)
13+
14+
def _hash(string, start=0):
15+
hash_code = 0
16+
for x in xrange(pattern_len):
17+
hash_code += ord(string[start + x]) * 2 ** (pattern_len - x - 1)
18+
return hash_code
19+
20+
def _refresh(old_hash, old_char, new_char):
21+
return (old_hash - ord(old_char) * 2 ** (pattern_len - 1)) * 2 + ord(new_char)
22+
23+
def test_equal(start_index):
24+
for x in xrange(pattern_len):
25+
if origin[x + start_index] != pattern[x]:
26+
return False
27+
return True
28+
29+
origin_index = 0
30+
pattern_hash = _hash(pattern)
31+
origin_hash = _hash(origin)
32+
while origin_index < len(origin) - pattern_len - 1:
33+
if pattern_hash == origin_hash and test_equal(origin_index):
34+
return origin_index
35+
else:
36+
print "origin hash:%s,pattern hash:%s" % (origin_hash, pattern_hash)
37+
origin_hash = _refresh(origin_hash, origin[origin_index], origin[origin_index + pattern_len])
38+
origin_index += 1
39+
40+
41+
def main():
42+
print match("sbsfsdgdgfgasbssssfsfdfeferf", 'sb')
43+
44+
45+
if __name__ == "__main__":
46+
main()

src/ssj/string/simple.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env python
2+
# -*- coding:UTF-8
3+
__author__ = 'shenshijun'
4+
5+
6+
def match(origin, pattern):
7+
origin_index, pattern_index = 0, 0
8+
match_flag = True
9+
pattern_len = len(pattern)
10+
while origin_index < len(origin):
11+
for pattern_index in xrange(pattern_len):
12+
if pattern[pattern_index] != origin[origin_index]:
13+
origin_index -= (pattern_index - 1)
14+
match_flag = False
15+
break
16+
else:
17+
origin_index += 1
18+
pattern_index += 1
19+
match_flag = True
20+
21+
if match_flag:
22+
return origin_index - pattern_index
23+
24+
25+
def main():
26+
print match("absabsvbshsbdhhd", 'sb')
27+
28+
29+
if __name__ == "__main__":
30+
main()

src/ssj/tree/BTree.py

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#!/usr/bin/env python
2+
# -*- coding:UTF-8
3+
from ssj.lib import Stack
4+
5+
__author__ = 'shenshijun'
6+
7+
8+
class Node(object):
9+
def __init__(self, is_leaf, keys, childs=None, parent=None):
10+
"""
11+
在真实的实现中应该在加上一个数组表示指向真实数据的指针
12+
keys和childs都是一个数组,分别表示关键字和孩子
13+
"""
14+
self.keys = list(sorted(keys))
15+
self.is_leaf = is_leaf
16+
self.__size = len(self.keys)
17+
if childs is None:
18+
self.childs = [None for x in xrange(0, self.__size)]
19+
self.childs.append(None)
20+
else:
21+
self.childs = childs
22+
self.parent = parent
23+
24+
def __str__(self):
25+
return "".join(['Node(keys=', ",".join(map(lambda key: str(key), self.keys)),
26+
',leaf' if self.is_leaf else ',not leaf',
27+
',childs num=', str(len(self.childs)), ')\n'])
28+
29+
def __len__(self):
30+
return self.__size
31+
32+
def append(self, key):
33+
"""
34+
向B树的节点中插入一个关键字,返回这个关键字的下标
35+
"""
36+
result = self.__size
37+
self.__size += 1
38+
for x in xrange(0, result):
39+
if self.keys[x] > key:
40+
self.keys.insert(x, key)
41+
self.childs.insert(x, None)
42+
return x
43+
self.keys.append(key)
44+
self.childs.append(None)
45+
return result
46+
47+
def search_child(self, instance):
48+
"""
49+
查找小于instance的子树
50+
"""
51+
for x in xrange(0, self.__size):
52+
if self.keys[x] > instance:
53+
return self.childs[x]
54+
return self.childs[self.__size]
55+
56+
57+
class BTree(object):
58+
"""
59+
B树实现,注意,不是二叉树
60+
"""
61+
62+
def __init__(self, load_factor=4, *vargs):
63+
"""Constructor for BTree"""
64+
self.__root = None
65+
self.__load_factor = load_factor
66+
self.__size = len(vargs)
67+
map(self.insert, vargs)
68+
69+
def insert(self, key):
70+
"""
71+
节点插入的时候不需要再检测节点是不是满了,因为load_factor>=2,每次插入节点前调整都是使得节点关键字个数为load_factor-1。
72+
而插入一个关键字之后节点关键字个数是2*load_factor-1或者load_factor
73+
:param key:
74+
:return:
75+
"""
76+
if self.__root is None:
77+
self.__root = Node(True, [key])
78+
return
79+
cur_node = self.__root
80+
while not cur_node.is_leaf:
81+
self.__split(cur_node)
82+
cur_node = cur_node.search_child(key)
83+
left_node, right_node = self.__split(cur_node)
84+
if left_node is None or right_node is None:
85+
# 返回None表示叶节点没有满
86+
cur_node.append(key)
87+
else:
88+
if left_node.keys[-1] < key:
89+
# 说明left_node中的所有节点都比key小,所以把新节点插入到右边
90+
right_node.append(key)
91+
else:
92+
left_node.append(key)
93+
94+
def __split(self, node):
95+
if self.full(node):
96+
parent_node = node.parent
97+
middle_key = node.keys[self.__load_factor - 1]
98+
if parent_node is None:
99+
# 处理根节点
100+
self.__root = Node(False, [])
101+
parent_node = self.__root
102+
parent_middle_index = parent_node.append(middle_key)
103+
left_node = Node(node.is_leaf, node.keys[:self.__load_factor - 1], node.childs[:self.__load_factor],
104+
parent_node)
105+
# 注意设定分裂节点的子节点的父指针
106+
for child in left_node.childs:
107+
if child is not None:
108+
child.parent = left_node
109+
right_node = Node(node.is_leaf, node.keys[self.__load_factor:], node.childs[self.__load_factor:],
110+
parent_node)
111+
for child in right_node.childs:
112+
if child is not None:
113+
child.parent = right_node
114+
parent_node.childs[parent_middle_index] = left_node
115+
parent_node.childs[parent_middle_index + 1] = right_node
116+
self.__root.is_leaf = False
117+
return left_node, right_node
118+
return None, None
119+
120+
def search(self, instance):
121+
return self.__search(self.__root, instance)
122+
123+
def full(self, node):
124+
return len(node) >= (self.__load_factor * 2 - 1)
125+
126+
@classmethod
127+
def __search(cls, root, instance):
128+
cur_node = root
129+
while True:
130+
cur_len = len(cur_node)
131+
x = 0
132+
while x < cur_len and cur_node.keys[x] < instance:
133+
x += 1
134+
if cur_node.keys[x] == instance:
135+
return cur_node, x
136+
elif cur_node.is_leaf:
137+
return None, None
138+
else:
139+
cur_node = cur_node.childs[x]
140+
141+
def min(self):
142+
cur_node = self.__root
143+
while not cur_node.is_leaf:
144+
cur_node = cur_node.childs[0]
145+
return cur_node.keys[0]
146+
147+
def max(self):
148+
cur_node = self.__root
149+
while not cur_node.is_leaf:
150+
cur_node = cur_node.childs[-1]
151+
return cur_node.keys[-1]
152+
153+
def midorder(self, f):
154+
"""
155+
B树中序遍历
156+
:param f:
157+
:return:
158+
"""
159+
result = []
160+
stack = Stack()
161+
cur_node = self.__root
162+
if cur_node.is_leaf:
163+
return map(f, cur_node.keys)
164+
165+
while True:
166+
if cur_node.is_leaf:
167+
# 到叶节点了,开始把叶节点的所有关键字都遍历掉
168+
result.extend(map(f, cur_node.keys))
169+
# 开始从栈中取元素,遍历下一个节点叶节点
170+
if stack.empty():
171+
return result
172+
cur_node, i = stack.pop()
173+
result.append(f(cur_node.keys[i]))
174+
if i < len(cur_node) - 1:
175+
stack.push((cur_node, i + 1))
176+
cur_node = cur_node.childs[i + 1]
177+
else:
178+
stack.push((cur_node, 0))
179+
cur_node = cur_node.childs[0]
180+
return result
181+
182+
def __str__(self):
183+
return "\n".join(self.midorder(lambda s: str(s)))
184+
185+
def test(self):
186+
print "-" * 20
187+
print self.__root
188+
print self.__root.childs[0]
189+
print self.__root.childs[1]
190+
191+
192+
def main():
193+
btree = BTree(3, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U',
194+
'V', 'X', 'Y', 'Z')
195+
print btree
196+
print btree.max()
197+
print btree.min()
198+
199+
200+
if __name__ == "__main__":
201+
main()

src/ssj/tree/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env python
2+
# -*- coding:UTF-8
3+
__author__ = 'shenshijun'

src/ssj/tree/avltree.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env python
2+
# -*- coding:UTF-8
3+
__author__ = 'shenshijun'
4+
5+
6+
class AVLTree(object):
7+
""""""
8+
9+
def __init__(self):
10+
"""Constructor for """
11+
pass

0 commit comments

Comments
 (0)