Python编程之数据结构与算法练习_010

Posted orcsir

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python编程之数据结构与算法练习_010相关的知识,希望对你有一定的参考价值。

练习内容:

判断一个二叉树T1是否是另一颗二叉树T2的子树。(T2>T1)

要求:时间复杂度O(N),空间复杂度O(1)

正文内容提要:

1.morris遍历实现T1,T2的先序序列化。

2.kmp算法判断T1与T2的序列化结果(T2>T1)

  (1)如果seralize(T1)是seralize(T2)的子串,则T1是T2的子树

  (2)否则,T1不是T2的子树

1.创建类描述树结构

 1 class MyProperty:
 2     def __init__(self, get_attrib_func):
 3         self.get_attrib_func = get_attrib_func
 4         self.set_attrib_func = None
 5 
 6     def __set__(self, instance, value):
 7         if not self.set_attrib_func:
 8             raise AttributeError("can‘t set attribute")
 9         self.set_attrib_func(instance, value)
10 
11     def __get__(self, instance, owner):
12         return self.get_attrib_func(instance)
13 
14     def setter(self, set_attrib_func):
15         self.set_attrib_func = set_attrib_func
16         return self
17 
18 
19 class Node:
20     def __init__(self, value):
21         self.value = value
22         self.__left = None
23         self.__right = None
24 
25     @MyProperty
26     def left(self):
27         return self.__left
28 
29     @left.setter
30     def left(self, node):
31         self.__left = node
32 
33     @MyProperty
34     def right(self):
35         return self.__right
36 
37     @right.setter
38     def right(self, node):
39         self.__right = node

2.使用morris遍历,实现二叉树的先序序列化

 1 def morris_pre_serialize(head):
 2     if not head:
 3         return
 4     string = []
 5     cur = head
 6     most_left = None
 7     while cur != None:
 8         most_left = cur.left
 9         if most_left != None:
10             while most_left.right != None and most_left.right != cur:
11                 most_left = most_left.right
12 
13             if most_left.right == None:  # 第一次到达cur节点
14                 string.append("{}{}".format(cur.value, "_"))
15                 most_left.right = cur
16                 cur = cur.left
17                 continue
18             else:
19                 most_left.right = None  # 第二次到达cur节点
20                 string.append("#_")
21 
22         else:
23             string.append(str(cur.value) + "_")
24             string.append("#_")
25         cur = cur.right
26     else:
27         string.append("#_")
28 
29     return "".join(string)

3.实现kmp算法

 1 def kmp(str_x, str_y):
 2 
 3     def __get_nexts(str_x):
 4         if str_x is None:
 5             return None
 6 
 7         length = len(str_x)
 8         if length == 1:
 9             return [-1]
10 
11         nexts = [0] * length
12         nexts[0] = -1
13         nexts[1] = 0
14         i1, i2 = 2, 1
15         while i1 < length:
16             if str_x[i1 - 1] == str_x[nexts[i2]]:
17                 nexts[i1] = nexts[i2] + 1
18                 i2, i1 = i1, i1 + 1
19             elif nexts[i2] != -1:
20                 i2 = nexts[i2]
21             else:
22                 nexts[i1] = 0
23                 i2, i1 = i1, i1 + 1
24         return nexts
25 
26 
27     if str_x is None or str_y is None or len(str_y) < 1 or len(str_x) < len(str_y):
28         return -1
29 
30     len_str_x, len_str_y = len(str_x), len(str_y)
31 
32     i1, i2 = 0, 0
33 
34     nexts = __get_nexts(str_y)
35 
36     while i1 < len_str_x and i2 < len_str_y:
37         if str_x[i1] == str_y[i2]:
38             i1, i2 = i1 + 1, i2 + 1
39         elif nexts[i2] != -1:
40             i2 = nexts[i2]
41         else:
42             i1 += 1
43     return i1 - i2 if i2 == len_str_y else -1

4.结合morris遍历,kmp子串判断,实现子树的判断。时间复杂O(N), 空间复杂度O(1)

 1 def is_sub_tree(head1, head2):
 2     if head1 is None or head2 is None:
 3         return False
 4 
 5     str1 = morris_pre_serialize(head1)
 6     str2 = morris_pre_serialize(head2)
 7 
 8     str1, str2 = (str2, str1) if len(str1) < len(str2) else (str1, str2)
 9 
10     ret = kmp(str1, str2)
11 
12     return True if ret != -1 else False

 5.简单测试代码

 1 if __name__ == "__main__":
 2     tree_1 = Node(1)
 3     tree_1.left = Node(2)
 4     tree_1.right = Node(3)
 5     tree_1.left.left = Node(4)
 6     tree_1.left.right = Node(5)
 7     tree_1.right.left = Node(6)
 8     tree_1.right.right = Node(7)
 9 
10     tree_2 = Node(3)
11     tree_2.left = Node(6)
12     tree_2.right = Node(7)
13     tree_2.left.right = Node(8)
14     # tree_2 is not tree_1‘s sub tree
15     print(is_sub_tree(tree_2, tree_1))  # False
16     print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
17     tree_3 = Node(3)
18     tree_3.left = Node(6)
19     tree_3.right = Node(7)
20     # tree_3 is tree_1‘s sub tree
21     print(is_sub_tree(tree_1, tree_3))  # True

 

以上是关于Python编程之数据结构与算法练习_010的主要内容,如果未能解决你的问题,请参考以下文章

Python编程之数据结构与算法练习_009

Python编程之算法练习_001

Python编程之算法练习_002

Python编程之算法练习_003

Python编程之基础知识练习_002

Python编程之基础知识练习_007