diff --git a/.gitignore b/.gitignore index 886d710..f7dc621 100755 --- a/.gitignore +++ b/.gitignore @@ -58,4 +58,8 @@ docs/_build/ # PyBuilder target/ -test.py \ No newline at end of file +test.py + +#c out file +*.out +*.exe \ No newline at end of file diff --git a/README.md b/README.md index 23f6a41..372e16d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ algorithm ========= -在阅读算法导论的时候。我用Python写的一些算法,这些算法大部分使用list来作为底层存储数据的结构。但是python的list用的是链表实现,因此有些操作性能不高。 +在阅读算法导论的时候。我用Python写的一些算法,这些算法大部分使用list来作为底层存储数据的结构。 #算法 -------------- ##排序算法:sort文件夹下面 1. 冒泡排序 2. 插入排序 @@ -91,5 +90,14 @@ algorithm 3. Set +未来计划 +===================== +* 在学习redis源码的过程中修改各个数据结构的实现,目的是使用更加精细的规则去提高数据结构的性能 +* 添加更多注释并且格式化代码,注释中注重于设计的思考 +* 添加算法导论中其他高级的数据结构 +* 计划完成一些在线的题库,比如leecode和projecteuler + + + diff --git a/divide_conquer/find_max_sublist_without_ recursion.py b/divide_conquer/find_max_sublist_without_ recursion.py deleted file mode 100755 index e537d77..0000000 --- a/divide_conquer/find_max_sublist_without_ recursion.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# -*-coding:utf-8 -*- -def find_max_sublist(li): - b, max_sum, left, right = 0, 0, 0, 0 - li_len = len(li) - for x in xrange(0, li_len): - if b < 0: - b = li[x] - left = x - else: - b += li[x] - if max_sum < b: - right = x - max_sum = b - - return (left, right, max_sum) - - -def main(): - print find_max_sublist([1, -2, 3, 10, -4, 7, 2, -5]) - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/graph/general_graph.py b/graph/general_graph.py deleted file mode 100644 index 5af1532..0000000 --- a/graph/general_graph.py +++ /dev/null @@ -1,213 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 - -import sys - -reload(sys) -sys.setdefaultencoding('UTF-8') - -from lib import queue -from lib.stack import Stack - -__author__ = 'shenshijun' - - -class Node(object): - """ - 图中存储数据的结点 - """ - - def __init__(self, key, color): - """ - color - -1:白色 - 0:灰色 - 1:黑色 - """ - - self.key = key - self.color = color - self.depth = 0 - self.parent = None - self.start_time = None - self.end_time = None - - def set_gray(self): - self.color = 0 - - def set_black(self): - self.color = 1 - - def set_white(self): - self.color = -1 - - def is_gray(self): - return self.color is 0 - - def is_white(self): - return self.color is -1 - - def is_black(self): - return self.color is 1 - - def __eq__(self, other): - return self.key == other.key and self.color == other.color and self.depth == other.depth - - def __str__(self): - return "".join(['Node(key=', unicode(self.key), - ',depth=', str(self.depth), ',start_time=', str(self.start_time), ',end_time=', - str(self.end_time), - ',color:', 'white' if self.color is -1 else 'gray' if self.color is 0 else 'black', ')']) - - -class GeneralGraph(object): - """ - 使用邻接链表法存储一个通用的图结构。 - 使用一个元组来表示一个图中的边 - 要注意一个实现上的问题:邻接链表中的元素和关键字元素必须指向同一个对象 - """ - - def __init__(self, *vargs): - """ """ - self.__dict = {} - map(self.insert, vargs) - - def insert(self, edge): - start_node = self.__find(edge[0]) - end_node = self.__find(edge[1]) - linked_node = self.__dict.setdefault(start_node, []) - linked_node.append(end_node) - - def delete_edge(self, edge): - start_node = self.__find(edge[0]) - linked_list = self.__dict.get(start_node, []) - for x in xrange(0, len(linked_list)): - if linked_list[x].key == edge[1]: - del linked_list[x] - return True - return False - - def __find(self, instance): - for key_node in self.__dict.iterkeys(): - if key_node.key == instance: - return key_node - node = Node(instance, -1) - self.__dict[node] = [] - return node - - def bfs(self, instance, gray_func, black_func): - """ - 图的广度遍历 - :param gray_func:当节点在灰色的时候遍历的函数 - :param black_func:当节点在黑色的时候执行的函数 - :return:结果 - """ - gray_list = [] - black_list = [] - node = self.__find(instance) - if node is None: - return None - graph_queue = queue.Queue() - # 初始化节点 - node.set_white() - node.depth = 0 - node.parent = None - for end_node in self.__dict.iterkeys(): - end_node.set_white() - end_node.depth = 0 - end_node.parent = Node - - # 开始遍历 - node.set_gray() - graph_queue.enter(node) - while not graph_queue.empty(): - cur_node = graph_queue.exit() - gray_list.append(gray_func(cur_node)) - for end_node in self.__dict[cur_node]: - if end_node.is_white(): - end_node.set_gray() - end_node.depth += cur_node.depth - end_node.parent = cur_node - graph_queue.enter(end_node) - cur_node.set_black() - black_list.append(black_func(cur_node)) - return gray_list, black_list - - def dfs(self, gray_func, black_func): - """ - 图的深度遍历 - :param gray_func: - :param black_func: - :return: - """ - gray_list = [] - black_list = [] - - # 初始化 - for key in self.__dict.iterkeys(): - key.start_time = None - key.end_time = None - key.set_white() - - # 开始遍历 - counter = 0 - for key in self.__dict.iterkeys(): - if key.is_white(): - dfs_stack = Stack() - key.set_gray() - key.start_time = counter - counter += 1 - dfs_stack.push(key) - while not dfs_stack.empty(): - cur_node = dfs_stack.pop() - gray_list.append(gray_func(key)) - for end_node in self.__dict[cur_node]: - if end_node.is_white(): - end_node.set_gray() - end_node.start_time = counter - counter += 1 - dfs_stack.push(end_node) - cur_node.set_black() - black_list.append(black_func(cur_node)) - cur_node.end_time = counter - counter += 1 - return gray_list, black_list - - def topology_sort(self): - gray_list, black_list = self.dfs(lambda node: node, lambda node: node) - return reversed(black_list) - - -def main(): - graph = GeneralGraph(('内裤', '鞋'), ('内裤', '裤子'), ('裤子', '腰带'), ('腰带', '夹克'), ('衬衣', '腰带'), ('衬衣', '领带'), ('袜子', '鞋'), - ('手表', '手表')) - gray_list, black_list = graph.dfs(lambda node: str(node), lambda node: str(node)) - print gray_list - print black_list - - -if __name__ == "__main__": - main() - - - - - - - - - - - - - - - - - - - - - - - diff --git a/list/linked_list.py b/list/linked_list.py deleted file mode 100644 index 0fc4e6f..0000000 --- a/list/linked_list.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf-8 -*- - -""" -实现一个带哨兵的双向循环链表。一个哨兵是一个空对象,在双向链表实现中简化了改变链接的时候需要判断None的情况。 -实现这个链表的过程时刻记得更新插入和删除节点的前后节点的指针 -""" - - -class LinkedList(object): - class Node(object): - """docstring for LinkedList.Node""" - - def __init__(self, key, prev, next): - super(LinkedList.Node, self).__init__() - self.key = key - self.prev = prev - self.next = next - - def __str__(self): - return "".join([str(self.key), "-->"]) - - def __init__(self, *arg): - super(LinkedList, self).__init__() - self.__nil = LinkedList.Node(None, None, None) - self.__nil.prev = self.__nil - self.__nil.next = self.__nil - self.__length = 0 - for key in arg: - self.append(key) - - def insert(self, index, value): - if index > self.__length: - raise IndexError("can not insert beyond the list") - cur_pos = 0 - cur_node = self.__nil - while cur_pos < index: - cur_node = cur_node.next - cur_pos += 1 - prev_node = cur_node.prev - node = LinkedList.Node(value, prev_node, cur_node) - cur_node.prev = node - prev_node.next = node - self.__length += 1 - return node - - def append(self, value): - last_node = self.__nil.prev - node = LinkedList.Node(value, last_node, self.__nil) - last_node.next = node #现在结尾的节点指向新加的结尾点 - self.__nil.prev = node - self.__length += 1 - #处理空链表的情况 - if self.__nil.next is self.__nil: - self.__nil.next = node - return node - - def prepend(self, value): - node = LinkedList.Node(value, self.__nil, self.__nil.next) - self.__nil.next = node - self.__nil.next.prev = node - #处理空链表的情况 - if self.__nil.prev is self.__nil: - self.__nil.prev = node - self.__length += 1 - return node - - def search(self, value): - cur_node = self.__nil.next - while cur_node is not self.__nil and cur_node.key != value: - cur_node = cur_node.next - return cur_node.key - - def delete(self, value): - cur_node = self.__nil.next - while cur_node is not self.__nil and cur_node.key != value: - cur_node = cur_node.next - #如果不是空链表,那么就是查找到了相应的元素 - if cur_node is not self.__nil: - cur_node.prev.next = cur_node.next - cur_node.next.prev = cur_node.prev - - return cur_node.key - - def __len__(self): - return self.__length - - def __str__(self): - cur_node = self.__nil.next - li = [] - while cur_node is not self.__nil: - li.append(str(cur_node)) - cur_node = cur_node.next - return "".join(li) - - -def main(): - li = LinkedList(20, 40, 5050, 495, 39948) - print "li: ", li - print li.search(5050) - li.delete(5050) - print li - li = LinkedList() - for x in xrange(1, 10): - li.insert(0, x) - print li - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/src/ssj/__init__.py b/src/ssj/__init__.py new file mode 100644 index 0000000..286f8de --- /dev/null +++ b/src/ssj/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +#-*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/clrs/9/9-2(b).py b/src/ssj/clrs/9/9-2(b).py similarity index 92% rename from clrs/9/9-2(b).py rename to src/ssj/clrs/9/9-2(b).py index 773af40..92a8226 100644 --- a/clrs/9/9-2(b).py +++ b/src/ssj/clrs/9/9-2(b).py @@ -14,8 +14,8 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 使用随机元素元素作为分割点并且把随机元素放在列表最后 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] diff --git a/clrs/9/9-2(c).py b/src/ssj/clrs/9/9-2(c).py similarity index 92% rename from clrs/9/9-2(c).py rename to src/ssj/clrs/9/9-2(c).py index 79fc512..aaa513c 100644 --- a/clrs/9/9-2(c).py +++ b/src/ssj/clrs/9/9-2(c).py @@ -7,8 +7,8 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 使用随机元素元素作为分割点并且把随机元素放在列表最后 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] @@ -27,7 +27,7 @@ def partition(li, start, end): def selection(li, start, end, kth): - #一定会找到一个元素,因此这儿直接返回是对的。 + # 一定会找到一个元素,因此这儿直接返回是对的。 if start == end: return start mid_index = partition(li, start, end) @@ -88,4 +88,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/divide_conquer/__init__.py b/src/ssj/clrs/9/__init__.py similarity index 100% rename from divide_conquer/__init__.py rename to src/ssj/clrs/9/__init__.py diff --git a/src/ssj/clrs/README.md b/src/ssj/clrs/README.md new file mode 100644 index 0000000..5d405c2 --- /dev/null +++ b/src/ssj/clrs/README.md @@ -0,0 +1 @@ +算法导论里面的习题 \ No newline at end of file diff --git a/dynamic/__init__.py b/src/ssj/clrs/__init__.py similarity index 100% rename from dynamic/__init__.py rename to src/ssj/clrs/__init__.py diff --git a/dynamic/fabo/fabo_math.py b/src/ssj/dynamic/README.md old mode 100755 new mode 100644 similarity index 100% rename from dynamic/fabo/fabo_math.py rename to src/ssj/dynamic/README.md diff --git a/dynamic/fabo/__init__.py b/src/ssj/dynamic/__init__.py similarity index 100% rename from dynamic/fabo/__init__.py rename to src/ssj/dynamic/__init__.py diff --git a/dynamic/lcs/__init__.py b/src/ssj/dynamic/fabo/__init__.py similarity index 100% rename from dynamic/lcs/__init__.py rename to src/ssj/dynamic/fabo/__init__.py diff --git a/dynamic/fabo/fabo_loop.py b/src/ssj/dynamic/fabo/fabo_loop.py similarity index 97% rename from dynamic/fabo/fabo_loop.py rename to src/ssj/dynamic/fabo/fabo_loop.py index 98c32e8..0792576 100755 --- a/dynamic/fabo/fabo_loop.py +++ b/src/ssj/dynamic/fabo/fabo_loop.py @@ -4,6 +4,7 @@ 使用循环实现的斐波那契数列其实就是自底向上方式实现的动态规划 """ + def loop_fibonacci(n): this = 0 next = 1 @@ -25,4 +26,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/search/__init__.py b/src/ssj/dynamic/fabo/fabo_math.py similarity index 100% rename from search/__init__.py rename to src/ssj/dynamic/fabo/fabo_math.py diff --git a/dynamic/fabo/fabo_up_down.py b/src/ssj/dynamic/fabo/fabo_up_down.py similarity index 97% rename from dynamic/fabo/fabo_up_down.py rename to src/ssj/dynamic/fabo/fabo_up_down.py index 82efbd9..0427c7a 100644 --- a/dynamic/fabo/fabo_up_down.py +++ b/src/ssj/dynamic/fabo/fabo_up_down.py @@ -24,4 +24,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/dynamic/task/__init__.py b/src/ssj/dynamic/lcs/__init__.py similarity index 100% rename from dynamic/task/__init__.py rename to src/ssj/dynamic/lcs/__init__.py diff --git a/dynamic/lcs/down_up.py b/src/ssj/dynamic/lcs/down_up.py similarity index 99% rename from dynamic/lcs/down_up.py rename to src/ssj/dynamic/lcs/down_up.py index 78bb0d9..3c28ec7 100644 --- a/dynamic/lcs/down_up.py +++ b/src/ssj/dynamic/lcs/down_up.py @@ -70,4 +70,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/dynamic/lcs/up_down.py b/src/ssj/dynamic/lcs/up_down.py similarity index 99% rename from dynamic/lcs/up_down.py rename to src/ssj/dynamic/lcs/up_down.py index 1fd070f..30fee5d 100644 --- a/dynamic/lcs/up_down.py +++ b/src/ssj/dynamic/lcs/up_down.py @@ -67,4 +67,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/graph/__init__.py b/src/ssj/dynamic/lps/__init__.py similarity index 100% rename from graph/__init__.py rename to src/ssj/dynamic/lps/__init__.py diff --git a/dynamic/lps/down_up.py b/src/ssj/dynamic/lps/down_up.py similarity index 99% rename from dynamic/lps/down_up.py rename to src/ssj/dynamic/lps/down_up.py index a7b341c..cdedf2a 100644 --- a/dynamic/lps/down_up.py +++ b/src/ssj/dynamic/lps/down_up.py @@ -50,4 +50,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/dynamic/lps/up_down.py b/src/ssj/dynamic/lps/up_down.py similarity index 99% rename from dynamic/lps/up_down.py rename to src/ssj/dynamic/lps/up_down.py index 2990adc..ca88437 100644 --- a/dynamic/lps/up_down.py +++ b/src/ssj/dynamic/lps/up_down.py @@ -56,5 +56,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/greedy/__init__.py b/src/ssj/dynamic/task/__init__.py similarity index 100% rename from greedy/__init__.py rename to src/ssj/dynamic/task/__init__.py diff --git a/dynamic/task/max_weighted_action.py b/src/ssj/dynamic/task/max_weighted_action.py similarity index 99% rename from dynamic/task/max_weighted_action.py rename to src/ssj/dynamic/task/max_weighted_action.py index d44e39a..923fb32 100644 --- a/dynamic/task/max_weighted_action.py +++ b/src/ssj/dynamic/task/max_weighted_action.py @@ -79,4 +79,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/sort/__init__.py b/src/ssj/graph/README.md old mode 100755 new mode 100644 similarity index 100% rename from sort/__init__.py rename to src/ssj/graph/README.md diff --git a/src/ssj/graph/__init__.py b/src/ssj/graph/__init__.py new file mode 100644 index 0000000..b91606e --- /dev/null +++ b/src/ssj/graph/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + + +class GraphError(StandardError): + pass diff --git a/src/ssj/graph/digraph.py b/src/ssj/graph/digraph.py new file mode 100644 index 0000000..2e32c4d --- /dev/null +++ b/src/ssj/graph/digraph.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 + +__author__ = 'shenshijun' +from ssj.lib.queue import Queue +from ssj.graph import GraphError + + +class Vertex(object): + def __init__(self, key, weight=None): + """ + adjust_list 表示邻接节点 + """ + self.key = key + self.weight_list = [] + self.adjust_list = [] + self.in_degree = 0 + self.backup_in_degree = self.in_degree + self.out_degree = 0 + self.backup_out_degree = self.out_degree + self.dist = 0 + + def add_adjust(self, to_vertex): + self.adjust_list.append(to_vertex) + self.out_degree += 1 + self.backup_out_degree += 1 + + +class Digraph(object): + def __init__(self): + self._vertexes = {} + + def add_vertex(self, key): + """ + Args: + :param key:顶点关键字 + Returns: + :rtype: bool + """ + if key in self._vertexes: + return False + else: + self._vertexes[key] = Vertex(key) + return True + + def add_edge(self, from_key, to_key): + # 首先把两个节点查入到图中 + self.add_vertex(from_key) + self.add_vertex(to_key) + self._vertexes[from_key].add_adjust(self._vertexes[to_key]) + self._vertexes[to_key].in_degree += 1 + self._vertexes[to_key].backup_in_degree += 1 + + def top_sort(self, func): + zero_in_degree_queue = Queue() + + # 首先找到所有入度为0的顶点,遍历从这里开始 + for key, vertex in self._vertexes.iteritems(): + vertex.backup_in_degree = vertex.in_degree + if vertex.in_degree is 0: + zero_in_degree_queue.enter(vertex) + + if zero_in_degree_queue.empty(): + raise GraphError('图中有环,无法执行图的拓扑排序') + + result = [] + while not zero_in_degree_queue.empty(): + zero_vertex = zero_in_degree_queue.exit() + result.append(func(zero_vertex.key)) + for vertex in zero_vertex.adjust_list: + vertex.in_degree -= 1 + if vertex.in_degree is 0: + zero_in_degree_queue.enter(vertex) + + # 恢复 + for key, vertex in self._vertexes.iteritems(): + vertex.in_degree = vertex.backup_in_degree + return result + + def bfs(self, key, func): + next_vertex_queue = Queue() + for k, vertex in self._vertexes.iteritems(): + vertex.dist = -1 + + result = [] + self._vertexes[key].dist = 0 + next_vertex_queue.enter(self._vertexes[key]) + + while not next_vertex_queue.empty(): + vertex = next_vertex_queue.exit() + result.append(func(vertex.key, vertex.dist)) + for adjust_vertex in vertex.adjust_list: + if adjust_vertex.dist is -1: + adjust_vertex.dist = vertex.dist + 1 + next_vertex_queue.enter(adjust_vertex) + + for k, vertex in self._vertexes.iteritems(): + if vertex.dist is -1: + result.extend(self.bfs(vertex.key, func)) + return result + + +def main(): + graph = Digraph() + graph.add_edge('v1', 'v2') + graph.add_edge('v1', 'v3') + graph.add_edge('v1', 'v4') + graph.add_edge('v2', 'v4') + graph.add_edge('v4', 'v3') + graph.add_edge('v4', 'v7') + graph.add_edge('v4', 'v6') + graph.add_edge('v3', 'v6') + graph.add_edge('v2', 'v5') + graph.add_edge('v5', 'v4') + graph.add_edge('v5', 'v7') + graph.add_edge('v7', 'v6') + print graph.top_sort(lambda key: key) + print graph.bfs('v1', lambda key, dist: (key, dist)) + + +if __name__ == "__main__": + main() diff --git a/graph/weighted_graph.py b/src/ssj/graph/weighted_graph.py similarity index 99% rename from graph/weighted_graph.py rename to src/ssj/graph/weighted_graph.py index 1cbc1e9..e1eb1db 100644 --- a/graph/weighted_graph.py +++ b/src/ssj/graph/weighted_graph.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from lib.queue import Queue +from ssj.lib.queue import Queue __author__ = 'shenshijun' """ diff --git a/src/ssj/greedy/README.md b/src/ssj/greedy/README.md new file mode 100644 index 0000000..e69de29 diff --git a/heap/__init__.py b/src/ssj/greedy/__init__.py similarity index 100% rename from heap/__init__.py rename to src/ssj/greedy/__init__.py diff --git a/greedy/max_task_count.py b/src/ssj/greedy/max_task_count.py similarity index 99% rename from greedy/max_task_count.py rename to src/ssj/greedy/max_task_count.py index 70f82cd..b889be4 100644 --- a/greedy/max_task_count.py +++ b/src/ssj/greedy/max_task_count.py @@ -26,5 +26,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/src/ssj/heap/README.md b/src/ssj/heap/README.md new file mode 100644 index 0000000..e69de29 diff --git a/lib/__init__.py b/src/ssj/heap/__init__.py similarity index 100% rename from lib/__init__.py rename to src/ssj/heap/__init__.py diff --git a/src/ssj/heap/fibonacci_heap.py b/src/ssj/heap/fibonacci_heap.py new file mode 100644 index 0000000..7a90dc1 --- /dev/null +++ b/src/ssj/heap/fibonacci_heap.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + + +class FibonacciHeap(object): + """实现斐波那契堆,斐波那契堆在一些操作执行的时候复杂度比较低,而其他操作的复杂度和普通的堆是一样的""" + + class Node(object): + """节点实现""" + + def __init__(self, key, parent=None, child=None, left=None, right=None): + """Constructor for """ + self.key = key + self.degree = 0 + self.mark = False + self.parent = parent + self.child = child + self.left = left or self + self.right = right or self + + def __str__(self): + return str(self.key) + " : " + str(self.degree) + + def __init__(self, *argv): + """Constructor for """ + self.__root = None + self.__size = 0 + map(self.insert, argv) + + def insert(self, key): + self.__size += 1 + return self.__insert_root(self.Node(key)) + + def __insert_root(self, node, change_root=True): + node.parent = None + if not self.__root: + self.__root = node + self.__root.left = node + self.__root.right = node + else: + node.left = self.__root.left + node.right = self.__root + self.__root.left.right = node + self.__root.left = node + + if self.__root.key > node.key and change_root: + self.__root = node + return node + + def extract_min(self): + if not self.__root: + return None + + result = self.__root + self.__size -= 1 + + # 首先把根节点的子节点全部移到根链表上 + child = self.__root.child + for i in xrange(0, self.__root.degree): + next_node = child.right + self.__remove_self(child) + self.__insert_root(child) + child = next_node + + # 移除根节点 + self.__remove_self(self.__root) + if self.__root.right is self.__root: + self.__root = None + else: + self.__root = self.__root.right + self.__extract_consolidating() + + result.left = result + result.right = result + result.parent = None + return result.key + + @classmethod + def __remove_self(cls, node): + node.left.right = node.right + node.right.left = node.left + + def __extract_consolidating(self): + # 合并根链表 + node_degrees = {} + pass_root = False + cur_node = self.__root + after_merge = False + next_node = None + while cur_node is not self.__root or not pass_root or after_merge: + if cur_node == self.__root: + pass_root = True + + if not after_merge: + next_node = cur_node.right + + d = cur_node.degree + if d in node_degrees: + other_node = node_degrees[d] + sm_node = cur_node if cur_node.key <= other_node.key else other_node + bg_node = cur_node if cur_node.key > other_node.key else other_node + # 把大的节点连接到小的节点上面,然后继续在sm_node上面循环,因为sm_node的度数发生了变化 + self.__link_to(bg_node, sm_node) + del node_degrees[d] + after_merge = True + cur_node = sm_node + else: + after_merge = False + node_degrees[d] = cur_node + cur_node = next_node + + self.__root = None + + for d, node in node_degrees.iteritems(): + self.__insert_root(node) + + @staticmethod + def __link_to(src, dest): + """ + bugfix: 不能把src从根链表移除,这样的话会破坏根链表,导致在__extract_consolidating中的while找不到退出条件 + 我是为了避免重新创建根链表而把src从根链表中移除,这段注释只是为了提醒 + :param src: + :param dest: + :return: + """ + src.mark = False + + dest_child = dest.child + src.parent = dest + if not dest_child: + dest.child = src + src.left = src + src.right = src + else: + src.left = dest_child.left + dest_child.left.right = src + dest_child.left = src + src.right = dest_child + dest.degree += 1 + + def union(self, other): + if not self.__root: + self.__root = other.__root + else: + self_left = self.__root.left + other_right = other.__root.right + self.__root.left = other.__root + other.__root.right = self.__root + self_left.right = other_right + other_right.left = self_left + self.__root = self.__root if self.__root.key < other.__root.key else other.__root + self.__size += other.__size + + return self + + def min(self): + return None if self.__root else self.__root.key + + def change_key(self, node, new_key): + """ + 给node设置一个比其key小的值 + :param node: + :param new_key: + :return: + """ + if node.key < new_key: + return + node.key = new_key + parent = node.parent + if parent and parent.key > node.key: + self.__cut(node) + self.__cascade_cut(parent) + if self.__root.key > node.key: + self.__root = node + + def __len__(self): + return self.__size + + def delete(self, node): + self.change_key(node, float('-Inf')) + self.extract_min() + + def __cut(self, node): + parent = node.parent + if not parent: + return node + + # 处理parent的child指针 + if node.right is node: + parent.child = None + else: + parent.child = node.right + self.__remove_self(node) + parent.degree -= 1 + self.__insert_root(node) + node.mark = False + return node + + def __cascade_cut(self, node): + parent = node.parent + # 如果parent为None,说明这个节点在根链表上,因此不需要继续处理 + if parent: + if not node.mark: + node.mark = True + else: + # 如果已经丢失了两个节点,那么要把本节点移到根链表上 + self.__cut(node) + self.__cascade_cut(parent) + + +def main(): + import random + test = ['O', 'J', 'S', 'Y', 'C', 'M', 'B', 'R', 'N', 'F', 'L', 'Z', 'U', 'Q', 'A', 'G', 'V', 'E', 'D', 'W', 'I', + 'H', 'T', 'K', 'X', 'P'] + random.shuffle(test) + rele = 'Z' + test.remove(rele) + heap = FibonacciHeap(*test) + rnode = heap.insert(rele) + + for i in xrange(0, random.randint(1, len(heap))): + print(heap.extract_min()) + + print("change a node key") + heap.change_key(rnode, 0) + + for i in xrange(0, len(heap)): + print(heap.extract_min()) + + print("test union") + one = [10, 20, 0] + other = [15, 5, 30] + one_heap = FibonacciHeap(*one) + other_heap = FibonacciHeap(*other) + one_heap.union(other_heap) + for i in xrange(0, len(one_heap)): + print(one_heap.extract_min()) + + +if __name__ == "__main__": + main() diff --git a/heap/max_heap.py b/src/ssj/heap/max_heap.py similarity index 90% rename from heap/max_heap.py rename to src/ssj/heap/max_heap.py index 3387a4b..e61f556 100644 --- a/heap/max_heap.py +++ b/src/ssj/heap/max_heap.py @@ -34,14 +34,14 @@ def heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] self.heapify(largest) @@ -56,14 +56,14 @@ def loop_heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] parent = largest @@ -88,7 +88,6 @@ def __deep_walk_through(self, func, start=0): self.__deep_walk_through(func, left) self.__deep_walk_through(func, right) - def __str__(self): title = "Heap Length: %s\n" % self.length content_list = [title] @@ -116,4 +115,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/heap/max_queue.py b/src/ssj/heap/max_queue.py similarity index 93% rename from heap/max_queue.py rename to src/ssj/heap/max_queue.py index 80e997f..b06fecf 100644 --- a/heap/max_queue.py +++ b/src/ssj/heap/max_queue.py @@ -31,14 +31,14 @@ def heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] self.heapify(largest) @@ -52,14 +52,14 @@ def loop_heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] parent = largest @@ -84,7 +84,6 @@ def __deep_walk_through(self, func, start=0): self.__deep_walk_through(func, left) self.__deep_walk_through(func, right) - def __str__(self): title = "Heap Length: %s\n" % self.length content_list = [title] @@ -102,7 +101,7 @@ def append(self, value): insert_index = self.length while True: parent = (insert_index - 1) / 2 - #这儿需要判断使得parent不会越界 + # 这儿需要判断使得parent不会越界 if parent >= 0 and self.__array[insert_index] > self.__array[parent]: self.__array[parent], self.__array[insert_index] = self.__array[insert_index], self.__array[parent] insert_index = parent @@ -119,7 +118,7 @@ def append_with_one_assign(self, value): insert_index = self.length while True: parent = (insert_index - 1) / 2 - #这儿需要判断使得parent不会越界 + # 这儿需要判断使得parent不会越界 if parent >= 0 and value > self.__array[parent]: self.__array[insert_index] = self.__array[parent] insert_index = parent @@ -128,7 +127,6 @@ def append_with_one_assign(self, value): self.__array[insert_index] = value self.length += 1 - def __setitem__(self, index, value): self.__array[index] = value @@ -220,7 +218,6 @@ def __setitem__(self, key, value): node = MaxQueue.Node(key, value) self.__heap.append_with_one_assign(node) - def __str__(self): return str(self.__heap) diff --git a/src/ssj/leecode/README.md b/src/ssj/leecode/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/leecode/__init__.py b/src/ssj/leecode/__init__.py new file mode 100644 index 0000000..286f8de --- /dev/null +++ b/src/ssj/leecode/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +#-*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/src/ssj/leecode/add_two_numbers.py b/src/ssj/leecode/add_two_numbers.py new file mode 100644 index 0000000..60b3d17 --- /dev/null +++ b/src/ssj/leecode/add_two_numbers.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. + +Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) +Output: 7 -> 0 -> 8 +""" + + +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + + +class Solution(object): + def __addUpDigit(self, node, up_digit): + last_node = None + while node is not None and up_digit > 0: + node.val += up_digit + if node.val >= 10: + node.val -= 10 + up_digit = 1 + else: + up_digit = 0 + last_node = node + node = node.next + if up_digit > 0 and last_node: + last_node.next = ListNode(up_digit) + + def addTwoNumbers(self, l1, l2): + """ + :type l1: ListNode + :type l2: ListNode + :rtype: ListNode + """ + cur_l1 = l1 + cur_l2 = l2 + last_l1 = None + last_up_digit = 0 + while cur_l1 is not None and cur_l2 is not None: + this_val = cur_l1.val + cur_l2.val + last_up_digit + if this_val >= 10: + cur_l1.val = this_val - 10 + last_up_digit = 1 + else: + cur_l1.val = this_val + last_up_digit = 0 + last_l1 = cur_l1 + cur_l1 = cur_l1.next + cur_l2 = cur_l2.next + + if cur_l1 is None and cur_l2 is None and last_up_digit > 0 and last_l1 is not None: + last_l1.next = ListNode(last_up_digit) + self.__addUpDigit(cur_l1, last_up_digit) + self.__addUpDigit(cur_l2, last_up_digit) + + # 如果l1比较短,需要把l2长的部分合并到l1后面 + if cur_l2 is not None: + if last_l1 is None: + return l2 + else: + last_l1.next = cur_l2 + + return l1 + + +def main(): + pass + + +if __name__ == "__main__": + main() diff --git a/src/ssj/leecode/atoi.c b/src/ssj/leecode/atoi.c new file mode 100644 index 0000000..670ce17 --- /dev/null +++ b/src/ssj/leecode/atoi.c @@ -0,0 +1,98 @@ +#include +#include +#include + + +static int intToString(int i,char *arr){ + int t_len = sprintf(arr,"%d",i); + arr[t_len] = '\0'; + return t_len; +} +static int myStrcmp(char *start,char *end,char *other){ + for(char *c1 = start,*c2 = other;c1<=end&&c2!='\0';c1++,c2++){ + if (*c1 > *c2){ + return 1; + }else if(*c1 < *c2){ + return -1; + } + } + return 0; +} + +int myAtoi(char* str) { + int is_negative = 0; + char *start=NULL,*end=NULL; + for(char *c=str;c!='\0';c++){ + if(start==NULL && (*c == ' ' || *c =='\n' || *c == '\t')){ + continue; + }else if((*c=='-' || (*c >='0' && *c<='9') || *c=='+') && start==NULL){ + start = c; + if(*c == '-'){ + is_negative=1; + } + }else if(*c >='0' && *c<='9'&& start!=NULL){ + end = c; + }else{ + break; + } + } + + if(start==NULL){ + return 0; + }else if (end==NULL){ + end = start; + } + + if(*start == '+'){ + start++; + } + +// printf("%c:%c\n",*start,*end); + //检查是否越界 + int result_len = end - start + 1; + if(is_negative){ + char min_str[40]; + int min_len = intToString(INT_MIN,min_str); + if(result_len>min_len || (result_len == min_len && myStrcmp(start,end,min_str)>0)){ + return INT_MIN; + } + }else{ + char max_str[40]; + int max_len = intToString(INT_MAX,max_str); + if(result_len>max_len || (result_len == max_len && myStrcmp(start,end,max_str)>0)){ + return INT_MAX; + } + } + + int result = 0; + +// printf("%c:%c",*start,*end); + for(char *c=start;c<=end;c++){ + if(*c != '-' && *c != '+'){ + result *= 10; + result += (*c - '0'); + } + } + + if(*start=='-'){ + result = -result; + } + return result; +} + + +int main(){ + printf("%d\n",myAtoi("+1231312")); + printf("%d\n",myAtoi(" -11919730356x")); + printf("%d\n",myAtoi(" +1146905820n1")); + printf("%d\n",myAtoi("1")); + printf("%d\n",myAtoi("123")); + printf("%d\n",myAtoi("-1231312")); + printf("%d\n",myAtoi("-1231312fqwef")); + printf("%d\n",myAtoi("-1231312 992")); + printf("%d\n",myAtoi("3000000001")); + printf("%d\n",myAtoi("-3000000001")); + printf("%d\n",myAtoi("wefwqef-3000000001")); + printf("%d\n",myAtoi(" -3000000001")); + return 0; +} \ No newline at end of file diff --git a/src/ssj/leecode/find_median_sorted_arrays.py b/src/ssj/leecode/find_median_sorted_arrays.py new file mode 100644 index 0000000..b8a1224 --- /dev/null +++ b/src/ssj/leecode/find_median_sorted_arrays.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). +""" +""" +思路一:遍历一遍就可以把两个数组排序,然后取中点的值就可以了,这样的复杂度是O(m+n) +思路二:排序显然做了许多无用功,因为只需要一个中间数就可以了 +参考:http://www.cnblogs.com/lichen782/p/leetcode_Median_of_Two_Sorted_Arrays.html +可以分成四种情况考虑 +1,两个列表都没有数据,那么返回0 +2,两个列表中只有一个列表有数据,那么返回其中一个列表的中间点 +3,两个列表中的一个列表整体大于另一个列表,那么可以在逻辑上把这两个列表合并起来求出合并后的中点 +4,问题可以简化成从两个排序列表中求出第k个数,也就是从两个数组的开头取出k个数字,这k个数字比留在数组中的数字要小 +那么可以开始从两个数组中取出k/2的数字(这样做每次可以把问题的规模减小一半,整体的复杂度也就是指数级的), +比较k/2位置处数字的大小,小的那一部分一定是在k小的数字之内(可以假设法证明),这样剩下的问题就是从剩下的列表中找 +第k/2位数了.等到这个数为1,那么就好计算了. + + +注意:本解答仍然有问题。 + +""" + + +class Solution(object): + def findMedianSortedArrays(self, nums1, nums2): + """ + :type nums1: List[int] + :type nums2: List[int] + :rtype: float + """ + if not nums1: + return self.__findMedian(nums2) + elif not nums2: + return self.__findMedian(nums1) + elif not nums1 and not nums2: + return 0 + + len1 = len(nums1) + len2 = len(nums2) + + if (len1 + len2) % 2 is 0: + return (self.__findKth(4, nums1, nums2)) + return (self.__findKth((len1 + len2) / 2 + 1, nums1, nums2) + self.__findKth((len1 + len2) / 2, nums1, + nums2)) / 2.0 + else: + return self.__findKth((len1 + len2) / 2 + 1, nums1, nums2) + + @staticmethod + def __findMedian(li): + median = len(li) / 2 + if len(li) % 2 is 0: + return (li[median] + li[median - 1]) / 2.0 + else: + return li[median] + + @staticmethod + def __findKth(k, l1, l2): + l1_start = 0 + l2_start = 0 + while (len(l1) + len(l2) - l1_start - l2_start) >= k: + if k is 1: + return min(l1[l1_start], l2[l2_start]) + if len(l1) - l1_start < len(l2) - l2_start: + l1_comp_start = l1_start + min(len(l1) - l1_start, k / 2) + l2_comp_start = k - min(len(l1) - l1_start, k / 2) + l2_start - 1 + else: + l2_comp_start = min(len(l2) - l2_start, k / 2) + l2_start + l1_comp_start = k - min(len(l2) - l2_start, k / 2) + l1_start - 1 + + if l1[l1_comp_start] > l2[l2_comp_start]: + k -= (l2_comp_start - l2_start + 1) + l2_start = l2_comp_start + 1 + elif l1[l1_comp_start] < l2[l2_comp_start]: + k -= (l1_comp_start - l1_start + 1) + l1_start = l1_comp_start + 1 + else: + return l1[l1_comp_start] + return 0 + + +def main(): + print(Solution().findMedianSortedArrays([0, 1, 2, 3, 4], [0, 1, 2])) # 1 + # print(Solution().findMedianSortedArrays([], [1])) # + + +if __name__ == "__main__": + main() diff --git a/src/ssj/leecode/longest_palindromic_substring.py b/src/ssj/leecode/longest_palindromic_substring.py new file mode 100644 index 0000000..29df72c --- /dev/null +++ b/src/ssj/leecode/longest_palindromic_substring.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. + +我的解法就是这个解法:http://taop.marchtea.com/01.05.html +感谢 +""" + + +class Solution(object): + def longestPalindrome(self, original): + """ + :type s: str + :rtype: str + """ + if not original: + return 0 + s = self.__preProcess(original) + longest_right_bound = 0 + longest_median = 0 + pali_list = [1 for i in range(len(s))] + # 注意迭代位置,为了不出现越界,最前和最后的字符串是不会被遍历的 + for i in range(1, len(s) - 1): + # 这边使用的是对称的原理,使得可以快速个p[i]一个基础的值 + if longest_right_bound > i: + if longest_right_bound - i <= pali_list[2 * longest_median - i]: + pali_list[i] = longest_right_bound - i + else: + pali_list[i] = pali_list[2 * longest_median - i] + # 在字符串的最前面和最后面都必须加上一个特殊字符,用于防止越界 + # 另一个方法是在每次循环的时候都判断边界,但是效率比直接加特殊字符低 + while s[i + pali_list[i]] == s[i - pali_list[i]]: + pali_list[i] += 1 + if pali_list[i] >= longest_right_bound - longest_median: + longest_right_bound = pali_list[i] + i + longest_median = i + return self.__clearString(s[2 * longest_median - longest_right_bound + 1:longest_right_bound]) + + def __clearString(self, sub_str): + return "".join([ch for ch in sub_str if ch != '#']) + + def __preProcess(self, s): + str_list = ['#{}'.format(ele) for ele in s] + str_list.append("#$") + str_list.insert(0, '^') + return "".join(str_list) + + +def main(): + print(Solution().longestPalindrome("bbbbbb")) # 6 + print(Solution().longestPalindrome("fqwefqwefqwadccdaafwfawef")) # 6 + print(Solution().longestPalindrome("qwefqwefqsjsjsssgsssjsjsg3q4gekwSKDFKALJKFIUWIUEFWEG")) # 15 + print(Solution().longestPalindrome("ababababa")) # 10 + + +if __name__ == "__main__": + main() diff --git a/src/ssj/leecode/longest_substring.py b/src/ssj/leecode/longest_substring.py new file mode 100644 index 0000000..b9d4381 --- /dev/null +++ b/src/ssj/leecode/longest_substring.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + +""" +Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1. +""" + +""" +思路:使用两个指针来遍历字符串,他们之间的字符是不重复的字符.前面的指针每次前进一步都会判断新扫描的字符是不是和两个指针的间的字符重复 +s a f b r g r e g + ^ ^ + | |index +start_index +为了这个目的,使用了哈希表. +如果重复,那么就找到一个连续的非重复字符串,这里就是afbrg(index现在在r的位置),判断这个字符串长度和已有的最大长度的大小, +并且记录下最大值.发生重复之后的处理非常重要,是把前面重复的部分丢弃掉,这样后面的字符串还是一个非重复的字符串(start_index在g的位置) +这样的目的是尽量构建一个长的非重复字符串 + +如果没有重复,那么就把字符和对应的索引放入哈希表,以备后面使用 + +如果限定了字符集,那么可以使用数组来模拟哈希表,这样的效率更高. +""" + + +class Solution(object): + def lengthOfLongestSubstring(self, s): + """ + :type s: str + :rtype: int + """ + if not s: + return 0 + tmp_dict = {} + # 字符串不为空,因此最小值是1 + max_length = 1 + start_index = 0 + for index, ch in enumerate(s): + if ch in tmp_dict: + if max_length < index - start_index: + max_length = index - start_index + dup_index = tmp_dict[ch] + for i in range(start_index, dup_index + 1): + del tmp_dict[s[i]] + start_index = dup_index + 1 + tmp_dict[ch] = index + # 注意结束的时候如果没有重复,那么会安静退出循环而不发生任何比较,所以在退出循环的时候要比较 + return len(tmp_dict) if len(tmp_dict) > max_length else max_length + + +def main(): + print(Solution().lengthOfLongestSubstring("bbbbbb")) # 1 + print(Solution().lengthOfLongestSubstring("abcabcbb")) # 3 + print(Solution().lengthOfLongestSubstring("dvdfefqwfqwef")) # 3 + + +if __name__ == "__main__": + main() diff --git a/src/ssj/leecode/palindrome_number.c b/src/ssj/leecode/palindrome_number.c new file mode 100644 index 0000000..0232605 --- /dev/null +++ b/src/ssj/leecode/palindrome_number.c @@ -0,0 +1,41 @@ +/** +*Determine whether an integer is a palindrome. Do this without extra space. +*/ + +/** +可以直接把int逆转,然后只需要判断他们是不是相等就可以了 +关于溢出的问题 +1,如果原来的数字没有溢出,那么如果他们是回文,那么逆转后的数字也不会越界。这样保证如果是回文,那么就不会越界。 +2,如果原来的数字不是回文,那么逆转后的数字一定不会溢出,因此一旦在逆转数字的时候出现溢出,那么就可以判断这个数字不是回文 +**/ + +#include +#include +#include +#include + +bool isPalindrome(int x){ + if(x<0) return 0; + int res = 0; + int tmp = x; + while (x != 0) { + /** + * 假设INT_MAX / 10 = m,因为他是一个浮点数,那么假设他在n-1,n之间 + * 那么也就是abs(res)的最大值是n-1,这个数字是在接下来的计算中可能会越界(依赖于x % 10的值) + * 如果abs(res)为n,那么就一定会发生越界 + */ + if (abs(res) > INT_MAX / 10 || abs(res) * 10 > INT_MAX - abs(x) % 10) return 0; + res = res * 10 + x % 10; + x /= 10; + } + return res==tmp; +} + +int main(){ + printf("%d\n",isPalindrome(1)); + printf("%d\n",isPalindrome(0)); + printf("%d\n",isPalindrome(12311321)); + printf("%d\n",isPalindrome(-12311321)); + printf("%d\n",isPalindrome(-2147447412)); + return 0; +} diff --git a/src/ssj/leecode/regular_expression_matching.py b/src/ssj/leecode/regular_expression_matching.py new file mode 100644 index 0000000..1f64edd --- /dev/null +++ b/src/ssj/leecode/regular_expression_matching.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +""" +'.' Matches any single character. +'*' Matches zero or more of the preceding element. + +The matching should cover the entire input string (not partial). + +The function prototype should be: +bool isMatch(const char *s, const char *p) + +Some examples: +isMatch("aa","a") → false +isMatch("aa","aa") → true +isMatch("aaa","aa") → false +isMatch("aa", "a*") → true +isMatch("aa", ".*") → true +isMatch("ab", ".*") → true +isMatch("aab", "c*a*b") → true +""" + + +class Solution(object): + def isMatch(self, s, p): + """ + :type s: str + :type p: str + :rtype: bool + """ + pass diff --git a/src/ssj/leecode/reverse_integer.c b/src/ssj/leecode/reverse_integer.c new file mode 100644 index 0000000..a991cb6 --- /dev/null +++ b/src/ssj/leecode/reverse_integer.c @@ -0,0 +1,33 @@ +/** +*本题目使用C编写,因为Python的int类型是无限大的,要判断一个数字是否溢出非常简单,祝需要和2^32-1比较就好了 +*/ + +#include +#include +#include + +int reverse(int x) { + int res = 0; + while (x != 0) { + /** + * 假设INT_MAX / 10 = m,因为他是一个浮点数,那么假设他在n-1,n之间 + * 那么也就是abs(res)的最大值是n-1,这个数字是在接下来的计算中可能会越界(依赖于x % 10的值) + * 如果abs(res)为n,那么就一定会发生越界 + */ + if (abs(res) > INT_MAX / 10 || abs(res) * 10 > INT_MAX - abs(x) % 10) return 0; + res = res * 10 + x % 10; + x /= 10; + } + return res; +} + + + +int main(){ + printf("%d\n",reverse(1231312)); + printf("%d\n",reverse(123)); + printf("%d\n",reverse(-1231312)); + printf("%d\n",reverse(1000000003)); + printf("%d\n",reverse(-1000000003)); + return 0; +} \ No newline at end of file diff --git a/src/ssj/leecode/two_sum.py b/src/ssj/leecode/two_sum.py new file mode 100644 index 0000000..3808b47 --- /dev/null +++ b/src/ssj/leecode/two_sum.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +""" +Given an array of integers, find two numbers such that they add up to a specific target number. +The function twoSum should return indices of the two numbers such that they add up to the target, +where index1 must be less than index2.Please note that your returned answers (both index1 and index2) are not zero-based. + +You may assume that each input would have exactly one solution. + +Input: numbers={2, 7, 11, 15}, target=9 +Output: index1=1, index2=2 +""" + +__author__ = 'shenshijun' + +""" +本题有两个思路: +一: 利用排序和二分查找 +先排序得到一个排序的数列,复杂度是O(nlgn),然后遍历数列,每遍历到一个元素的时候使用二分查询查找另外一个数字是否存在,复杂度仍然是O(nlgn) + +二: 使用hash表 +思路一为了快速查找而把数据都排了序,为了查找,显然可以使用hash表.而hash表是更高效的实现.一遍完成,因此复杂度是O(n) +""" + + +class Solution(object): + def twoSum(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: List[int] + """ + d = {} + for ind, num in enumerate(nums): + # 为了防止列表中出现重复的数,并且保证列表前面的index比后面的index小 + if num in d: + if type(d[num]) is list: + d[num].append(ind) + else: + d[num] = [d[num], ind] + else: + d[num] = ind + + for num, ind in d.iteritems(): + # 注意:要同时考虑ind和d[other_part]都为list的情况 + # 还要考虑,找到的index不能是同一个,并且不能重复 + this_indexs = ind if type(ind) == list else [ind] + other_part = target - num + for this_index in this_indexs: + if other_part in d: + if type(d[other_part]) == list: + for other_index in d[other_part]: + if other_index != this_index: + return [min(other_index, this_index) + 1, max(other_index, this_index) + 1] + elif d[other_part] != this_index: + return [min(d[other_part], this_index) + 1, max(d[other_part], this_index) + 1] + + return [-1, -1] + + +def main(): + print(Solution().twoSum([0, 4, 3, 0], 0)) + print(Solution().twoSum([2, 7, 11, 15], 9)) + print(Solution().twoSum([-3, 4, 3, 90], 0)) + + +if __name__ == "__main__": + main() diff --git a/src/ssj/lib/README.md b/src/ssj/lib/README.md new file mode 100644 index 0000000..e69de29 diff --git a/list/__init__.py b/src/ssj/lib/__init__.py similarity index 100% rename from list/__init__.py rename to src/ssj/lib/__init__.py diff --git a/lib/queue.py b/src/ssj/lib/queue.py similarity index 99% rename from lib/queue.py rename to src/ssj/lib/queue.py index 67c2711..28e699a 100644 --- a/lib/queue.py +++ b/src/ssj/lib/queue.py @@ -3,6 +3,7 @@ __author__ = 'shenshijun' import copy + class Queue(object): """ 使用Python的list快速实现一个队列 diff --git a/lib/set.py b/src/ssj/lib/set.py similarity index 99% rename from lib/set.py rename to src/ssj/lib/set.py index 997a408..40fecd9 100644 --- a/lib/set.py +++ b/src/ssj/lib/set.py @@ -46,6 +46,7 @@ def __iter__(self): def __str__(self): return ",".join(map(lambda node: str(node), iter(self))) + def main(): test_set = Set() test_set.add(10) @@ -56,5 +57,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/lib/stack.py b/src/ssj/lib/stack.py similarity index 100% rename from lib/stack.py rename to src/ssj/lib/stack.py diff --git a/src/ssj/list/README.md b/src/ssj/list/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/list/__init__.py b/src/ssj/list/__init__.py new file mode 100644 index 0000000..6417397 --- /dev/null +++ b/src/ssj/list/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' +from linked_list import LinkedList +from mutiarray_linkedlist import MultiArrayLinkedList +from skip_list import SkipList +from stack import Stack diff --git a/src/ssj/list/linked_list.py b/src/ssj/list/linked_list.py new file mode 100644 index 0000000..ff4cbd7 --- /dev/null +++ b/src/ssj/list/linked_list.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- + +""" +实现一个带哨兵的双向循环链表。一个哨兵是一个空对象 +在双向链表实现中简化了改变链接的时候需要判断None的情况。 +实现这个链表的过程时刻记得更新插入和删除节点的前后节点的指针 +""" +from __builtin__ import object + + +class LinkedList(object): + class Node(object): + """docstring for LinkedList.Node""" + + def __init__(self, value, prev, next_node): + super(LinkedList.Node, self).__init__() + self.value = value + self.prev = prev + self.next_node = next_node + + def __str__(self): + return str(self.value) + + def __init__(self, *arg): + """ + 创建一个链表 + :param arg: 可变参数,是列表的初始元素 + :return: + """ + super(LinkedList, self).__init__() + # dump对象的prev指针始终指向列表的尾巴 + # 而列表的最后一个元素的next指针则始终指向列表开头,整个列表就是一个环 + self.__dump = LinkedList.Node(None, None, None) + self.__dump.prev = self.__dump + self.__dump.next_node = self.__dump + self.__length = 0 + for value in arg: + self.append(value) + + def insert(self, index, value): + """ + 在列表的中间插入一个元素 + :param index: 要插入的位置 + :param value: 要插入的值 + :return: 插入值之后列表的大小 + """ + if index > self.__length: + raise IndexError("can not insert beyond the list") + + cur_pos = 0 + cur_node = self.__dump + while cur_pos < index: + cur_node = cur_node.next_node + cur_pos += 1 + + prev_node = cur_node.prev + node = LinkedList.Node(value, prev_node, cur_node) + cur_node.prev = node + prev_node.next_node = node + self.__length += 1 + return self.__length + + def append(self, value): + """ + 在列表的结尾插入一个元素 + :param value:要插入的元素 + :return: 插入之后列表的大小 + """ + last_node = self.__dump.prev + node = LinkedList.Node(value, last_node, self.__dump) + # 现在结尾的节点指向新加的结尾点 + last_node.next_node = node + self.__dump.prev = node + self.__length += 1 + return self.__length + + def prepend(self, value): + """ + 在列表的最前面插入一个值 + :param value: 要插入的元素 + :return: 插入之后列表的大小 + """ + node = LinkedList.Node(value, self.__dump, self.__dump.next_node) + self.__dump.next_node.prev = node + self.__dump.next_node = node + self.__length += 1 + return self.__length + + def search(self, value): + """ + 寻找一个元素是否存在于列表中 + :param value: 要寻找的元素 + :return: 如果没有,返回None;如果有,则返回找到的值 + """ + cur_node = self.__dump.next_node + while cur_node is not self.__dump and cur_node.value != value: + cur_node = cur_node.next_node + return cur_node.value + + def delete(self, value): + """ + 删除一个值 + :param value: 要删除的元素 + :return: 被删除的值 + """ + cur_node = self.__dump.next_node + while cur_node is not self.__dump and cur_node.value != value: + cur_node = cur_node.next_node + + # 如果不是空链表,那么就是查找到了相应的元素 + if cur_node is not self.__dump: + cur_node.prev.next_node = cur_node.next_node + cur_node.next_node.prev = cur_node.prev + self.__length -= 1 + + return cur_node.value + + def __len__(self): + return self.__length + + def __str__(self): + cur_node = self.__dump.next_node + li = [] + while cur_node is not self.__dump: + li.append(str(cur_node)) + cur_node = cur_node.next_node + return '[' + ", ".join(li) + ']' + + +def main(): + li = LinkedList(20, 40, 5050, 495, 39948) + print "li: ", li + print li.search(5050) + li.delete(5050) + print li + li = LinkedList() + for x in range(1, 10): + li.insert(0, x) + print li + + li = LinkedList() + for x in range(1, 10): + li.append(x) + print li + + li = LinkedList() + for x in range(1, 10): + li.prepend(x) + print li + + +if __name__ == '__main__': + main() diff --git a/list/mutiarray_linkedlist.py b/src/ssj/list/mutiarray_linkedlist.py similarity index 89% rename from list/mutiarray_linkedlist.py rename to src/ssj/list/mutiarray_linkedlist.py index f2f988d..265c6d0 100644 --- a/list/mutiarray_linkedlist.py +++ b/src/ssj/list/mutiarray_linkedlist.py @@ -17,16 +17,16 @@ def __init__(self, length): super(MultiArrayLinkedList, self).__init__() self.__empty = self.EmptyNode() self.__cap = length - self.__lenght = 0 + self.__length = 0 self.__key = [self.__empty for x in xrange(0, length + 1)] self.__prev = [-1 for x in xrange(0, length + 1)] - self.__next = [x + 1 for x in xrange(0, length + 1)] #next数组在节点为空的时候存储的是下一个空节点的位置 - self.__free = 1 #第一个空元素位置 - #设置哨兵元素 + self.__next = [x + 1 for x in xrange(0, length + 1)] # next数组在节点为空的时候存储的是下一个空节点的位置 + self.__free = 1 # 第一个空元素位置 + # 设置哨兵元素 self.__key[0] = self.__empty self.__prev[0] = 0 self.__next[0] = 0 - self.__full = 0 #第一个元素位置 + self.__full = 0 # 第一个元素位置 def prepend(self, value): first_node = self.__next[0] @@ -41,16 +41,16 @@ def prepend(self, value): def append(self, value): last_node = self.__prev[0] - #创建新节点 + # 创建新节点 self.__key[self.__free] = value self.__prev[self.__free] = last_node next_free = self.__next[self.__free] self.__next[self.__free] = 0 - #设置上一个节点 + # 设置上一个节点 self.__next[last_node] = self.__free - #设置起始节点 + # 设置起始节点 self.__prev[0] = self.__free - #设置空链表 + # 设置空链表 self.__free = next_free self.__full = self.__next[0] diff --git a/list/skip_list.py b/src/ssj/list/skip_list.py similarity index 99% rename from list/skip_list.py rename to src/ssj/list/skip_list.py index b86e519..939e0b2 100644 --- a/list/skip_list.py +++ b/src/ssj/list/skip_list.py @@ -132,7 +132,6 @@ def __search(self, value): # 既不能右行也不能下行的时候查询失败 return None - @classmethod def __insert_node(cls, prev_node, down_node, node): next_node = prev_node.next @@ -206,8 +205,3 @@ def main(): if __name__ == "__main__": main() - - - - - diff --git a/list/stack.py b/src/ssj/list/stack.py similarity index 100% rename from list/stack.py rename to src/ssj/list/stack.py diff --git a/src/ssj/map/README.md b/src/ssj/map/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/map/__init__.py b/src/ssj/map/__init__.py new file mode 100644 index 0000000..eee6022 --- /dev/null +++ b/src/ssj/map/__init__.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + +from hash_map import HashMap +from open_address_map import OpenAddressMap diff --git a/hashtable/HashMap.py b/src/ssj/map/hash_map.py similarity index 56% rename from hashtable/HashMap.py rename to src/ssj/map/hash_map.py index 82a1478..abd116e 100644 --- a/hashtable/HashMap.py +++ b/src/ssj/map/hash_map.py @@ -12,7 +12,7 @@ class HashMap(object): # 来自算法导论乘法哈希函数的值,暂时仅支持2**32个元素 HASH_CONST = 2654435769 DEFAULT_SIZE_POWER = 3 - DEFAULT_SIZE = 2 << DEFAULT_SIZE_POWER # aka16 + DEFAULT_SIZE = 2 << DEFAULT_SIZE_POWER # aka8 DEFAULT_LOAD_FACTOR = 0.75 # 默认装载因子0.75 class Node(object): @@ -20,14 +20,17 @@ class Node(object): 哈希表中存储的节点 """ - def __init__(self, key, value, hash_code, prev, nex): + def __init__(self, key, value, hash_code, nex, last_insert, next_insert): """ + nex用来解决链表的哈希冲突 + next_insert用来记录下一个插入的元素 """ self.key = key self.value = value self.hash_code = hash_code self.nex = nex - self.prev = prev + self.last_insert = last_insert + self.next_insert = next_insert def __cmp__(self, other): return cmp(self.key, other.key) @@ -44,13 +47,13 @@ def __init__(self): """""" self.__load_factor = 0 self.__size = 0 # 表示真正存储的元素有几个 - self.__power = HashMap.DEFAULT_SIZE_POWER + self.__power = HashMap.DEFAULT_SIZE_POWER # 把哈希表大小存储为幂数,这样的好处不用在扩展时再从头计算 self.__cap = HashMap.DEFAULT_SIZE # 表示哈希表的容量 self.__head = None - self.__last_put = None - self.__values = [[] for x in range(0, self.__cap)] + self.__last_put = None # 存储上一个插入时的元素,这样便于在插入新元素的时候用指针把他们按照插入顺序连接起来 + self.__values = [None for x in range(0, self.__cap)] # 主要使用的列表 - def hash(self, key): + def __get_index(self, key): """ 乘法哈希函数 :param key: @@ -72,67 +75,87 @@ def __resize(self): # 如果哈希表太满了,则把原来的所有元素都重新插入到哈希表中去 self.__cap *= 2 self.__power += 1 - old_values = self.__values - self.__values = [[] for x in xrange(0, self.__cap)] + self.__values = [None for x in xrange(0, self.__cap)] self.__size = 0 self.__load_factor = 0 self.__last_put = None cur_node = self.__head self.__head = None - while cur_node is not None: + while cur_node: self.__setitem__(cur_node.key, cur_node.value) - cur_node = cur_node.nex + cur_node = cur_node.next_insert def foreach(self, f): cur_node = self.__head - while cur_node is not None: + while cur_node: yield f(cur_node.key, cur_node.value) - cur_node = cur_node.nex + cur_node = cur_node.next_insert def __get(self, key): - index = self.hash(key) - indexed_nodes = self.__values[index] - for node in indexed_nodes: - if node.key == key: - return node + index = self.__get_index(key) + indexed_node = self.__values[index] + while indexed_node: + if indexed_node.key == key: + return indexed_node + indexed_node = indexed_node.nex return None def __contains__(self, key): node = self.__get(key) - return False if node is None else True + return node def __getitem__(self, item): node = self.__get(item) return None if node is None else node.value def __setitem__(self, key, value): - node = self.Node(key, value, HashMap.hash_code(key), self.__last_put, None) - index = self.hash(key) + index = self.__get_index(key) + exists_nodes = self.__values[index] exists_flag = False - for x in range(0, len(exists_nodes)): - if node == exists_nodes[x]: - exists_nodes[x] = node - exists_flag = True + if exists_nodes: + cur_node = exists_nodes + while cur_node: + if cur_node.key == key: + exists_flag = True + cur_node.value = value + node = cur_node + break + cur_node = cur_node.nex + if not exists_flag: - exists_nodes.append(node) + node = self.Node(key, value, HashMap.hash_code(key), exists_nodes, self.__last_put, None) + self.__values[index] = node self.__size += 1 - if self.__last_put is not None: - self.__last_put.nex = node + + if self.__last_put: + self.__last_put.next_insert = node self.__last_put = node - if self.__head is None: + if not self.__head: self.__head = node - self.__load_factor = float(self.__size) / self.__cap self.__resize() def __delitem__(self, key): old_value = None - index = self.hash(key) - indexed_nodes = self.__values[index] - for x in xrange(len(indexed_nodes)): - if indexed_nodes[x].key == key: - old_value = indexed_nodes[x].value - del indexed_nodes[x] + index = self.__get_index(key) + indexed_node = self.__values[index] + last_node = None + while indexed_node: + if indexed_node.key == key: + old_value = indexed_node.value + if last_node: + last_node.nex = indexed_node.nex + else: + self.__values[index] = indexed_node.nex + # 处理哈希表 + self.__size -= 1 + if indexed_node.last_insert: + indexed_node.last_insert.next_insert = indexed_node.next_insert + + if indexed_node.next_insert: + indexed_node.next_insert.last_insert = indexed_node.last_insert + last_node = indexed_node + indexed_node = indexed_node.nex return old_value def __len__(self): @@ -148,12 +171,11 @@ def main(): d["ssh" + str(x)] = x print len(d) print d - del d['ssj100'] - print d['ssj100'] + del d['ssh100'] + print d['ssh100'] + print(len(d)) + print(d) if __name__ == "__main__": main() - - - diff --git a/hashtable/OpenAddressMap.py b/src/ssj/map/open_address_map.py similarity index 99% rename from hashtable/OpenAddressMap.py rename to src/ssj/map/open_address_map.py index a15e83a..7d075bd 100644 --- a/hashtable/OpenAddressMap.py +++ b/src/ssj/map/open_address_map.py @@ -156,4 +156,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/src/ssj/matrix/README.md b/src/ssj/matrix/README.md new file mode 100644 index 0000000..e69de29 diff --git a/matrix/__init__.py b/src/ssj/matrix/__init__.py similarity index 100% rename from matrix/__init__.py rename to src/ssj/matrix/__init__.py diff --git a/matrix/strassen_matrix.py b/src/ssj/matrix/strassen_matrix.py similarity index 99% rename from matrix/strassen_matrix.py rename to src/ssj/matrix/strassen_matrix.py index 0193ef3..b19da92 100755 --- a/matrix/strassen_matrix.py +++ b/src/ssj/matrix/strassen_matrix.py @@ -103,9 +103,8 @@ def __combine_matrix(cls, m11, m12, m21, m22): result[x].extend(temp) return Matrix(m11.__weight + m12.__weight, m11.__height + m21.__height, result) - def __strassen_method(self, other): - #首先需要保证矩阵可以分割 + # 首先需要保证矩阵可以分割 a11, a12, a21, a22 = Matrix.__divide_matrix(self) b11, b12, b21, b22 = Matrix.__divide_matrix(other) # print b11 @@ -150,4 +149,3 @@ def main(): if __name__ == '__main__': main() - \ No newline at end of file diff --git a/src/ssj/number_theory/README.md b/src/ssj/number_theory/README.md new file mode 100644 index 0000000..e69de29 diff --git a/number_theory/__init__.py b/src/ssj/number_theory/__init__.py similarity index 100% rename from number_theory/__init__.py rename to src/ssj/number_theory/__init__.py diff --git a/number_theory/gcd.py b/src/ssj/number_theory/gcd.py similarity index 99% rename from number_theory/gcd.py rename to src/ssj/number_theory/gcd.py index 85203fb..e19879b 100644 --- a/number_theory/gcd.py +++ b/src/ssj/number_theory/gcd.py @@ -17,4 +17,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/src/ssj/other/README.md b/src/ssj/other/README.md new file mode 100644 index 0000000..e64b270 --- /dev/null +++ b/src/ssj/other/README.md @@ -0,0 +1,3 @@ +#本文件夹里面的算法是一些很分散的算法,没有确切的来源 +* find_max_sublist.py 最大连续子数组和问题:从一个所有元素都是数字的数组中找出连续的最大的和,使用二分法可以解决 +* find_max_sublist_without_recursion.py 也是求最大连续子数组和问题,但是这是一种更加高效的算法,负责度只有O(lgN),而且没有递归 \ No newline at end of file diff --git a/string/__init__.py b/src/ssj/other/__init__.py similarity index 100% rename from string/__init__.py rename to src/ssj/other/__init__.py diff --git a/divide_conquer/find_max_sublist.py b/src/ssj/other/find_max_sublist.py similarity index 69% rename from divide_conquer/find_max_sublist.py rename to src/ssj/other/find_max_sublist.py index cea6537..5bac8cd 100755 --- a/divide_conquer/find_max_sublist.py +++ b/src/ssj/other/find_max_sublist.py @@ -8,22 +8,28 @@ 3,跨越了左右半部分。这个时候只要从中点开始分别在左右找最大子数组就可以了。 边界条件是:列表中的元素只有一个的时候 """ +""" +复杂度,使用递归树来分析: +因为二分法,树的高度是lgN。 +每一层树的复杂度是N,因为find_max_in_middle中需要把所有节点都遍历一遍 +所以整体复杂度是O(NlgN) +""" def find_max_sublist(li): li_len = len(li) if li_len < 2: - return (0, 0, sum(li)) + return 0, 0, sum(li) middle = li_len / 2 m_x, m_y, m_sum = find_max_in_middle(li, middle) l_x, l_y, l_sum = find_max_sublist(li[:middle]) r_x, r_y, r_sum = find_max_sublist(li[middle + 1:]) if m_sum >= l_sum and m_sum >= r_sum: - return (m_x, m_y, m_sum) + return m_x, m_y, m_sum elif l_sum >= m_sum and l_sum >= r_sum: - return (l_x, l_y, l_sum) + return l_x, l_y, l_sum else: - return (r_x, r_y, r_sum) + return r_x, r_y, r_sum """ @@ -39,7 +45,7 @@ def find_max_sublist(li): def find_max_in_middle(li, middle): li_len = len(li) left_max_index, right_max_index = 0, middle - #这里有一个bug,如果列表里面所有的数据都是负的,那么就找不到最小值了 + # 这里有一个bug,如果列表里面所有的数据都是负的,那么就找不到最小值了 left_max_sum, cur_sum, right_max_sum = li[middle - 1], 0, li[middle] for x in reversed(xrange(0, middle)): cur_sum += li[x] @@ -52,13 +58,13 @@ def find_max_in_middle(li, middle): if cur_sum > right_max_sum: right_max_sum = cur_sum right_max_index = x - #这里并没有判断一端结果为负的情况,因为这个时候可以在其中一端的列表中得到最大子数列 - return (left_max_index, right_max_index, right_max_sum + left_max_sum) + # 这里并没有判断一端结果为负的情况,因为这个时候可以在其中一端的列表中得到最大子数列 + return left_max_index, right_max_index, right_max_sum + left_max_sum def main(): - print find_max_sublist([0]) + print find_max_sublist([1, -2, 3, 10, -4, 7, 2, -5]) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/ssj/other/find_max_sublist_without_recursion.py b/src/ssj/other/find_max_sublist_without_recursion.py new file mode 100755 index 0000000..b22a692 --- /dev/null +++ b/src/ssj/other/find_max_sublist_without_recursion.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*-coding:utf-8 -*- + +""" +复杂度是O(N),因为只需要遍历一遍数组就可以了 +""" + +""" +思想:采取打擂台的方法,也就是把最大值时刻放在擂台上和别的和比较。 +同样的方法我用来解决leecode的问题中的https://leetcode.com/problems/longest-palindromic-substring/ +采用打擂台的方法解决的问题有同样的特点就是:他们都要求连续,只要要求连续才能保证算法的正确性。 + +对于本题的算法正确性,可以使用递归法来证明: +基本情况:不用证明。 +""" + + +def find_max_sublist(li): + b, max_sum, left, right = 0, 0, 0, 0 + li_len = len(li) + for x in xrange(0, li_len): + if b < 0: + b = li[x] + left = x + else: + b += li[x] + if max_sum < b: + right = x + max_sum = b + + return left, right, max_sum + + +def main(): + print find_max_sublist([1, -2, 3, 10, -4, 7, 2, -5]) + + +if __name__ == '__main__': + main() diff --git a/divide_conquer/power.py b/src/ssj/other/power.py similarity index 88% rename from divide_conquer/power.py rename to src/ssj/other/power.py index 72522dd..0ecc96d 100755 --- a/divide_conquer/power.py +++ b/src/ssj/other/power.py @@ -13,8 +13,8 @@ def power(x, n): def main(): - print power(1000, 1) + print power(1000, 2) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/divide_conquer/yong_matrix.py b/src/ssj/other/yong_matrix.py similarity index 86% rename from divide_conquer/yong_matrix.py rename to src/ssj/other/yong_matrix.py index ede339c..909d31b 100644 --- a/divide_conquer/yong_matrix.py +++ b/src/ssj/other/yong_matrix.py @@ -13,7 +13,7 @@ def extract_min(matrix, w, h): left = empty_index + w right = empty_index + 1 # 1,矩阵碰到右边界的时候 - #2,右边的值是None,表示没有元素 + # 2,右边的值是None,表示没有元素 print "left :", left print "right :", right if left > (w * h - 1) and right % w is 0: @@ -23,12 +23,12 @@ def extract_min(matrix, w, h): if left <= (w * h - 1) and (right % w is 0 or matrix[right] is None or matrix[left] <= matrix[right]): matrix[empty_index] = matrix[left] empty_index = left - #1,判断矩阵碰到左边界的时候 - #2,左边的值是None,表示值是None + # 1,判断矩阵碰到左边界的时候 + # 2,左边的值是None,表示值是None elif left > (w * h - 1) or matrix[left] is None or matrix[left] > matrix[right]: matrix[empty_index] = matrix[right] empty_index = right - #到最终节点的时候 + # 到最终节点的时候 else: matrix[empty_index] = None break @@ -47,4 +47,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/src/ssj/queue/README.md b/src/ssj/queue/README.md new file mode 100644 index 0000000..e69de29 diff --git a/tree/__init__.py b/src/ssj/queue/__init__.py similarity index 100% rename from tree/__init__.py rename to src/ssj/queue/__init__.py diff --git a/queue/fifo_queue.py b/src/ssj/queue/fifo_queue.py similarity index 94% rename from queue/fifo_queue.py rename to src/ssj/queue/fifo_queue.py index 2a27ee5..6330077 100644 --- a/queue/fifo_queue.py +++ b/src/ssj/queue/fifo_queue.py @@ -31,14 +31,14 @@ def heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] self.heapify(largest) @@ -52,14 +52,14 @@ def loop_heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] parent = largest @@ -84,7 +84,6 @@ def __deep_walk_through(self, func, start=0): self.__deep_walk_through(func, left) self.__deep_walk_through(func, right) - def __str__(self): title = "Heap Length: %s\n" % self.length content_list = [title] @@ -102,7 +101,7 @@ def append(self, value): insert_index = self.length while True: parent = (insert_index - 1) / 2 - #这儿需要判断使得parent不会越界 + # 这儿需要判断使得parent不会越界 if parent >= 0 and self.__array[insert_index] > self.__array[parent]: self.__array[parent], self.__array[insert_index] = self.__array[insert_index], self.__array[parent] insert_index = parent @@ -119,7 +118,7 @@ def append_with_one_assign(self, value): insert_index = self.length while True: parent = (insert_index - 1) / 2 - #这儿需要判断使得parent不会越界 + # 这儿需要判断使得parent不会越界 if parent >= 0 and value > self.__array[parent]: self.__array[insert_index] = self.__array[parent] insert_index = parent @@ -128,7 +127,6 @@ def append_with_one_assign(self, value): self.__array[insert_index] = value self.length += 1 - def __setitem__(self, index, value): self.__array[index] = value @@ -221,7 +219,6 @@ def __setitem__(self, key, value): node = MaxQueue.Node(key, value) self.__heap.append_with_one_assign(node) - def __str__(self): return str(self.__heap) @@ -258,4 +255,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/queue/list_queue.py b/src/ssj/queue/list_queue.py similarity index 99% rename from queue/list_queue.py rename to src/ssj/queue/list_queue.py index aacddae..ee37e58 100644 --- a/queue/list_queue.py +++ b/src/ssj/queue/list_queue.py @@ -33,7 +33,6 @@ def enter(self, x): if self.__tail >= self.__cap: self.__tail = 0 - def exit(self): if self.__tail == self.__head and self.__value[self.__head] is self.__empty: raise IndexError("queue is empty") @@ -53,5 +52,3 @@ def __len__(self): return 0 else: return self.__cap - - diff --git a/src/ssj/search/README.md b/src/ssj/search/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/search/__init__.py b/src/ssj/search/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/search/binary_search.py b/src/ssj/search/binary_search.py similarity index 99% rename from search/binary_search.py rename to src/ssj/search/binary_search.py index 397a474..30830b3 100755 --- a/search/binary_search.py +++ b/src/ssj/search/binary_search.py @@ -35,4 +35,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/search/find_kth_with_middle.py b/src/ssj/search/find_kth_with_middle.py similarity index 53% rename from search/find_kth_with_middle.py rename to src/ssj/search/find_kth_with_middle.py index 80d931c..1137fa8 100644 --- a/search/find_kth_with_middle.py +++ b/src/ssj/search/find_kth_with_middle.py @@ -1,4 +1,4 @@ # /usr/bin/env python -#-*- coding:uft-8 +# -*- coding:uft-8 +""" """ -""" \ No newline at end of file diff --git a/search/find_middle_of_two_sorted_array.py b/src/ssj/search/find_middle_of_two_sorted_array.py similarity index 97% rename from search/find_middle_of_two_sorted_array.py rename to src/ssj/search/find_middle_of_two_sorted_array.py index 18baf76..021a7b8 100644 --- a/search/find_middle_of_two_sorted_array.py +++ b/src/ssj/search/find_middle_of_two_sorted_array.py @@ -27,4 +27,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/search/find_min_max.py b/src/ssj/search/find_min_max.py similarity index 93% rename from search/find_min_max.py rename to src/ssj/search/find_min_max.py index ad442e0..9dcc1e3 100644 --- a/search/find_min_max.py +++ b/src/ssj/search/find_min_max.py @@ -1,5 +1,5 @@ # /usr/bin/env python -#-*- coding:utf-8 -*- +# -*- coding:utf-8 -*- """ 同时找出一个列表中的最大和最小的值,算法实现的时候分别记录 了到当前的最大值和最小值。并且每次比较都对一对输入元素进行比较。 @@ -21,7 +21,7 @@ def find_min_max(li): li_max = li[0] start = 2 - #处理奇数的情况 + # 处理奇数的情况 if li_len / 2 is 1 and li_len >= 3: start += 1 if li[3] < li_min: @@ -30,7 +30,7 @@ def find_min_max(li): li_max = li[3] for x in xrange(start, li_len, 2): - #默认first是小的 + # 默认first是小的 first = li[x] second = li[x + 1] if first > second: @@ -51,5 +51,3 @@ def main(): if __name__ == '__main__': main() - - diff --git a/search/find_sum_equals.py b/src/ssj/search/find_sum_equals.py similarity index 95% rename from search/find_sum_equals.py rename to src/ssj/search/find_sum_equals.py index fc559ad..0b13319 100755 --- a/search/find_sum_equals.py +++ b/src/ssj/search/find_sum_equals.py @@ -31,7 +31,7 @@ def binary_search(sorted_list, value): def __merge_sort__(llist, rlist): llen = len(llist) rlen = len(rlist) - #递归结束时间:[]和[ele] + # 递归结束时间:[]和[ele] if llen + rlen < 2: return llist + rlist lrst = __merge_sort__(llist[:llen / 2], llist[llen / 2:]) @@ -39,7 +39,7 @@ def __merge_sort__(llist, rlist): lcursor, rcursor = 0, 0 result = [] min_len = min(llen, rlen) - #从小到大排序 + # 从小到大排序 while lcursor < llen and rcursor < rlen: if lrst[lcursor] < rrst[rcursor]: result.append(lrst[lcursor]) @@ -47,7 +47,7 @@ def __merge_sort__(llist, rlist): else: result.append(rrst[rcursor]) rcursor += 1 - #把没有合并的数据合并起来。 + # 把没有合并的数据合并起来。 result.extend(lrst[lcursor:]) result.extend(rrst[rcursor:]) return result @@ -75,4 +75,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/search/random_loop_section.py b/src/ssj/search/random_loop_section.py similarity index 96% rename from search/random_loop_section.py rename to src/ssj/search/random_loop_section.py index 16b9a25..aa61598 100644 --- a/search/random_loop_section.py +++ b/src/ssj/search/random_loop_section.py @@ -8,7 +8,7 @@ def partition(li, start, end): if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") # 使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] @@ -53,4 +53,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/search/random_selection.py b/src/ssj/search/random_selection.py similarity index 86% rename from search/random_selection.py rename to src/ssj/search/random_selection.py index 1afcc75..2abd7c2 100644 --- a/search/random_selection.py +++ b/src/ssj/search/random_selection.py @@ -7,8 +7,8 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 使用随机元素元素作为分割点并且把随机元素放在列表最后 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] @@ -27,7 +27,7 @@ def partition(li, start, end): def selection(li, start, end, kth): - #一定会找到一个元素,因此这儿直接返回是对的。 + # 一定会找到一个元素,因此这儿直接返回是对的。 if start == end: return li[start] mid_index = partition(li, start, end) diff --git a/search/split_nth.py b/src/ssj/search/split_nth.py similarity index 91% rename from search/split_nth.py rename to src/ssj/search/split_nth.py index 696907e..ea062c6 100644 --- a/search/split_nth.py +++ b/src/ssj/search/split_nth.py @@ -7,8 +7,8 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用随机元素元素作为分割点并且把随机元素放在列表最后 - #这样就可以不变动原来的逻辑了 + # 使用随机元素元素作为分割点并且把随机元素放在列表最后 + # 这样就可以不变动原来的逻辑了 key_index = randint(start, end) key = li[key_index] li[key_index], li[end] = li[end], li[key_index] @@ -27,7 +27,7 @@ def partition(li, start, end): def selection(li, start, end, kth): - #一定会找到一个元素,因此这儿直接返回是对的。 + # 一定会找到一个元素,因此这儿直接返回是对的。 if start == end: return start mid_index = partition(li, start, end) @@ -55,7 +55,7 @@ def split_even_nth(li, start, end, k, kth_list): return kth_list if k % 2 is 1: return split_odd_nth(li, start, end, k, kth_list) - middle_index = selection(li, start, end, (end - start - 1) / 2) #必须要减一,分割的点是中间元素的前一个 + middle_index = selection(li, start, end, (end - start - 1) / 2) # 必须要减一,分割的点是中间元素的前一个 print "start:%s,end:%s,mid_index:%s" % (start, end, middle_index) kth_list.append(li[middle_index]) split_even_nth(li, start, middle_index, k / 2, kth_list) diff --git "a/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" "b/src/ssj/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" similarity index 100% rename from "search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" rename to "src/ssj/search/\344\270\244\344\270\252\346\234\211\345\272\217\345\210\227\350\241\250\345\220\210\345\271\266\347\232\204\347\244\272\346\204\217\345\233\276.png" diff --git a/src/ssj/sort/README.md b/src/ssj/sort/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/sort/__init__.py b/src/ssj/sort/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/sort/bubble_sort.py b/src/ssj/sort/bubble_sort.py similarity index 99% rename from sort/bubble_sort.py rename to src/ssj/sort/bubble_sort.py index 825adf6..285e0c4 100755 --- a/sort/bubble_sort.py +++ b/src/ssj/sort/bubble_sort.py @@ -24,5 +24,3 @@ def main(): if __name__ == '__main__': main() - - diff --git a/sort/bucketsort.png b/src/ssj/sort/bucketsort.png similarity index 100% rename from sort/bucketsort.png rename to src/ssj/sort/bucketsort.png diff --git a/sort/counting_sort.py b/src/ssj/sort/counting_sort.py similarity index 98% rename from sort/counting_sort.py rename to src/ssj/sort/counting_sort.py index 8d48e42..9f493d6 100644 --- a/sort/counting_sort.py +++ b/src/ssj/sort/counting_sort.py @@ -32,4 +32,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/sort/countingsort.png b/src/ssj/sort/countingsort.png similarity index 100% rename from sort/countingsort.png rename to src/ssj/sort/countingsort.png diff --git a/sort/fuzzy_space_quick_sort.py b/src/ssj/sort/fuzzy_space_quick_sort.py similarity index 97% rename from sort/fuzzy_space_quick_sort.py rename to src/ssj/sort/fuzzy_space_quick_sort.py index 24b9916..e7a3aef 100644 --- a/sort/fuzzy_space_quick_sort.py +++ b/src/ssj/sort/fuzzy_space_quick_sort.py @@ -1,6 +1,5 @@ #!/usr/bin/env python # -*- coding:utf-8 -*- -from math import * """ 模糊空间排序唯一需要考虑的问题就是空间的合并。 @@ -43,7 +42,7 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用最后一个元素作为分割点 + # 使用最后一个元素作为分割点 key = li[end] middle_index = start for x in xrange(start, end + 1): diff --git a/sort/heap_sort.py b/src/ssj/sort/heap_sort.py similarity index 91% rename from sort/heap_sort.py rename to src/ssj/sort/heap_sort.py index 02aae02..86ad116 100644 --- a/sort/heap_sort.py +++ b/src/ssj/sort/heap_sort.py @@ -31,14 +31,14 @@ def heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] self.heapify(largest) @@ -52,14 +52,14 @@ def loop_heapify(self, parent): largest = parent left = parent * 2 + 1 right = parent * 2 + 2 - #这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 + # 这个地方使用left和right比较,是为了防止到了叶节点的时候会出现数组越界。 if left < self.length and self.__array[parent] < self.__array[left]: largest = left if right < self.length and self.__array[largest] < self.__array[right]: largest = right - #保证在父元素就是最大值的时候不要移动元素 + # 保证在父元素就是最大值的时候不要移动元素 if largest != parent: self.__array[largest], self.__array[parent] = self.__array[parent], self.__array[largest] parent = largest @@ -84,7 +84,6 @@ def __deep_walk_through(self, func, start=0): self.__deep_walk_through(func, left) self.__deep_walk_through(func, right) - def __str__(self): title = "Heap Length: %s\n" % self.length content_list = [title] @@ -103,7 +102,6 @@ def __deepcopy__(self): newone.__dict__[x] = copy.deepcopy(self.__dict__[x]) return newone - @classmethod def heap_sort(cls, list): """ diff --git a/sort/hoare_quick_sort.py b/src/ssj/sort/hoare_quick_sort.py similarity index 98% rename from sort/hoare_quick_sort.py rename to src/ssj/sort/hoare_quick_sort.py index 4b12114..ddd3f58 100644 --- a/sort/hoare_quick_sort.py +++ b/src/ssj/sort/hoare_quick_sort.py @@ -36,4 +36,4 @@ def main(): # print quick_sort(li,0,11) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/sort/improve_fuzzy_space_quick_sort.py b/src/ssj/sort/improve_fuzzy_space_quick_sort.py similarity index 93% rename from sort/improve_fuzzy_space_quick_sort.py rename to src/ssj/sort/improve_fuzzy_space_quick_sort.py index e579116..d8f81dc 100644 --- a/sort/improve_fuzzy_space_quick_sort.py +++ b/src/ssj/sort/improve_fuzzy_space_quick_sort.py @@ -1,6 +1,5 @@ #!/usr/bin/env python # -*- coding:utf-8 -*- -from math import * """ 模糊空间排序唯一需要考虑的问题就是空间的合并。 @@ -45,7 +44,7 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用最后一个元素作为分割点 + # 使用最后一个元素作为分割点 print "end:", end key = li[end] middle_index = start @@ -54,7 +53,7 @@ def partition(li, start, end): li[middle_index], li[x] = li[x], li[middle_index] middle_index += 1 li[end], li[middle_index] = li[middle_index], li[end] - #处理middle_index:middle_index有两种情况,一是被合并,二是合并其他元素。 + # 处理middle_index:middle_index有两种情况,一是被合并,二是合并其他元素。 result = [] for i in xrange(start, end + 1): x = li[i] @@ -93,4 +92,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/sort/insert_sort.py b/src/ssj/sort/insert_sort.py similarity index 54% rename from sort/insert_sort.py rename to src/ssj/sort/insert_sort.py index 29201fb..d2bc385 100755 --- a/sort/insert_sort.py +++ b/src/ssj/sort/insert_sort.py @@ -4,17 +4,17 @@ def main(): print reverse_insert_sort([2, 13, 4, 1919, 1, 1100, 1, 2, 3, 373737, 0]) -#从小到大排序 +# 从小到大排序 def insert_sort(li): list_len = len(li) if list_len < 2: return li for x in xrange(1, list_len): cursor = li[x] - #算法不是从头开始比较的,而是从Cursor的上一个元素比较的,否则必须使用多个循环。 + # 算法不是从头开始比较的,而是从Cursor的上一个元素比较的,否则必须使用多个循环。 for y in reversed(xrange(0, x)): - if cursor < li[y]: #一个重要的细节:如果两个元素相等,那么它们的顺序不会变 - #忽略了一个边界条件cursor=1,而li[0]=2的时候,需要li[0]=cursor + if cursor < li[y]: # 一个重要的细节:如果两个元素相等,那么它们的顺序不会变 + # 忽略了一个边界条件cursor=1,而li[0]=2的时候,需要li[0]=cursor li[y + 1], li[y] = li[y], cursor else: li[y + 1] = cursor @@ -28,10 +28,10 @@ def reverse_insert_sort(li): return li for x in xrange(1, list_len): cursor = li[x] - #算法不是从头开始比较的,而是从Cursor的上一个元素比较的,负责必须使用多个循环。 + # 算法不是从头开始比较的,而是从Cursor的上一个元素比较的,负责必须使用多个循环。 for y in reversed(xrange(0, x)): - if cursor > li[y]: #一个重要的细节:如果两个元素相等,那么它们的顺序不会变 - #忽略了一个边界条件cursor=1,而li[0]=2的时候,需要li[0]=cursor + if cursor > li[y]: # 一个重要的细节:如果两个元素相等,那么它们的顺序不会变 + # 忽略了一个边界条件cursor=1,而li[0]=2的时候,需要li[0]=cursor li[y + 1], li[y] = li[y], cursor else: li[y + 1] = cursor @@ -41,6 +41,3 @@ def reverse_insert_sort(li): if __name__ == '__main__': main() - - - diff --git a/sort/merge_sort.py b/src/ssj/sort/merge_sort.py similarity index 88% rename from sort/merge_sort.py rename to src/ssj/sort/merge_sort.py index 8066b26..aa9bd4d 100755 --- a/sort/merge_sort.py +++ b/src/ssj/sort/merge_sort.py @@ -14,7 +14,7 @@ def main(): def merge_sort(llist, rlist): llen = len(llist) rlen = len(rlist) - #递归结束时间:[]和[ele] + # 递归结束时间:[]和[ele] if llen + rlen < 2: return llist + rlist lrst = merge_sort(llist[:llen / 2], llist[llen / 2:]) @@ -22,7 +22,7 @@ def merge_sort(llist, rlist): lcursor, rcursor = 0, 0 result = [] min_len = min(llen, rlen) - #从小到大排序 + # 从小到大排序 while lcursor < llen and rcursor < rlen: if lrst[lcursor] < rrst[rcursor]: result.append(lrst[lcursor]) @@ -30,11 +30,11 @@ def merge_sort(llist, rlist): else: result.append(rrst[rcursor]) rcursor += 1 - #把没有合并的数据合并起来。 + # 把没有合并的数据合并起来。 result.extend(lrst[lcursor:]) result.extend(rrst[rcursor:]) return result if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/sort/quick_sort.py b/src/ssj/sort/quick_sort.py similarity index 94% rename from sort/quick_sort.py rename to src/ssj/sort/quick_sort.py index b0705d5..ec28543 100644 --- a/sort/quick_sort.py +++ b/src/ssj/sort/quick_sort.py @@ -5,7 +5,7 @@ def partition(li, start, end): li_len = end - start + 1 if li_len < 2: raise ValueError("list which lenght is less then 2 do not need to partition") - #使用最后一个元素作为分割点 + # 使用最后一个元素作为分割点 key = li[end] middle_index = start for x in xrange(start, end): diff --git a/sort/random_quick_sort.py b/src/ssj/sort/random_quick_sort.py similarity index 100% rename from sort/random_quick_sort.py rename to src/ssj/sort/random_quick_sort.py diff --git a/sort/random_two_partition_quick_sort.py b/src/ssj/sort/random_two_partition_quick_sort.py similarity index 98% rename from sort/random_two_partition_quick_sort.py rename to src/ssj/sort/random_two_partition_quick_sort.py index 6482cc5..13cb4ef 100644 --- a/sort/random_two_partition_quick_sort.py +++ b/src/ssj/sort/random_two_partition_quick_sort.py @@ -36,4 +36,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/sort/recursive_insert_sort.py b/src/ssj/sort/recursive_insert_sort.py similarity index 76% rename from sort/recursive_insert_sort.py rename to src/ssj/sort/recursive_insert_sort.py index 627d5fa..e290b6f 100755 --- a/sort/recursive_insert_sort.py +++ b/src/ssj/sort/recursive_insert_sort.py @@ -12,15 +12,15 @@ def recursive_insert_sort(li): li_len = len(li) if li_len < 2: return li - first = li[0] #取出第一个元素 - sorted_li = recursive_insert_sort(li[1:]) #默认从小到大 + first = li[0] # 取出第一个元素 + sorted_li = recursive_insert_sort(li[1:]) # 默认从小到大 for x in xrange(0, li_len - 1): if first > sorted_li[x]: li[x] = sorted_li[x] else: - #由于Python列表切片的规则,这个地方不用判断列表的索引是不是 - #超过了列表的大小,因为如果在切片中超出列表大小,返回的是一个 - #空列表 + # 由于Python列表切片的规则,这个地方不用判断列表的索引是不是 + # 超过了列表的大小,因为如果在切片中超出列表大小,返回的是一个 + # 空列表 li[x] = first li[x + 1:] = sorted_li[x:] break diff --git a/sort/select_sort.py b/src/ssj/sort/select_sort.py similarity index 98% rename from sort/select_sort.py rename to src/ssj/sort/select_sort.py index f045f26..25b0afa 100755 --- a/sort/select_sort.py +++ b/src/ssj/sort/select_sort.py @@ -25,4 +25,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/src/ssj/string/README.md b/src/ssj/string/README.md new file mode 100644 index 0000000..e69de29 diff --git a/dynamic/lps/__init__.py b/src/ssj/string/__init__.py similarity index 97% rename from dynamic/lps/__init__.py rename to src/ssj/string/__init__.py index 414d02d..fb57e2f 100644 --- a/dynamic/lps/__init__.py +++ b/src/ssj/string/__init__.py @@ -1,5 +1,3 @@ #!/usr/bin/env python # -*- coding:UTF-8 __author__ = 'shenshijun' - - diff --git a/string/kmp.py b/src/ssj/string/kmp.py similarity index 98% rename from string/kmp.py rename to src/ssj/string/kmp.py index cb2bcb1..e92a8f0 100644 --- a/string/kmp.py +++ b/src/ssj/string/kmp.py @@ -20,7 +20,6 @@ def build_next(): origin_index, pattern_index = 0, 0 next_list = build_next() - print(next_list) while origin_index < origin_len: # while需要放在前面,如果放在后面的话且有匹配的情况下pattern[pattern_index]就会越界 while pattern_index > 0 and origin[origin_index] != pattern[pattern_index]: @@ -39,6 +38,3 @@ def main(): if __name__ == "__main__": main() - - - diff --git a/string/rabin-karp.py b/src/ssj/string/rabin-karp.py similarity index 100% rename from string/rabin-karp.py rename to src/ssj/string/rabin-karp.py diff --git a/string/simple.py b/src/ssj/string/simple.py similarity index 100% rename from string/simple.py rename to src/ssj/string/simple.py diff --git a/src/ssj/tree/BTree.py b/src/ssj/tree/BTree.py new file mode 100644 index 0000000..e11ab7a --- /dev/null +++ b/src/ssj/tree/BTree.py @@ -0,0 +1,420 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +from ssj.lib.stack import Stack + +__author__ = 'shenshijun' + + +class Node(object): + def __init__(self, is_leaf, keys, childs=None, parent=None): + """ + 在真实的实现中应该在加上一个数组表示指向真实数据的指针 + keys和childs都是一个数组,分别表示关键字和孩子 + """ + self.keys = list(sorted(keys)) + self.is_leaf = is_leaf + self.__size = len(self.keys) + if not self.is_leaf and childs is None: + self.childs = [None for x in xrange(0, self.__size + 1)] + else: + self.childs = childs + self.parent = parent + + def __str__(self): + return "".join(['Node(keys=', ",".join(map(lambda key: str(key), self.keys)), + ',Leaf' if self.is_leaf else ',Not Leaf', + ',childs num=', '0' if self.is_leaf else str(len(self.childs)), ')\n']) + + def __len__(self): + return self.__size + + def append(self, key): + """ + 向B树的节点中插入一个关键字,返回这个关键字的下标 + """ + result = self.__size + self.__size += 1 + + for x in xrange(0, result): + if self.keys[x] > key: + self.keys.insert(x, key) + if not self.is_leaf: + self.childs.insert(x, None) + return x + self.keys.append(key) + if not self.is_leaf: + self.childs.append(None) + return result + + def search_child(self, instance): + """ + 查找小于instance的子树 + """ + for x in xrange(0, self.__size): + if self.keys[x] > instance: + return self.childs[x] + return self.childs[self.__size] + + def leaf_remove(self, index): + if self.is_leaf: + del self.keys[index] + self.__size -= 1 + + +class BTree(object): + """ + B树实现,注意,不是二叉树 + """ + + def __init__(self, load_factor=4, *vargs): + """Constructor for BTree""" + self.__root = None + self.__load_factor = load_factor + self.__size = 0 + map(self.insert, vargs) + + def insert(self, key): + """ + 插入一个节点 + :param key: + :return: + """ + if self.__root is None: + self.__root = Node(True, [key]) + return + + cur_node = self.__root + while not cur_node.is_leaf: + self.__split(cur_node) + # 这个地方cur_node并没有被改变,所以是可以继续搜索的。 + cur_node = cur_node.search_child(key) + + left_node, right_node = self.__split(cur_node) + if left_node is None or right_node is None: + # 返回None表示叶节点没有满 + cur_node.append(key) + else: + # 找到左右节点的共同关键字 + parent_key = None + parent = left_node.parent + for i in xrange(len(parent)): + if parent.childs[i] is left_node: + parent_key = parent.keys[i] + + if parent_key <= key: + # 说明left_node中的所有节点都比key小,所以把新节点插入到右边 + right_node.append(key) + else: + left_node.append(key) + + self.__size += 1 + + def __split(self, node): + """ + 在节点满的时候分裂节点。要注意两个问题: + 1,根节点分裂的时候需要重新设置根节点 + 2,叶节点是没有子节点的,一次要时刻判断 + :param node: + :return: + """ + if self.full(node): + parent_node = node.parent + middle_key = node.keys[self.__load_factor - 1] + if parent_node is None: + # 处理根节点 + parent_node = self.__root = Node(False, []) + + parent_middle_index = parent_node.append(middle_key) + left_node = Node(node.is_leaf, node.keys[:self.__load_factor - 1], + None if node.is_leaf else node.childs[:self.__load_factor], + parent_node) + + right_node = Node(node.is_leaf, node.keys[self.__load_factor:], + None if node.is_leaf else node.childs[self.__load_factor:], + parent_node) + + # 注意设定分裂节点的子节点的父指针,因为如果node是叶节点,那么两个子节点肯定都是叶节点,反之同理 + if not node.is_leaf: + for child in left_node.childs: + if child is not None: + child.parent = left_node + for child in right_node.childs: + if child is not None: + child.parent = right_node + + parent_node.childs[parent_middle_index] = left_node + parent_node.childs[parent_middle_index + 1] = right_node + self.__root.is_leaf = False + return left_node, right_node + return None, None + + def search(self, instance): + """ + 查找一个元素的位置,位置使用一个tuple表示,前面一个元素是Node,后面一个元素是元素的位置 + :param instance: + :return:(Node, index) + """ + return self.__search(self.__root, instance) + + def full(self, node): + return len(node) >= (self.__load_factor * 2 - 1) + + @classmethod + def __search(cls, root, instance): + """ + 搜索树中节点 + :param root: + :param instance: + :return: + """ + cur_node = root + while True: + cur_len = len(cur_node) + x = 0 + while x < cur_len and cur_node.keys[x] < instance: + x += 1 + if x < cur_len and cur_node.keys[x] == instance: + return cur_node, x + elif cur_node.is_leaf: + return None, None + else: + cur_node = cur_node.childs[x] + + def min(self): + """ + 取出树中最小值 + :return: + """ + cur_node = self.__root + while not cur_node.is_leaf: + cur_node = cur_node.childs[0] + return cur_node.keys[0] + + def max(self): + """ + 取出树中最大值 + :return: + """ + cur_node = self.__root + while not cur_node.is_leaf: + cur_node = cur_node.childs[-1] + return cur_node.keys[-1] + + def mid_order(self, f): + """ + B树中序遍历 + :param f: + :return: + """ + result = [] + stack = Stack() + cur_node = self.__root + if cur_node.is_leaf: + return map(f, cur_node.keys) + + while True: + if cur_node.is_leaf: + # 到叶节点了,开始把叶节点的所有关键字都遍历掉 + result.extend(map(f, cur_node.keys)) + # 开始从栈中取元素,遍历下一个节点叶节点 + if stack.empty(): + return result + cur_node, i = stack.pop() + result.append(f(cur_node.keys[i])) + if i < len(cur_node) - 1: + stack.push((cur_node, i + 1)) + cur_node = cur_node.childs[i + 1] + else: + stack.push((cur_node, 0)) + cur_node = cur_node.childs[0] + return result + + def delete(self, key): + """ + 删除一个关键字 + :param key: + :return: + """ + node, index = self.search(key) + if node is None: + return False + + return self.__delete(node, index) + + def __delete(self, node, index): + if node is None: + return False + + if node.is_leaf: + self.__size -= 1 + + if self.will_starve(node): + # 检查是否能从兄弟节点借一个元素,会检查左右两个节点。如果不能从兄弟节点借,那么就只能和兄弟节点合并了 + change_index, bro_node, bro_index = self.__check_brother_borrow(node) + if bro_node is None: + del node.keys[index] + + self.__merge_brother(node) + else: + parent = node.parent + node.keys[index] = parent.keys[change_index] + parent.keys[change_index] = bro_node.keys[bro_index] + bro_node.leaf_remove(bro_index) + else: + # 删除之后节点还是有效的B树节点,因此直接从B树中删除元素 + node.leaf_remove(index) + else: + # 如果节点删除发生在内部节点上,那么先把后继节点上的关键字移动到被删除的元素的位置上,然后把后继节点删除 + succ, succ_index = self.__successor(node, index) + node.keys[index] = succ.keys[succ_index] + # 因为调用了自己,所有并没有把size减一 + return self.__delete(succ, succ_index) + return True + + def __successor(self, node, i): + """ + 查找在node的i处的节点的关键字的后继节点,位置使用一个元祖表示,前面的一个元素是node,后面的是index + 如果返回None表示没有后继,也就是说是最大元素 + :param node: + :param i: + :return:(Node,index)|None + """ + if not node.is_leaf: + child_node = node.childs[i + 1] + while not child_node.is_leaf: + child_node = child_node.childs[0] + return self.__successor(child_node, -1) + else: + if i < len(node) - 1: + return node, i + 1 + else: + return None, None + + def will_starve(self, node): + """ + 检查一个节点的元素是否小于load_factor,这样的话如果在删除一个关键字节点就不符合B树的节点定义了 + :param node: + :return: + """ + return len(node) < self.__load_factor + + def successor(self, key): + """ + 查找关键字的后继节点,位置使用一个元祖表示,前面的一个元素是node,后面的是index + 如果返回None表示没有后继,也就是说是最大元素 + :param key: + :return:(Node,index)|None + """ + node, index = self.search(key) + if node is None: + return None, None + return self.__successor(node, index) + + def __str__(self): + return "\n".join(self.mid_order(lambda s: str(s))) + + def test(self): + node = self.successor('0') + print(node) + + def __check_brother_borrow(self, node): + """ + 检查左右的兄弟节点是否能够借出节点 + int:父节点中交换元素的位置 + Node:要借出元素的节点 + int:借出元素的位置 + + 如果不能借出,那么返回(None,None,None) + :param node: + :return:(int,Node,int)|(None,None,None) + """ + parent = node.parent + node_index = -1 + # 寻找node在parent的位置 + for i in xrange(len(parent.childs)): + if parent.childs[i] is node: + node_index = i + + # 先从左边的兄弟节点借 + if node_index >= 1 and not self.will_starve(parent.childs[node_index - 1]): + return node_index - 1, parent.childs[node_index - 1], -1 + + if node_index >= 0 and not self.will_starve(parent.childs[node_index + 1]): + return node_index, parent.childs[node_index + 1], 0 + + return None, None, None + + def __merge_brother(self, node): + parent = node.parent + if parent is self.__root and len(parent.keys) > 0: + return + + node_index = -1 + # 寻找node在parent的位置 + for i in xrange(len(parent.childs)): + if parent.childs[i] is node: + node_index = i + + # 合并只和长度较小的节点合并 + smaller_node = None + is_left = True + if node_index >= 1: + smaller_node = parent.childs[node_index - 1] + + if node_index >= 0 and (smaller_node is None or len(smaller_node) > parent.childs[node_index + 1]): + smaller_node = parent.childs[node_index + 1] + is_left = False + + # 只有在必要的时候才合并 + if len(smaller_node) < self.__load_factor - 1 or len(node) < self.__load_factor - 1: + if is_left: + new_keys = smaller_node.keys + new_keys.append(parent.keys[node_index - 1]) + new_keys.extend(node.keys) + else: + new_keys = node.keys + new_keys.append(parent.keys[node_index - 1]) + new_keys.extend(smaller_node.keys) + + new_childs = None + if not node.is_leaf: + if is_left: + new_childs = smaller_node.childs + new_childs.extend(node.childs) + else: + new_childs = node.childs + new_childs.extend(smaller_node.childs) + + new_node = Node(node.is_leaf, new_keys, new_childs, parent) + + # 从父节点中删除被拿到子节点的节点 + if is_left: + del parent.childs[node_index - 1] + del parent.keys[node_index - 1] + parent.childs[node_index - 1] = new_node + else: + del parent.childs[node_index + 1] + del parent.keys[node_index + 1] + parent.childs[node_index] = new_node + + # 处理根节点,然后调用递归调用合并父节点 + if parent is self.__root and len(parent.keys): + new_node.parent = None + self.__root = new_node + else: + self.__merge_brother(parent) + + +def main(): + import random + test = ['O', 'J', 'S', 'Y', 'C', 'M', 'B', 'R', 'N', 'F', 'L', 'Z', 'U', 'Q', 'A', 'G', 'V', 'E', 'D', 'W', 'I', + 'H', 'T', 'K', 'X', 'P'] + + random.shuffle(test) + btree = BTree(3, *test) + print(btree.delete('O')) + print(btree) + + +if __name__ == "__main__": + main() diff --git a/src/ssj/tree/README.md b/src/ssj/tree/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/ssj/tree/__init__.py b/src/ssj/tree/__init__.py new file mode 100644 index 0000000..fb57e2f --- /dev/null +++ b/src/ssj/tree/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' diff --git a/src/ssj/tree/avl_tree.py b/src/ssj/tree/avl_tree.py new file mode 100644 index 0000000..1f3a1f6 --- /dev/null +++ b/src/ssj/tree/avl_tree.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding:UTF-8 +__author__ = 'shenshijun' + +""" +定义: +AVL树是高度平衡的二叉搜索树,平衡的方式是每一个节点左右子树高度差顶多为1. +每一个节点中会存储这个节点的高度。节点高度是指从这个节点到叶节点的最大距离。 + +高度: +AVL树的高度大约是1.44log(N)。 +高度为n的AVL树的最小节点数:s(h)=s(h-1)+s(h-2)+1 +""" + + +class Node(object): + """""" + + def __init__(self, value, parent, left, right, height=0): + """Constructor for Node""" + self.value = value + self.height = height + self.parent = parent + self.left = left + self.right = right + + +class AVLTree(object): + """""" + + def __init__(self): + """Constructor for """ + self.__root = None + self.__size = 0 + + def insert(self, value): + pass diff --git a/tree/binarystree.py b/src/ssj/tree/binary_search_tree.py similarity index 99% rename from tree/binarystree.py rename to src/ssj/tree/binary_search_tree.py index ccede2f..22d8072 100644 --- a/tree/binarystree.py +++ b/src/ssj/tree/binary_search_tree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding:utf-8 -*- -from lib.queue import Queue -from lib.stack import Stack +from ssj.lib.queue import Queue +from ssj.lib.stack import Stack class BSTree(object): diff --git a/tree/binarytree.py b/src/ssj/tree/binary_tree.py similarity index 94% rename from tree/binarytree.py rename to src/ssj/tree/binary_tree.py index b2459cb..2549d13 100644 --- a/tree/binarytree.py +++ b/src/ssj/tree/binary_tree.py @@ -1,6 +1,5 @@ # /usr/bin/env python -#-*- coding:utf-8 -*- -import Queue +# -*- coding:utf-8 -*- class Stack(object): @@ -10,8 +9,8 @@ class Stack(object): def __init__(self, cap): super(Stack, self).__init__() - self.__cap = cap #栈大小 - self.__length = 0 #栈长度 + self.__cap = cap # 栈大小 + self.__length = 0 # 栈长度 if self.__cap < 0: raise ValueError("length of Stack can not be negtive") self.__values = [0 for x in xrange(0, self.__cap)] @@ -89,12 +88,12 @@ def breadth_walk(self, f): 使用堆实现广度遍历 """ result = [] - q = Queue.Queue(maxsize=-1) + q = queue.Queue(maxsize=-1) q.put(self.__root) while not q.empty(): cur_node = q.get() result.append(f(cur_node.key)) - #注意:这儿的顺序比较讲究,不能调换 + # 注意:这儿的顺序比较讲究,不能调换 if cur_node.left is not None: q.put(cur_node.left) @@ -115,7 +114,3 @@ def main(): if __name__ == '__main__': main() - - - - \ No newline at end of file diff --git a/src/ssj/tree/bplus_tree.py b/src/ssj/tree/bplus_tree.py new file mode 100644 index 0000000..427d393 --- /dev/null +++ b/src/ssj/tree/bplus_tree.py @@ -0,0 +1,6 @@ +# TODO实现B+树 +class BplusTree: + def __init__(self): + pass + + pass diff --git a/tree/interval_tree.py b/src/ssj/tree/interval_tree.py similarity index 99% rename from tree/interval_tree.py rename to src/ssj/tree/interval_tree.py index 550ede7..862be7c 100644 --- a/tree/interval_tree.py +++ b/src/ssj/tree/interval_tree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from lib.queue import Queue -from lib.stack import Stack +from ssj.lib.queue import Queue +from ssj.lib.stack import Stack __author__ = 'shenshijun' @@ -45,7 +45,7 @@ def restore_max(self): self.sub_max = max([self.left.sub_max, self.right.sub_max]) def not_empty(self): - return self.left is not None and self.right is not None + return self.left is not None and self.right is not None @property def key(self): @@ -57,7 +57,6 @@ class IntervalTree(object): 用红黑树实现区间树 """ - def __init__(self, *vargs): """ @@ -72,7 +71,6 @@ def __len__(self): return self.__size - def __left_rotate(self, node): """ @@ -103,7 +101,6 @@ def __left_rotate(self, node): node.restore_max() right_child.restore_max() - def __right_rotate(self, node): """ 二叉搜索树右旋操作 @@ -134,7 +131,6 @@ def __right_rotate(self, node): node.restore_max() left_child.restore_max() - def insert(self, key): cur_node = self.__root node = Node(key[0], key[1], key[1], self.Nil, self.Nil, self.Nil, True) @@ -159,7 +155,6 @@ def insert(self, key): node.parent = parent_node self.__insert_fixup(node) - def __insert_fixup(self, node): # 首先判断节点是不是根节点或者父节点是不是根节点 @@ -269,7 +264,6 @@ def __find(self, key): cur_node = cur_node.left return cur_node - def __successor(self, value): find_node = self.__find(value) if find_node is self.Nil: @@ -301,12 +295,10 @@ def __min(self, root): cur_node = cur_node.left return cur_node - def min(self): min_node = self.__min(self.__root) return min_node.value if min_node is not None else None - def __delete_fixup(self, node): cur_node = node while cur_node is not self.__root and cur_node.is_black(): @@ -357,7 +349,6 @@ def __delete_fixup(self, node): cur_node = self.__root cur_node.color = False - def midorder(self, f): """ 中序遍历 @@ -380,7 +371,6 @@ def midorder(self, f): cur_node = cur_node.right return result - def print_tree(self): """ 打印树的结构 @@ -419,4 +409,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/tree/lchild_rbro_tree.py b/src/ssj/tree/lchild_rbro_tree.py similarity index 97% rename from tree/lchild_rbro_tree.py rename to src/ssj/tree/lchild_rbro_tree.py index 38ef247..79dbcb4 100644 --- a/tree/lchild_rbro_tree.py +++ b/src/ssj/tree/lchild_rbro_tree.py @@ -1,6 +1,5 @@ #!/usr/bin/env -#!-*- coding:utf-8 -*- -import Queue +# !-*- coding:utf-8 -*- class Stack(object): @@ -86,13 +85,12 @@ def depth_walk(self, f): stack.push(cur_node.child) return result - def breadth_walk(self, f): """ 使用队列实现广度遍历的思路是类似的,在访问到一个父节点的时候把所有的子节点都依次放到队列中 """ result = [] - q = Queue.Queue(maxsize=-1) + q = queue.Queue(maxsize=-1) q.put(self.__root) while not q.empty(): cur_node = q.get() @@ -116,4 +114,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/tree/order_statistic_tree.py b/src/ssj/tree/order_statistic_tree.py similarity index 99% rename from tree/order_statistic_tree.py rename to src/ssj/tree/order_statistic_tree.py index 0de4b09..ff5ff92 100644 --- a/tree/order_statistic_tree.py +++ b/src/ssj/tree/order_statistic_tree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from lib.queue import Queue -from lib.stack import Stack +from ssj.lib.queue import Queue +from ssj.lib.stack import Stack __author__ = 'shenshijun' @@ -450,4 +450,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/tree/red_black_tree.py b/src/ssj/tree/red_black_tree.py similarity index 87% rename from tree/red_black_tree.py rename to src/ssj/tree/red_black_tree.py index 88f3143..a169eb0 100644 --- a/tree/red_black_tree.py +++ b/src/ssj/tree/red_black_tree.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding:UTF-8 -from lib.queue import Queue -from lib.stack import Stack +from ssj.lib.queue import Queue +from ssj.lib.stack import Stack __author__ = 'shenshijun' @@ -268,46 +268,47 @@ def __delete_fixup(self, node): parent = cur_node.parent if parent.left is cur_node: # 判断是左支还是右支,仅仅是实现所限 - uncle = parent.right - if uncle.is_red(): - # 情况一:叔节点是红色,则重新设色并左旋 - uncle.color = False + brother = parent.right + if brother.is_red(): + # 情况一:兄弟节点是红色,则重新设色并左旋 + brother.color = False parent.color = True self.__left_rotate(parent) - elif uncle.left.is_black() and uncle.right.is_black(): - # 情况二(1):叔节点和其两个子节点都是黑色.则设置叔节点为红色,这个时候如果parent是红色,那么循环就会退出 - uncle.color = True + cur_node = brother + elif brother.left.is_black() and brother.right.is_black(): + # 情况二(1):兄弟节点和其两个子节点都是黑色.则设置兄弟节点为红色,这个时候如果parent是红色,那么循环就会退出 + brother.color = True cur_node = parent - elif uncle.right.is_black(): - uncle.color = True - uncle.left.color = False - # 情况二(2):叔节点红和其右节点是黑色,那么意味着叔节点的左节点是红色,这个时候叔节点右旋并且父子节点交换颜色 - self.__right_rotate(uncle) + elif brother.right.is_black(): + brother.color = True + brother.left.color = False + # 情况二(2):兄弟节点红和其右节点是黑色,那么意味着兄弟节点的左节点是红色,这个时候兄弟节点右旋并且父子节点交换颜色 + self.__right_rotate(brother) else: - # 情况二(3):叔节点是黑色,其右节点红色(可以由前面的转换而来),这个时候叔节点设红,其父节点和右子节点设黑并且父节点左旋 + # 情况二(3):兄弟节点是黑色,其右节点红色(可以由前面的转换而来),这个时候兄弟节点设红,其父节点和右子节点设黑并且父节点左旋 parent.color = False - uncle.color = True - uncle.right.color = False + brother.color = True + brother.right.color = False self.__left_rotate(parent) # 退出情况 cur_node = self.__root else: - uncle = parent.left - if uncle.is_red(): - uncle.color = False + brother = parent.left + if brother.is_red(): + brother.color = False parent.color = True self.__right_rotate(parent) - elif uncle.left.is_black() and uncle.right.is_black(): - uncle.color = True + elif brother.left.is_black() and brother.right.is_black(): + brother.color = True cur_node = parent - elif uncle.left.is_black(): - uncle.color = True - uncle.right.color = False - self.__left_rotate(uncle) + elif brother.left.is_black(): + brother.color = True + brother.right.color = False + self.__left_rotate(brother) else: parent.color = False - uncle.color = True - uncle.left.color = False + brother.color = True + brother.left.color = False self.__right_rotate(parent) cur_node = self.__root cur_node.color = False diff --git a/tree/Tries.py b/src/ssj/tree/tries.py similarity index 93% rename from tree/Tries.py rename to src/ssj/tree/tries.py index 9caf5d0..6a267bf 100644 --- a/tree/Tries.py +++ b/src/ssj/tree/tries.py @@ -3,6 +3,7 @@ __author__ = 'shenshijun' +# TODO实现 class Tries(object): """ 字符串前缀树实现 @@ -11,4 +12,3 @@ class Tries(object): def __init__(self): """""" pass - diff --git a/tree/AVLTree.py b/tree/AVLTree.py deleted file mode 100644 index 8d24c9b..0000000 --- a/tree/AVLTree.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -__author__ = 'shenshijun' - - -class AVLTree(object): - """""" - - def __init__(self): - """Constructor for """ - pass diff --git a/tree/BTree.py b/tree/BTree.py deleted file mode 100644 index f860d3e..0000000 --- a/tree/BTree.py +++ /dev/null @@ -1,200 +0,0 @@ -#!/usr/bin/env python -# -*- coding:UTF-8 -from lib.stack import Stack - -__author__ = 'shenshijun' - - -class Node(object): - def __init__(self, is_leaf, keys, childs=None, parent=None): - """ - 在真实的实现中应该在加上一个数组表示指向真实数据的指针 - keys和childs都是一个数组,分别表示关键字和孩子 - """ - self.keys = list(sorted(keys)) - self.is_leaf = is_leaf - self.__size = len(self.keys) - if childs is None: - self.childs = [None for x in xrange(0, self.__size)] - self.childs.append(None) - else: - self.childs = childs - self.parent = parent - - def __str__(self): - return "".join(['Node(keys=', ",".join(map(lambda key: str(key), self.keys)), - ',leaf' if self.is_leaf else ',not leaf', - ',childs num=', str(len(self.childs)) ,')\n']) - - def __len__(self): - return self.__size - - def append(self, key): - """ - 向B树的节点中插入一个关键字,返回这个关键字的下标 - """ - result = self.__size - self.__size += 1 - for x in xrange(0, result): - if self.keys[x] > key: - self.keys.insert(x, key) - self.childs.insert(x, None) - return x - self.keys.append(key) - self.childs.append(None) - return result - - def search_child(self, instance): - """ - 查找小于instance的子树 - """ - for x in xrange(0, self.__size): - if self.keys[x] > instance: - return self.childs[x] - return self.childs[self.__size] - - -class BTree(object): - """ - B树实现,注意,不是二叉树 - """ - - def __init__(self, load_factor=4, *vargs): - """Constructor for BTree""" - self.__root = None - self.__load_factor = load_factor - self.__size = len(vargs) - map(self.insert, vargs) - - def insert(self, key): - """ - 节点插入的时候不需要再检测节点是不是满了,因为load_factor>=2,每次插入节点前调整都是使得节点关键字个数为load_factor-1。 - 而插入一个关键字之后节点关键字个数是2*load_factor-1或者load_factor - :param key: - :return: - """ - if self.__root is None: - self.__root = Node(True, [key]) - return - cur_node = self.__root - while not cur_node.is_leaf: - self.__split(cur_node) - cur_node = cur_node.search_child(key) - left_node, right_node = self.__split(cur_node) - if left_node is None or right_node is None: - # 返回None表示叶节点没有满 - cur_node.append(key) - else: - if left_node.keys[-1] < key: - # 说明left_node中的所有节点都比key小,所以把新节点插入到右边 - right_node.append(key) - else: - left_node.append(key) - - def __split(self, node): - if self.full(node): - parent_node = node.parent - middle_key = node.keys[self.__load_factor-1] - if parent_node is None: - # 处理根节点 - self.__root = Node(False, []) - parent_node = self.__root - parent_middle_index = parent_node.append(middle_key) - left_node = Node(node.is_leaf, node.keys[:self.__load_factor-1], node.childs[:self.__load_factor], parent_node) - #注意设定分裂节点的子节点的父指针 - for child in left_node.childs: - if child is not None: - child.parent = left_node - right_node = Node(node.is_leaf, node.keys[self.__load_factor:], node.childs[self.__load_factor:], parent_node) - for child in right_node.childs: - if child is not None: - child.parent = right_node - parent_node.childs[parent_middle_index] = left_node - parent_node.childs[parent_middle_index + 1] = right_node - self.__root.is_leaf = False - return left_node, right_node - return None, None - - def search(self, instance): - return self.__search(self.__root, instance) - - def full(self, node): - return len(node) >= (self.__load_factor * 2 - 1) - - @classmethod - def __search(cls, root, instance): - cur_node = root - while True: - cur_len = len(cur_node) - x = 0 - while x < cur_len and cur_node.keys[x] < instance: - x += 1 - if cur_node.keys[x] == instance: - return cur_node, x - elif cur_node.is_leaf: - return None, None - else: - cur_node = cur_node.childs[x] - - def min(self): - cur_node = self.__root - while not cur_node.is_leaf: - cur_node = cur_node.childs[0] - return cur_node.keys[0] - - def max(self): - cur_node = self.__root - while not cur_node.is_leaf: - cur_node = cur_node.childs[-1] - return cur_node.keys[-1] - - def midorder(self, f): - """ - B树中序遍历 - :param f: - :return: - """ - result = [] - stack = Stack() - cur_node = self.__root - if cur_node.is_leaf: - return map(f, cur_node.keys) - - while True: - if cur_node.is_leaf: - # 到叶节点了,开始把叶节点的所有关键字都遍历掉 - result.extend(map(f, cur_node.keys)) - #开始从栈中取元素,遍历下一个节点叶节点 - if stack.empty(): - return result - cur_node, i = stack.pop() - result.append(f(cur_node.keys[i])) - if i < len(cur_node)-1: - stack.push((cur_node, i + 1)) - cur_node = cur_node.childs[i + 1] - else: - stack.push((cur_node, 0)) - cur_node = cur_node.childs[0] - return result - - def __str__(self): - return "\n".join(self.midorder(lambda s: str(s))) - - def test(self): - print "-" * 20 - print self.__root - print self.__root.childs[0] - print self.__root.childs[1] - - -def main(): - btree = BTree(3, 'A', 'B', 'C', 'D', 'E', 'F', 'G','H','I','J','K','L','M','N','O','P','R','S','T','U','V','X','Y','Z') - print btree - print btree.max() - print btree.min() - - -if __name__ == "__main__": - main() - -