Array sequence:
set_at and get_at only need time,but delete and insert needs lineartime.We need to move the items and resize the array.
class Array_Seq:
def __init__(self):
self.A = []
self.size = 0
def __len__(self):
return self.size()
def __iter__(self):
yield from self.A
def build(self, X):
self.A = [a for a in X]
self.size = len(self.A)
def get_at(self, i):
return self.A[i]
def set_at(self, i, x):
self.A[i] = x
def _copy_forward(self, i, n, A, j):
for k in range(n):
A[j + k] = self.A[i + k]
def _copy_backward(self, i, n, A, j):
for k in range(n - 1, -1, -1):
A[j + k] = self.A[i + k]
def insert_at(self, i, x):
n = len(self)
A = [None] * (n + 1)
self._copy_forward(0, i, A, 0)
A[i] = x
self._copy_forward(i, n - i, A, i + 1)
self.build(A)
def delete_at(self, i):
n = len(self)
A = [None] * (n - 1)
self._copy_forward(0, i, A, 0)
x = self.A[i]
self._copy_forward(i + 1, n - i - 1, i)
self.build(A)
return x
The key operation is the defination: copy_forward.We need to resize the array
Linked List
A linked note stores an item in a node,instead of allocating a contiguous chunk of memory
node.item stores the item,and the node.next stores the memory address of next node
class Linked_list_node:W
def _init_(self, x):
self.item = x
self.next = None
def later_node(self, i):
if i == 0: return self
assert self.next
return self.next.later_node(i - 1)
Link list are more flexible sometimes ,because the constituent items can be stored anywhere.
Adventures:
easy to add or delete some items,and add a new item at the front takes O(1)time
disadventures:
hard to find some items,if the item is at the end,it will take O(n) time.
class Linked_List_Seq:
def __init__(self):
self.head = None
self.size = 0
def __len__(self):
return self.size
def __iter__(self):
node = self.head
while node:
yield node.item
node = node.next
def build(self, X):
for a in reversed(X):
self.insert_first(a)
def later_node(self, i):
if i == 0: return self
assert self.next
return self.later_node(i - 1)
def get_at(self, i):
node = self.head.later_node(i)
return node.item
def set_at(self, i, x):
node = self.head.later_node(i)
node.item = x
def insert_first(self, x):
new_node = Linked_List_Seq(x)
new_node.next = self.head
self.head = new_node
self.size += 1
def delete_first(self):
x = self.head.item
self.head = self.head.next
self.size -= 1
return x
def insert_at(self, i, x):
if i == 0:
self.insert_first(x)
return
new_node = Linked_List_Seq(x)
node = self.head.later_node(i - 1)
new_node.next = node.next
node.next = new_node
self.size += 1
def delete_at(self, i):
if i == 0:
return self.delete_first()
node = self.head.later_node(i - 1)
x = node.next.item
node.next = node.next.next
self.size -= 1
return x
The key operation is the def insert_at and delete_at
Dynamic Array:
class Dynamic_Array_Seq(Array_Seq):
def __init__(self,r):
super().__init__()
self.size=0
self.r=r
self.coupute_bounds()
self.resize(0)
def __len__(self):
return self.size
def __iter__(self):
for i in range(len(self)):
yield self.A[i]
def build(self,X):
for a in X:
self.insert_last(a)
def compute_bounds(self):
self.upper=len(self.A)
self.lower=len(self.A)//(self.r*self.r)
# 当元素达到数组的上界时,需要拓展数组容量
# 低于下界时,进行缩容以节省空间
# self.lower=len(self.A)//(self.r*self.r)为什么除以r^2是为了令下界尽可能的小
def _resize(self,n):
if (self.lower<n<self.upper): return
m=max(n,1)*self.r
A=[None]*m
self._copy_forward(0,self.size,A,0)
self.A=A
self.compute_bounds()
def insert_last(self,x):
self._resize(self.size+1)
self.A[self.size]=x
self.size+=1
def delete_last(self,x):
self.A[size-1]=None
self.size-=1
self._resize(self.size)
def insert_at(self,i,x):
self.insert_last(None)
self._copy_backward(i,self.size-(i+1),A,i+1)
# forward 还是backward
self.A[i]=x
# 先将数组多预留出来一个位置即insert_last(None)
# 从编号为i的元素开始向后移动self.size()-(i+1)个元素
def delete_at(self,i):
x=self.A[i]
self._copy_forward(i+1,self.size()-(i+1),self.A,i)
self.deleet_last
return x
Exercises:
Given a data structure implementing the Sequence interface, show how to use it to implement the Set interface. (Your implementation does not need to be efficient.)
Solution:
思路:将Sequence中的元素逐一添加到Set中,但是当插入时,我们要进行检查,检查该元素是否在Set中已经存在过。
Sequence相对于Set独有的性质是其具有 有序性,所以我们利用这个性质即可实现
def Set_from_Sequence(seq):
class set_from_sequence:
def __init__(self):
self.S = seq()
def __len__(self):
return len(self.S)
def __iter__(self):
yield from self.S
def build(self, A):
self.S.build(A)
def insert(self, x):
for i in range(len(self.S)):
if self.S.get_at(i).key == x.key:
self.S.set_at(i, x) # 如果Set中存在这个元素的key,那么进行替换
return
self.S.insert_last(x) # 如果不存在这个key,那么直接在最后进行插入即可
def delete(self, k):
for i in range(len(self.S)):
if self.S.get_at(i) == k:
return self.delete_at(i)
def find(self, k):
for x in self:
if x.key == k:
return x
return None
def find_min(self):
out = None
for x in range(self):
if (out == None) or (x.key < out.key):
out = x
return out
def find_max(self):
out = None
for x in range(self):
if (out == None) or (x.key > out.key):
out = x
return out
def find_next(self, k): # 寻找键值为k的下一位元素
out = None
for x in range(self):
if (x.key > k):
if (out == None) or (x.key < out.key):
out = x
return out
def find_prev(self, k):
out = None
for x in range(self):
if x.key < k:
if (out == None) or (x.key > out.key):
out = x
return out
def iter_ord(self):
x = self.find_min()
while x:
yield x
x = self.find_prev(x.key)
return set_from_sequence