python拓展4 数据结构
内容:
1.数组
2.链表
3.字典
4.二叉树(搜索树)
5.set集合实现
1.数组
数组在python中是以列表的形式存在,基本上每一个语言中都有数组形式的数据结构存在
数组一般存储在连续的一块内存,数组存取元素时间是 O(1),插入、删除是 O(n),另外可以用数组实现栈和队列,栈:先进后出,队列:先进先出
另外python list中有两个部件:
- 数组 存储数据在链表中的地址
- 链表 实际存储数据
列表:
1 lt = [1, 2, 3, 4, 5, 5] 2 3 # 存取 4 print(lt[0]) 5 lt[1] = 666 6 print(lt) 7 8 # 插入元素 9 lt.insert(0, 333) 10 print(lt) 11 12 # 删除元素 13 # 按值删除: 14 lt.remove(5) 15 print(lt) 16 # 按索引删除: 17 lt.pop(0) 18 print(lt) 19 del lt[0] 20 print(lt)
用python中的list相关操作实现栈和列表如下:
1 # encoding: utf-8 2 # __author__ = "wyb" 3 # date: 2018/9/28 4 5 6 class Stack(object): 7 def __init__(self): 8 self.lt = [] 9 10 def empty(self): 11 """ 12 判断栈是否为空 13 :return: 14 """ 15 return len(self.lt) == 0 16 17 def top(self): 18 """ 19 查看栈顶的对象,但不移除 20 :return: 21 """ 22 if not self.empty(): 23 return self.lt[-1] 24 return None 25 26 def push(self, obj): 27 """ 28 把对象压入栈顶 29 :return: 30 """ 31 self.lt.append(obj) 32 33 def pop(self): 34 """ 35 移除栈顶对象,并返回该对象的值 36 :return: 37 """ 38 if not self.empty(): 39 return self.lt.pop() 40 return None 41 42 def search(self, obj): 43 """ 44 返回对象在栈中的位置,以1为基数 45 :param obj: 46 :return: 47 """ 48 if not self.empty(): 49 return self.lt.index(obj) + 1 50 return -1 51 52 53 class Queue(object): 54 def __init__(self): 55 self.lt = [] 56 57 def empty(self): 58 """ 59 判断队列是否为空 60 :return: 61 """ 62 return len(self.lt) == 0 63 64 def first(self): 65 """ 66 查看队首的对象,但不移除 67 :return: 68 """ 69 if not self.empty(): 70 return self.lt[0] 71 return None 72 73 def enqueue(self, obj): 74 """ 75 将指定元素加入队列的尾部 76 :param obj: 77 :return: 78 """ 79 self.lt.append(obj) 80 81 def dequeue(self): 82 """ 83 移除队首对象,并返回该对象的值 84 :return: 85 """ 86 if not self.empty(): 87 return self.lt.pop(0) 88 return None 89 90 def search(self, obj): 91 """ 92 返回对象在队列中的位置,以1为基数 93 :param obj: 94 :return: 95 """ 96 if not self.empty(): 97 return self.lt.index(obj) + 1 98 return -1
用python list实现python中的set:
1 # encoding: utf-8 2 # __author__ = "wyb" 3 # date: 2018/9/29 4 5 6 class Set(object): 7 def __init__(self, *args): 8 self.table_size = 10007 9 self.data = [0] * self.table_size 10 for i in args: 11 self.add(i) 12 13 def __repr__(self): 14 """ 15 调用str及输出的魔法方法 16 :return: 17 """ 18 lt = set() 19 for i in range(0, len(self.data)): 20 if self.data[i] != 0: 21 item = self.data[i] 22 lt.add(item[0]) 23 return str(lt) 24 25 def __eq__(self, other): 26 """ 27 判断相等的魔法方法 28 :param other: 29 :return: 30 """ 31 if type(other) == type(self): 32 return str(self.data) == str(other.data) 33 else: 34 return False 35 36 def remove(self, x): 37 index = self._index(x) 38 self.data[index] = 0 39 40 def _index(self, obj): 41 index = hash(obj) % self.table_size 42 return index 43 44 def _insert_at_index(self, index, key): 45 v = self.data[index] 46 if v == 0: 47 self.data[index] = [key] 48 else: 49 return False 50 51 def add(self, key): 52 # 先计算出下标 53 index = self._index(key) 54 # 在下标处插入元素 55 self._insert_at_index(index, key) 56 57 # for i in range(0, len(self.data)): 58 # if self.data[i] == x: 59 # return False 60 # self.data.append(x) 61 62 def has(self, key): 63 index = self._index(key) 64 # 取元素 65 v = self.data[index] 66 if isinstance(v, list): 67 if v[0] == key: 68 return True 69 return False 70 71 # for i in range(0, len(self.data)): 72 # if self.data[i] == x: 73 # return True 74 # return False 75 76 77 def testSet(): 78 a = Set(1, 2, 2, 3, 4, 4) 79 b = Set(1, 2, 2, 3, 4) 80 c = Set(1, 3, 4, 2) 81 d = Set(2, 3) 82 assert (str(a) == '{1, 2, 3, 4}') 83 print(a, b, c, d) 84 assert (a == b) 85 assert (a == c) 86 assert (a != d) 87 assert (a.has(1) is True) 88 a.remove(1) 89 assert (a.has(1) is False) 90 a.add(1) 91 assert (a.has(1) is True) 92 93 94 if __name__ == '__main__': 95 testSet()
2.链表
我们可以将链表比作手拉手的盒子,一个盒子只能访问左右手的盒子
以下标方式读取元素的时间是 O(n),插入、删除是 O(1),栈和队列可以用链表实现,栈:先进后出,队列:先进先出
链表简单实现:
1 # encoding: utf-8 2 # __author__ = "wyb" 3 # date: 2018/9/27 4 5 6 class Node(): 7 def __init__(self, element=None): 8 self.e = element 9 self.next = None 10 11 12 def append(node, element): 13 """ 14 append: 添加一个元素到末尾 15 :param node: 是一个 Node 实例 16 :param element: 任意类型的元素 17 """ 18 n = node 19 while n.next is not None: 20 n = n.next 21 # n 现在是最后一个元素 22 new_node = Node(element) 23 n.next = new_node 24 25 26 def prepend(head_node, element): 27 """ 28 prepend: 添加一个元素到开头 29 :param head_node: 头元素 30 :param element: 任意类型的元素 31 :return: 32 """ 33 n = Node(element) 34 n.next = head_node.next 35 head_node.next = n 36 37 38 def pop(head_node): 39 """ 40 pop是stack的两个操作之一 41 push 入栈 42 pop 出栈 43 prepend + pop 就实现了 队列 的 入队(enqueue)和出队(dequeue)操作 44 append + pop 就实现了 栈 的 入栈(push) 和 出栈(pop)操作 45 :param head_node: 头部节点 46 :return: 47 """ 48 tail = head_node 49 while tail.next is not None: 50 tail = tail.next 51 # 现在 tail 是最后一个元素了 52 n = head_node 53 while n.next is not tail: 54 n = n.next 55 # 现在 n 是 tail 之前的元素了 56 n.next = None 57 return tail.e 58 59 60 def log_list(node): 61 n = node 62 s = '' 63 while n is not None: 64 s += (str(n.e) + ' > ') 65 n = n.next 66 print(s[0: -2]) 67 68 69 head = Node() 70 n1 = Node(111) 71 n2 = Node(222) 72 n3 = Node(333) 73 n1.next = n2 74 n2.next = n3 75 76 head.next = n1 77 78 log_list(n1) 79 append(n1, 'gua') 80 log_list(n1) 81 prepend(head, 'hello') 82 log_list(head) 83 print('pop head: ', pop(head)) 84 log_list(head)
链表封装成类:
1 # encoding: utf-8 2 # __author__ = "wyb" 3 # date: 2018/9/27 4 5 6 # 节点类 7 class Node(object): 8 def __init__(self, element=-1): 9 self.element = element 10 self.next = None 11 12 13 # 链表类 14 class LinkedList(object): 15 def __init__(self): 16 self.head = None 17 18 def is_empty(self): 19 """ 20 判断链表是否为空 21 :return: 22 """ 23 return self.head is None 24 25 def length(self): 26 """ 27 获得链表长度(包含head) 28 :return: 29 """ 30 index = 0 31 node = self.head 32 while node is not None: 33 index += 1 34 node = node.next 35 return index 36 37 def find(self, element): 38 """ 39 查找元素 40 :param element: 元素值 41 :return: 42 """ 43 node = self.head 44 while node is not None: 45 if node.element == element: 46 return node 47 node = node.next 48 return None 49 50 def _node_at_index(self, index): 51 """ 52 返回某个节点 53 :param index: 索引 -> 从0开始 0是head 54 :return: 55 """ 56 i = 0 57 node = self.head 58 while node is not None: 59 if i == index: 60 return node 61 node = node.next 62 i += 1 63 return None 64 65 def element_at_index(self, index): 66 """ 67 返回某个节点的值 68 :param index: 索引 -> 从0开始 0是head 69 :return: 70 """ 71 node = self._node_at_index(index) 72 return node.element 73 74 def first_object(self): 75 """ 76 返回第一个节点 -> head 77 :return: 78 """ 79 return self._node_at_index(0) 80 81 def last_object(self): 82 """ 83 返回最后一个节点 84 :return: 85 """ 86 i = 0 87 while self._node_at_index(i) is not None: 88 i += 1 89 return self._node_at_index(i - 1) 90 91 def insert_before_index(self, position, element): 92 """ 93 在节点之前插入元素 94 :param position: 节点位置 95 :param element: 元素值 96 :return: 97 """ 98 insert_node = Node(element) 99 # 错误情况判断: 100 if position == 0: 101 print("不能在head之前插入元素") 102 return False 103 if self._node_at_index(position) is None: 104 print("节点顺序超了!请输入正确的节点顺序!") 105 return False 106 node = self._node_at_index(position - 1) 107 # 插入元素 108 insert_node.next = node.next 109 node.next = insert_node 110 111 def insert_after_index(self, position, element): 112 """ 113 在节点之后插入元素 114 :param position: 节点位置 115 :param element: 元素值 116 :return: 117 """ 118 insert_node = Node(element) 119 node = self._node_at_index(position) 120 # 错误情况判断: 121 if node is None: 122 print("节点顺序超了!请输入正确的节点顺序!") 123 return False 124 # 在节点之后插入元素 125 insert_node.next = node.next 126 node.next = insert_node 127 128 def append(self, element): 129 """ 130 在最后插入节点 131 :param element: 节点值 132 :return: 133 """ 134 node = Node(element) 135 if self.head is None: 136 self.head.next = node 137 else: 138 last_node = self.last_object() 139 last_node.next = node 140 node.front = last_node 141 142 def prepend(self, element): 143 """ 144 在开头插入节点 145 :param element: 节点值 146 :return: 147 """ 148 node = Node(element) 149 node.next = self.head.next 150 self.head.next = node 151 152 def pop(self): 153 """ 154 删除最后一个节点 155 :return: 156 """ 157 tail = self.first_object() 158 while tail.next is not None: 159 tail = tail.next 160 # 现在 tail 是最后一个元素了 161 n = self.first_object() 162 while n.next is not tail: 163 n = n.next 164 # 现在 n 是 tail 之前的元素了 165 n.next = None 166 return tail.element 167 168 def log_list(self, msg=""): 169 """ 170 输出链表 171 :param msg: 输出链表之前显示的信息 172 :return: 173 """ 174 n = self.head.next 175 s = msg + '' 176 while n is not None: 177 s += (str(n.element) + ' > ') 178 n = n.next 179 print(s[0: -2]) 180 181 182 # 测试链表初始化及输出链表: 183 def test_log(): 184 head = Node(0) 185 n1 = Node(1) 186 n2 = Node(2) 187 n3 = Node(3) 188 lt = LinkedList() 189 lt.head = head 190 head.next = n1 191 n1.next = n2 192 n2.next = n3 193 lt.log_list("输出链表: ") 194 return lt 195 196 197 # 测试链表判空及链表长度: 198 def test_empty_length(lt): 199 if lt.is_empty() is True: 200 print("链表为空") 201 return None 202 else: 203 length = lt.length() 204 print("链表不为空, 链表长度为: ", length) 205 return length 206 207 208 # 测试find 209 def test_find(lt): 210 if lt.find(5) is None: 211 print("链表中不存在5") 212 else: 213 print("链表中存在5") 214 node = lt.find(5) 215 return node 216 217 if lt.find(3) is None: 218 print("链表中不存在3") 219 else: 220 print("链表中存在3") 221 node = lt.find(3) 222 return node 223 224 225 # 测试element_at_index 226 def test_element_at_index(lt): 227 print(lt.element_at_index(0)) 228 print(lt.element_at_index(1)) 229 print(lt.element_at_index(2)) 230 print(lt.element_at_index(3)) 231 232 233 # 测试first_obj和last_obj 234 def test_first_last(lt): 235 print(lt.first_object().element) 236 print(lt.last_object().element) 237 238 239 # 测试插入 240 def test_insert(lt): 241 lt.insert_before_index(0, "在节点0之前插入") 242 lt.log_list() 243 lt.insert_before_index(1, "在节点1之前插入") 244 lt.log_list() 245 lt.insert_after_index(0, "在节点0之后插入") 246 lt.log_list() 247 lt.insert_after_index(2, "在节点2之后插入") 248 lt.log_list() 249 lt.append("在最后插入节点") 250 lt.log_list() 251 lt.prepend("在开头插入节点") 252 lt.log_list() 253 254 255 # 测试pop 256 def test_pop(lt): 257 lt.pop() 258 lt.log_list("删除最后一个元素: ") 259 260 261 # 单元测试 262 def test(): 263 linked_list = test_log() 264 265 # 测试空链表: 266 # test_empty_length(LinkedList()) 267 268 # 测试非空链表: 269 # test_empty_length(linked_list) 270 271 # 测试find 272 # test_find(linked_list) 273 274 # 测试element_at_index 275 # test_element_at_index(linked_list) 276 277 # 测试first_obj和last_obj 278 # test_first_last(linked_list) 279 280 # 测试insert 281 # test_insert(linked_list) 282 283 # 测试pop 284 # test_pop(linked_list) 285 286 287 if __name__ == '__main__': 288 test()
另外,关于栈和队列的实现:
上述链表实现中prepend + pop 就实现了 队列 的 入队(enqueue)和出队(dequeue)操作,append + pop 就实现了 栈 的 入栈(push) 和 出栈(pop)操作
1 # encoding: utf-8 2 # __author__ = "wyb" 3 # date: 2018/9/28 4 5 """ 6 数据结构的核心是,一个结构只有特定的操作,可以实现特定的功能 7 8 栈的特点是「先进后出」,一般有这几个操作 9 # push 将一个元素存入栈中 10 # pop 将一个元素从栈中取出,并在栈中删除它 11 12 # top 将一个元素从栈中取出 13 # is_empty 查看栈是否是空的 14 15 """ 16 17 18 # Node类是一个节点,有两个属性,一个存储元素,一个存储指向另一个节点的引用 19 class Node: 20 def __init__(self, element=None, next=None): 21 self.element = element 22 self.next = next 23 24 # 这个函数是会在print的时候被自动调用,就是把这个Node显示出来 25 def __repr__(self): 26 return str(self.element) 27 28 29 class Stack: 30 # 初始化函数,自动被调用 31 # 初始化Stack()类的时候,它有一个head属性,值是一个空的Node 32 def __init__(self): 33 self.head = Node() 34 35 # 如果head的next属性为空,则说明栈是空的 36 def is_empty(self): 37 return self.head.next is None 38 39 # 创建一个node,并让它指向当前head.next指向的元素,再把head.next指向它 40 def push(self, element): 41 self.head.next = Node(element, self.head.next) 42 43 # 取出head.next指向的元素,如果栈不是空的,就让head.next指向node.next,这样node就不在栈中了 44 def pop(self): 45 node = self.head.next 46 if not self.is_empty(): 47 self.head.next = node.next 48 return node 49 50 # head.next就是栈里面第一个元素 51 def top(self): 52 return self.head.next 53 54 55 # 测试函数 56 def test(): 57 s = Stack() 58 59 s.push(1) 60 s.push(2) 61 s.push(3) 62 s.push(4) 63 64 print(s.pop()) 65 print(s.pop()) 66 print(s.pop()) 67 print(s.pop()) 68 69 70 if __name__ == '__main__': 71 # 运行测试函数 72 test()
1 # encoding: utf-8 2 # __author__ = "wyb" 3 # date: 2018/9/28 4 5 6 """ 7 队列的特点是「先进先出」,一般有这几个操作 8 9 # enqueue 将一个元素存入队列中 10 # dequeue 将一个元素从队列中取出,并在队列中删除它 11 12 # empty 查看栈是否是空的 13 14 可以把队列看做排队,银行叫号机就是队列,先取号的先入队,叫号的时候也就先出队 15 """ 16 17 18 # Node类是一个节点,有两个属性,一个存储元素,一个存储指向另一个节点的引用 19 class Node: 20 def __init__(self, element=None, next=None): 21 self.element = element 22 self.next = next 23 24 # 这个函数是会在print的时候被自动调用,就是把这个Node显示出来 25 def __repr__(self): 26 return str(self.element) 27 28 29 class Queue: 30 # 初始化函数,自动被调用 31 # 初始化Queue()类的时候,它有2个属性,分别指向头尾 32 def __init__(self): 33 self.head = Node() 34 self.tail = self.head 35 36 # 如果head的next属性为空,则说明队列是空的 37 def empty(self): 38 return self.head.next is None 39 40 # 创建一个node 41 # 让tail.next指向它 42 # 让tail指向它,tail现在就是新的队尾了 43 def enqueue(self, element): 44 n = Node(element) 45 self.tail.next = n 46 self.tail = n 47 48 # 取出head.next指向的元素,如果队列不是空的,就让head.next指向node.next,这样node就不在队列中了 49 def dequeue(self): 50 node = self.head.next 51 if not self.empty(): 52 self.head.next = node.next 53 return node 54 55 56 # 测试函数 57 def test(): 58 q = Queue() 59 60 q.enqueue(1) 61 q.enqueue(2) 62 q.enqueue(3) 63 q.enqueue(4) 64 65 print(q.dequeue()) 66 print(q.dequeue()) 67 print(q.dequeue()) 68 print(q.dequeue()) 69 70 71 if __name__ == '__main__': 72 # 运行测试函数 73 test()
3.字典(哈希表、对象、Map)
python中的字典把字符串转为数字作为下标存储到数组中,字符串转化为数字的算法是 O(1),所以字典的存取操作都是 O(1)
除非对数据有顺序要求,否则字典永远是最佳选择
字符串转化为数字的算法:
- 确定数据规模,这样可以确定容器数组的大小 Size
- 把字符当作 N 进制数字得到结果
- eg:'gua' 被视为 g * 1 + u * 10 + a * 100 得到结果 n,n % Size 作为字符串在数组中的下标(通常 Size 会选一个 素数)
- 当下标冲突时,有标准的解决碰撞方法(链接法)
实现字典(哈希表):
1 class HashTable(object): 2 def __init__(self): 3 # table 是用来存储数据的数组 4 # 先让它有 10007 个格子好了 5 # 上课的时候说过, 这个尺寸最好选素数 6 # 这样可以得到更为合理的下标分布 7 self.table_size = 10007 8 self.table = [0] * self.table_size 9 10 # 这个魔法方法是用来实现 in not in 语法的 11 def __contains__(self, item): 12 return self.has_key(item) 13 14 def has_key(self, key): 15 """ 16 检查一个 key 是否存在, 时间很短, 是 O(1) 17 如果用 list 来存储, 需要遍历, 时间是 O(n) 18 """ 19 index = self._index(key) 20 # 取元素 21 v = self.table[index] 22 if isinstance(v, list): 23 # 检查是否包含我们要找的 key 24 for kv in v: 25 if kv[0] == key: 26 return True 27 # 如果得到的是 int 0 说明没找到, 返回 False 28 # 如果得到的是 list 但是遍历结果没有我们要找的 key 也是没找到 29 return False 30 31 def _insert_at_index(self, index, key, value): 32 # 检查下标处是否是第一次插入数据 33 v = self.table[index] 34 data = [key, value] 35 # 也可以用这个判断 if v == 0: 36 if isinstance(v, int): 37 # 如果是第一次, 得到的是 int 0 38 # 那么就插入一个 list 来存, 以后相同 key 的元素都放这里面 39 # 注意我们把 key value 作为一个数组保存进去了, 这是因为 40 # 会出现相同 hash 值的 key 41 # 这时候就需要比较原始信息来找到相应的数据 42 self.table[index] = [data] 43 else: 44 # 如果不是, 得到的会是 list, 直接 append 45 self.table[index].append(data) 46 47 def add(self, key, value): 48 """ 49 add 函数往 hashtable 中加入一对元素 50 我们先只支持字符串当 key 51 """ 52 # 先计算出下标 53 index = self._index(key) 54 # 在下标处插入元素 55 self._insert_at_index(index, key, value) 56 57 def get(self, key, default_value=None): 58 """ 59 这个和 dict 的 get 函数一样 60 """ 61 index = self._index(key) 62 # 取元素 63 v = self.table[index] 64 if isinstance(v, list): 65 # 检查是否包含我们要找的 key 66 for kv in v: 67 if kv[0] == key: 68 return kv[1] 69 # 如果得到的是 int 0 说明没找到, 返回 default_value 70 # 如果得到的是 list 但是遍历结果没有我们要找的 key 也是没找到 71 return default_value 72 73 def _index(self, key): 74 # 先计算出下标 75 return self._hash(key) % self.table_size 76 77 def _hash(self, s): 78 """ 79 下划线开始的函数被我们视为私有函数 80 但实际上还是可以在外部调用, 这只是一个给自己看的标记 81 """ 82 n = 1 83 f = 1 84 for i in s: 85 n += ord(i) * f 86 f *= 10 87 return n 88 89 90 def test(): 91 import uuid 92 names = [ 93 'gua', 94 'xiao', 95 'name', 96 'web', 97 'python', 98 ] 99 ht = HashTable() 100 for key in names: 101 value = uuid.uuid4() 102 ht.add(key, value) 103 print('add 元素', key, value) 104 for key in names: 105 v = ht.get(key) 106 print('get 元素', key, v) 107 print('魔法方法', 'gua' in ht) 108 109 110 if __name__ == '__main__': 111 test()
4.二叉树(搜索树)
二叉树(又叫搜索树):
1 # encoding: utf-8 2 # __author__ = "wyb" 3 # date: 2018/9/28 4 5 6 class Tree(object): 7 def __init__(self, element=None): 8 self.element = element 9 self.left = None 10 self.right = None 11 12 def traversal(self): 13 """ 14 树的遍历, 是一个递归操作 15 """ 16 print(self.element) # 前序遍历 17 if self.left is not None: 18 self.left.traversal() 19 # print(self.element) # 中序遍历 20 if self.right is not None: 21 self.right.traversal() 22 # print(self.element) # 后序遍历 23 24 def reverse(self): 25 """ 26 翻转二叉树 27 :return: 28 """ 29 self.left, self.right = self.right, self.left 30 if self.left is not None: 31 self.left.reverse() 32 if self.right is not None: 33 self.right.reverse() 34 35 36 def test(): 37 # 手动构建二叉树 38 t = Tree(0) 39 left = Tree(1) 40 right = Tree(2) 41 t.left = left 42 t.right = right 43 # 遍历 44 t.traversal() 45 46 47 if __name__ == '__main__': 48 test()
5.set集合实现
(1)题目要求
1 # 作业一: 2 # 写一个 set 的类, 无序且元素不重复,内部使用数组来存储元素,具有以下成员函数 3 # 1. remove ,删除元素 4 # 2. add, 增加元素 5 # 3. has,判断元素是否存在 6 # 形式如下: 7 # class Set(object): 8 # def __init__(self, *args) 9 # self.data = [] 10 # # ... 11 # def remove(self, x): 12 # pass 13 # def add(self, x): 14 # pass 15 # def has(self, x): 16 # pass 17 # 18 # 19 # 作业二: 20 # 在作业一的基础上,在Set类里增加 __repr__ 和 __eq__ 两个成员函数。 21 # 并通过附带 testSet() 函数的测试。 22 # 形式如下: 23 # class Set(object): 24 # # ... 25 # def __init__(self, *args) 26 # self.data = [] 27 # 28 # def __repr__(self): 29 # pass 30 # 31 # def __eq__(self, other): 32 # pass 33 # 34 # def remove(self, x): 35 # pass 36 # def add(self, x): 37 # pass 38 # def has(self, x): 39 # pass 40 # 41 # def testSet(): 42 # a = Set(1, 2, 2, 3, 4, 4) 43 # b = Set(1, 2, 2, 3, 4) 44 # c = Set(1, 3, 4, 2) 45 # d = Set(2, 3) 46 # assert (str(a) == '{1, 2, 3, 4}') 47 # print(a, b, c, d) 48 # assert (a == b) 49 # assert (a == c) 50 # assert (a != d) 51 # assert (a.has(1) == True) 52 # a.remove(1) 53 # assert (a.has(1) == False) 54 # a.add(1) 55 # assert (a.has(1) == True) 56 # 57 # 58 # 作业三: 59 # 参考第17课板书 hash_table 的代码,写一个类 Set,实现时间复杂度为O(1) 的 add,remove 函数 。 60 # 形式如下: 61 # class Set(object): 62 # # ... 63 # def add(self, x): 64 # pass 65 # 66 # def remove(self, x): 67 # pass
(2)实现
too young too simple sometimes native!