这里写目录标题
12.27
import math
import numpy as np
class Empty(Exception):
pass
class _DoublyLinkedBase:
"""A base class providing a doubly linked list representation."""
class _Node:
"""Lightweight,nonpublic class for storing a doubly linked node."""
__slots__ = "_element", "_prev", "_next" # streaming memory
def __init__(self, element, prev, next): # initialize node's fields
self._element = element # use's element
self._prev = prev # previous node rederence
self._next = next # next node reference
def __init__(self):
"""Create an empty list."""
self._header = self._Node(None, None, None)
self._trailer = self._Node(None, None, None)
self._header._next = self._trailer # trailer is after header
self._trailer._prev = self._header # header is before trailer
self._size = 0 # number of elements
def __len__(self):
"""Return the number of elements in the list."""
return self._size
def is_empty(self):
"""Return True if list is empty."""
return self._size == 0
def _insert_between(self, e, predecessor, successor):
"""Add element e between two existing nodes and return new node."""
newest = self._Node(e, predecessor, successor)
predecessor._next = newest
successor._prev = newest
self._size += 1
return newest
def _delete_node(self, node):
"""Delete nonsentinel node from the list and return its element."""
predecessor = node._prev
successor = node._next
predecessor._next = successor
successor._prev = predecessor
self._size -= 1
element = node._element # record deleted element
node._prev = node._next = node._element = None # deprecate node
return element
class LinkedDeque(_DoublyLinkedBase): # note the use of inheritance
"""Double-ended queue implementation based on a doubly linked list."""
def first(self):
"""Return (but do not remove) the element at the front of the deque."""
if self.is_empty():
raise Empty("Deque is empty")
return self._header._next._element # real item just after header
def last(self):
"""Return (but do not remove) the element at the back of the deque."""
if self.is_empty():
raise Empty("Deque is empty")
return self._trailer._prev._element # readl item just before trailer
def insert_first(self, e):
"""Add an element to the front of the deuqe."""
self._insert_between(e, self._header, self._header._next) # after header
def insert_last(self, e):
"""Add an element to the back of the deque."""
self._insert_between(e, self._trailer._prev, self._trailer) # before trailer
def delete_first(self):
"""Remove and return the element from the front of the deque.
Raise Empty exception if the deque is empty.
"""
if self.is_empty():
raise Empty("Deque is empty")
return self._delete_node(self._header._next) # use inherited method
def delete_last(self):
"""Remove and return the element from the back of the deque.
Raise Empty exception if the deque is empty.
"""
if self.is_empty():
raise Empty("Deque is empty")
return self._delete_node(self._trailer._prev) # use inherited method
class PositionalList(_DoublyLinkedBase):
"""A sequential container of elements allowing positional accress."""
# ----------- nested Position class ------------
class Position:
"""An abstraction representing the location of a single element."""
def __init__(self, container, node):
"""Constructor should not be invoked by user."""
self._container = container
self._node = node
def element(self):
"""Return the element stored at this Position."""
return self._node._element
def __eq__(self, other):
"""Return True if other is a Position representing the same location."""
return type(other) is type(self) and other._node is self._node
def __ne__(self, other):
"""Return True if other does not represent the same location."""
return not (self == other) # opposite of __eq__
# --------------- utility method --------------------------------
def _validate(self, p):
"""Return position's node ,or raise appropriate error if invalid."""
if not isinstance(p, self.Position):
raise TypeError("p must be proper Position type")
if p._container is not self:
raise ValueError("p does not belong to this container")
if p._node._next is None:
raise ValueError("p is no longer valid")
return p._node
# ---------------------utility method -------------
def _make_position(self, node):
"""Return Position instance for given node (or None if sentinel)"""
if node is self._header or node is self._trailer:
return None # boundary violation
else:
return self.Position(self, node) # legitimate position
def first(self):
"""Return the first Position in the list (or None if list is empty)."""
return self._make_position(self._header._next)
def last(self):
"""Return the last Position in the list (or None if list is empty)."""
return self._make_position(self._trailer._prev)
def before(self, p):
"""Return the Position just before Position p (or None if p is first)."""
node = self._validate(p)
return self._make_position(node._prev)
def after(self, p):
"""Return the Position just after Position p (or None if p is last)."""
node = self._validate(p)
return self._make_position(node._next)
def __iter__(self):
"""Generate a forward iteration of the elements of the list."""
cursor = self.first()
while cursor is not None:
yield cursor.element()
cursor = self.after(cursor)
# -------------------mutators --------------------------
# override inherited version to return Position,rather than Node
def __insert_between(self, e, predecessor, successor):
"""Add element between existing nodes and return new Position."""
node = super()._insert_between(e, predecessor, successor)
return self._make_position(node)
def add_first(self, e):
"""Insert element e at the front of the list and return new Position."""
return self._insert_between(e, self._header, self._header._next)
def add_last(self, e):
"""Insert element e at the back of the list and return new Postion."""
return self.__insert_between(e, self._trailer._prev, self._trailer)
def add_before(self, p, e):
"""Insert element e into list before Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original._prev, original)
def add_after(self, p, e):
"""Insert element e into list after Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original, original._next)
def delete(self, p):
"""Remove and return the element at Position p."""
original = self._validate(p)
return self._delete_node(original) # inherited method returns element
def replace(self, p, e):
"""Replace the element at Position p with e.
Return the element formerly at Position p.
"""
original = self._validate(p)
old_value = original._element # temporarily store old element
original._element = e # replace with new element
return old_value # return the old element value
def merge(self, p):
walk1 = self.first()._node
walk2 = p.first()._node
while walk1 is not self._trailer and walk2 is not p._trailer:
temp1, temp2 = walk1._next, walk2._next
if walk2._element < walk1._element:
walk1._prev._next = walk2
walk2._prev = walk1._prev
walk2._next = walk1
walk1._prev = walk2
walk2 = temp2
else:
walk1 = temp1
self._size += 1
if walk2 is not p._trailer:
walk1 = walk1._prev # 如果第二个链表还有节点则继续连接
walk1._next = walk2
walk2._prev = walk1
while walk2 is not p._trailer:
self._size += 1
walk2 = walk2._next
self._trailer._element, self._trailer._next, self._trailer._prev = None, None, None
self._trailer = walk2
if __name__ == '__main__':
np.random.seed(1)
array1 = np.sort(np.random.randint(1, 100, 20))
array2 = np.sort(np.random.randint(1, 100, 30))
positionArray1 = PositionalList()
positionArray2 = PositionalList()
for value in array1:
positionArray1.add_last(value)
for value in array2:
positionArray2.add_last(value)
positionArray1.merge(positionArray2)
for value in positionArray1:
print(value, end=' ')
# 参考力扣合并两个有序链表
# https://leetcode-cn.com/problems/merge-two-sorted-lists/solution/he-bing-liang-ge-you-xu-lian-biao-by-leetcode-solu/
12.28
import math
import numpy as np
class Empty(Exception):
pass
class _DoublyLinkedBase:
"""A base class providing a doubly linked list representation."""
class _Node:
"""Lightweight,nonpublic class for storing a doubly linked node."""
__slots__ = "_element", "_prev", "_next" # streaming memory
def __init__(self, element, prev, next): # initialize node's fields
self._element = element # use's element
self._prev = prev # previous node rederence
self._next = next # next node reference
def __init__(self):
"""Create an empty list."""
self._header = self._Node(None, None, None)
self._trailer = self._Node(None, None, None)
self._header._next = self._trailer # trailer is after header
self._trailer._prev = self._header # header is before trailer
self._size = 0 # number of elements
def __len__(self):
"""Return the number of elements in the list."""
return self._size
def is_empty(self):
"""Return True if list is empty."""
return self._size == 0
def _insert_between(self, e, predecessor, successor):
"""Add element e between two existing nodes and return new node."""
newest = self._Node(e, predecessor, successor)
predecessor._next = newest
successor._prev = newest
self._size += 1
return newest
def _delete_node(self, node):
"""Delete nonsentinel node from the list and return its element."""
predecessor = node._prev
successor = node._next
predecessor._next = successor
successor._prev = predecessor
self._size -= 1
element = node._element # record deleted element
node._prev = node._next = node._element = None # deprecate node
return element
class LinkedDeque(_DoublyLinkedBase): # note the use of inheritance
"""Double-ended queue implementation based on a doubly linked list."""
def first(self):
"""Return (but do not remove) the element at the front of the deque."""
if self.is_empty():
raise Empty("Deque is empty")
return self._header._next._element # real item just after header
def last(self):
"""Return (but do not remove) the element at the back of the deque."""
if self.is_empty():
raise Empty("Deque is empty")
return self._trailer._prev._element # readl item just before trailer
def insert_first(self, e):
"""Add an element to the front of the deuqe."""
self._insert_between(e, self._header, self._header._next) # after header
def insert_last(self, e):
"""Add an element to the back of the deque."""
self._insert_between(e, self._trailer._prev, self._trailer) # before trailer
def delete_first(self):
"""Remove and return the element from the front of the deque.
Raise Empty exception if the deque is empty.
"""
if self.is_empty():
raise Empty("Deque is empty")
return self._delete_node(self._header._next) # use inherited method
def delete_last(self):
"""Remove and return the element from the back of the deque.
Raise Empty exception if the deque is empty.
"""
if self.is_empty():
raise Empty("Deque is empty")
return self._delete_node(self._trailer._prev) # use inherited method
class PositionalList(_DoublyLinkedBase):
"""A sequential container of elements allowing positional accress."""
# ----------- nested Position class ------------
class Position:
"""An abstraction representing the location of a single element."""
def __init__(self, container, node):
"""Constructor should not be invoked by user."""
self._container = container
self._node = node
def element(self):
"""Return the element stored at this Position."""
return self._node._element
def __eq__(self, other):
"""Return True if other is a Position representing the same location."""
return type(other) is type(self) and other._node is self._node
def __ne__(self, other):
"""Return True if other does not represent the same location."""
return not (self == other) # opposite of __eq__
# --------------- utility method --------------------------------
def _validate(self, p):
"""Return position's node ,or raise appropriate error if invalid."""
if not isinstance(p, self.Position):
raise TypeError("p must be proper Position type")
if p._container is not self:
raise ValueError("p does not belong to this container")
if p._node._next is None:
raise ValueError("p is no longer valid")
return p._node
# ---------------------utility method -------------
def _make_position(self, node):
"""Return Position instance for given node (or None if sentinel)"""
if node is self._header or node is self._trailer:
return None # boundary violation
else:
return self.Position(self, node) # legitimate position
def first(self):
"""Return the first Position in the list (or None if list is empty)."""
return self._make_position(self._header._next)
def last(self):
"""Return the last Position in the list (or None if list is empty)."""
return self._make_position(self._trailer._prev)
def before(self, p):
"""Return the Position just before Position p (or None if p is first)."""
node = self._validate(p)
return self._make_position(node._prev)
def after(self, p):
"""Return the Position just after Position p (or None if p is last)."""
node = self._validate(p)
return self._make_position(node._next)
def __iter__(self):
"""Generate a forward iteration of the elements of the list."""
cursor = self.first()
while cursor is not None:
yield cursor.element()
cursor = self.after(cursor)
# -------------------mutators --------------------------
# override inherited version to return Position,rather than Node
def __insert_between(self, e, predecessor, successor):
"""Add element between existing nodes and return new Position."""
node = super()._insert_between(e, predecessor, successor)
return self._make_position(node)
def add_first(self, e):
"""Insert element e at the front of the list and return new Position."""
return self._insert_between(e, self._header, self._header._next)
def add_last(self, e):
"""Insert element e at the back of the list and return new Postion."""
return self.__insert_between(e, self._trailer._prev, self._trailer)
def add_before(self, p, e):
"""Insert element e into list before Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original._prev, original)
def add_after(self, p, e):
"""Insert element e into list after Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original, original._next)
def delete(self, p):
"""Remove and return the element at Position p."""
original = self._validate(p)
return self._delete_node(original) # inherited method returns element
def replace(self, p, e):
"""Replace the element at Position p with e.
Return the element formerly at Position p.
"""
original = self._validate(p)
old_value = original._element # temporarily store old element
original._element = e # replace with new element
return old_value # return the old element value
def __getitem__(self, k):
if self.is_empty() or k >= len(self):
raise KeyError("Key Error: " + repr(k))
else:
index = 0
walk = self.first()
while walk:
if index == k:
return walk
walk = self.after(walk)
index += 1
def _partition(self, low, high):
temp = self[low].element()
while low < high:
while low < high and self[high].element() >= temp:
high -= 1
self.replace(self[low], self[high].element())
while low < high and self[low].element() <= temp:
low += 1
self.replace(self[high], self[low].element())
self.replace(self[low], temp)
return low
def recursive_quick_sort(self, low, high):
if low < high:
partition = self._partition(low, high)
self.recursive_quick_sort(low, partition - 1)
self.recursive_quick_sort(partition + 1, high)
def recursive_merge_sort(self, head):
if not head or not head._next:
return head
slow, fast = head, head._next
while fast and fast._next:
slow, fast = slow._next, fast._next._next
mid, slow._next._prev, slow._next = slow._next, None, None
left, right = self.recursive_merge_sort(head), self.recursive_merge_sort(mid)
sign = first = self._Node(None, None, None)
while left and right:
if left._element < right._element:
sign._next = left
left._prev = sign
left = left._next
else:
sign._next = right
right._prev = sign
right = right._next
sign = sign._next
if left:
sign._next = left
else:
sign._next = right
return first._next
def quick_sort(self):
left = 0
right = len(self) - 1
if right <= left:
return
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
partition = self._partition(left, right)
print(left, partition,right)
if partition + 1 < right: # 先让右边进栈,这样的结果与递归的处理方式完全一致
stack.append(partition + 1)
stack.append(right)
if left < partition - 1:
stack.append(left)
stack.append(partition - 1)
def merge_sort(self, head):
length, first = 0, head
while first:
first, length = first._next, length + 1
sign = self._Node(None, None, None)
sign._next = head
head._prev = sign
deep = 1
while deep < length:
pre, h = sign, sign._next
while h:
h1, i = h, deep
while i and h:
h, i = h._next, i - 1
if i:
break
h2, i = h, deep
while i and h:
h, i = h._next, i - 1
end1, end2 = deep, deep - i
while end1 and end2:
if h1._element < h2._element:
pre._next = h1
h1._prev = pre
h1 = h1._next
end1 = end1 - 1
else:
pre._next = h2
h2._prev = pre
h2 = h2._next
end2 = end2 - 1
pre = pre._next
if end1:
pre._next = h1
h1._prev = pre
else:
pre._next = h2
h2._prev = pre
while end1 > 0 or end2 > 0:
pre, end1, end2 = pre._next, end1 - 1, end2 - 1
pre._next = h
deep *= 2
return sign._next
def sort(self, kind='quick_sort'):
if kind == 'quick_sort':
self.quick_sort()
elif kind == 'recursive_quick_sort':
self.recursive_quick_sort(0, len(self) - 1)
elif kind == 'merge_sort':
start = self._header._next
self._header._next._prev = None
self._header._next = None
self._trailer._prev._next = None
self._trailer._prev = None
node = self.merge_sort(start)
self._header._next = node
node._prev = node
while node._next:
node = node._next
node._next = self._trailer
self._trailer._prev = node
elif kind == 'recursive_merge_sort':
start = self._header._next
self._header._next._prev = None
self._header._next = None
self._trailer._prev._next = None
self._trailer._prev = None
node = self.recursive_merge_sort(start)
self._header._next = node
node._prev = node
while node._next:
node = node._next
node._next = self._trailer
self._trailer._prev = node
pass
if __name__ == '__main__':
np.random.seed(1)
array = np.random.randint(1, 100, 10)
positionArray = PositionalList()
for value in array:
positionArray.add_last(value)
print(array)
positionArray.sort() # 提供了递归与非递归的快速排序算法与归并算法
for value in positionArray:
print(value, end=' ')
# 参考力扣https://leetcode-cn.com/problems/sort-list/solution/sort-list-gui-bing-pai-xu-lian-biao-by-jyd/
12.29
import math
import numpy as np
class Empty(Exception):
pass
class _DoublyLinkedBase:
"""A base class providing a doubly linked list representation."""
class _Node:
"""Lightweight,nonpublic class for storing a doubly linked node."""
__slots__ = "_element", "_prev", "_next" # streaming memory
def __init__(self, element, prev, next): # initialize node's fields
self._element = element # use's element
self._prev = prev # previous node rederence
self._next = next # next node reference
def __init__(self):
"""Create an empty list."""
self._header = self._Node(None, None, None)
self._trailer = self._Node(None, None, None)
self._header._next = self._trailer # trailer is after header
self._trailer._prev = self._header # header is before trailer
self._size = 0 # number of elements
def __len__(self):
"""Return the number of elements in the list."""
return self._size
def is_empty(self):
"""Return True if list is empty."""
return self._size == 0
def _insert_between(self, e, predecessor, successor):
"""Add element e between two existing nodes and return new node."""
newest = self._Node(e, predecessor, successor)
predecessor._next = newest
successor._prev = newest
self._size += 1
return newest
def _delete_node(self, node):
"""Delete nonsentinel node from the list and return its element."""
predecessor = node._prev
successor = node._next
predecessor._next = successor
successor._prev = predecessor
self._size -= 1
element = node._element # record deleted element
node._prev = node._next = node._element = None # deprecate node
return element
class LinkedDeque(_DoublyLinkedBase): # note the use of inheritance
"""Double-ended queue implementation based on a doubly linked list."""
def first(self):
"""Return (but do not remove) the element at the front of the deque."""
if self.is_empty():
raise Empty("Deque is empty")
return self._header._next._element # real item just after header
def last(self):
"""Return (but do not remove) the element at the back of the deque."""
if self.is_empty():
raise Empty("Deque is empty")
return self._trailer._prev._element # readl item just before trailer
def insert_first(self, e):
"""Add an element to the front of the deuqe."""
self._insert_between(e, self._header, self._header._next) # after header
def insert_last(self, e):
"""Add an element to the back of the deque."""
self._insert_between(e, self._trailer._prev, self._trailer) # before trailer
def delete_first(self):
"""Remove and return the element from the front of the deque.
Raise Empty exception if the deque is empty.
"""
if self.is_empty():
raise Empty("Deque is empty")
return self._delete_node(self._header._next) # use inherited method
def delete_last(self):
"""Remove and return the element from the back of the deque.
Raise Empty exception if the deque is empty.
"""
if self.is_empty():
raise Empty("Deque is empty")
return self._delete_node(self._trailer._prev) # use inherited method
class PositionalList(_DoublyLinkedBase):
"""A sequential container of elements allowing positional accress."""
# ----------- nested Position class ------------
class Position:
"""An abstraction representing the location of a single element."""
def __init__(self, container, node):
"""Constructor should not be invoked by user."""
self._container = container
self._node = node
def element(self):
"""Return the element stored at this Position."""
return self._node._element
def __eq__(self, other):
"""Return True if other is a Position representing the same location."""
return type(other) is type(self) and other._node is self._node
def __ne__(self, other):
"""Return True if other does not represent the same location."""
return not (self == other) # opposite of __eq__
# --------------- utility method --------------------------------
def _validate(self, p):
"""Return position's node ,or raise appropriate error if invalid."""
if not isinstance(p, self.Position):
raise TypeError("p must be proper Position type")
if p._container is not self:
raise ValueError("p does not belong to this container")
if p._node._next is None:
raise ValueError("p is no longer valid")
return p._node
# ---------------------utility method -------------
def _make_position(self, node):
"""Return Position instance for given node (or None if sentinel)"""
if node is self._header or node is self._trailer:
return None # boundary violation
else:
return self.Position(self, node) # legitimate position
def first(self):
"""Return the first Position in the list (or None if list is empty)."""
return self._make_position(self._header._next)
def last(self):
"""Return the last Position in the list (or None if list is empty)."""
return self._make_position(self._trailer._prev)
def before(self, p):
"""Return the Position just before Position p (or None if p is first)."""
node = self._validate(p)
return self._make_position(node._prev)
def after(self, p):
"""Return the Position just after Position p (or None if p is last)."""
node = self._validate(p)
return self._make_position(node._next)
def __iter__(self):
"""Generate a forward iteration of the elements of the list."""
cursor = self.first()
while cursor is not None:
yield cursor.element()
cursor = self.after(cursor)
# -------------------mutators --------------------------
# override inherited version to return Position,rather than Node
def __insert_between(self, e, predecessor, successor):
"""Add element between existing nodes and return new Position."""
node = super()._insert_between(e, predecessor, successor)
return self._make_position(node)
def add_first(self, e):
"""Insert element e at the front of the list and return new Position."""
return self._insert_between(e, self._header, self._header._next)
def add_last(self, e):
"""Insert element e at the back of the list and return new Postion."""
return self.__insert_between(e, self._trailer._prev, self._trailer)
def add_before(self, p, e):
"""Insert element e into list before Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original._prev, original)
def add_after(self, p, e):
"""Insert element e into list after Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original, original._next)
def delete(self, p):
"""Remove and return the element at Position p."""
original = self._validate(p)
return self._delete_node(original) # inherited method returns element
def replace(self, p, e):
"""Replace the element at Position p with e.
Return the element formerly at Position p.
"""
original = self._validate(p)
old_value = original._element # temporarily store old element
original._element = e # replace with new element
return old_value # return the old element value
def merge_sort(self, head):
length, first = 0, head
while first:
length, first = length + 1, first._next
node = self._Node(None, None, None)
node._next = head
head._prev = node
layer = 1
while layer < length:
start, h = node, node._next
while h:
h1, i = h, layer
while i and h:
h, i = h._next, i - 1
if i: # 只有一层则跳出
break
h2, i = h, layer
while i and h:
h, i = h._next, i - 1
end1, end2 = layer, layer - i
while end1 and end2:
if h1._element < h2._element:
start._next = h1
h1._prev = start
h1 = h1._next
end1 -= 1
else:
start._next = h2
h2._prev = start
h2 = h2._next
end2 -= 1
start = start._next
if end1:
start._next = h1
h1._prev = start
else:
start._next = h2
h2._prev = start
while end1 > 0 or end2 > 0:
start, end1, end2 = start._next, end1 - 1, end2 - 1
start._next = h
layer *= 2
return node._next
def sort(self):
start = self._header._next
self._header._next._prev = None
self._header._next = None
self._trailer._prev._next = None
self._trailer._prev = None
node = self.merge_sort(start)
self._header._next = node
node._prev = node
while node._next:
node = node._next
node._next = self._trailer
self._trailer._prev = node
if __name__ == '__main__':
np.random.seed(1)
array = np.random.randint(1, 100, 10)
positionArray = PositionalList()
for value in array:
positionArray.add_last(value)
positionArray.sort()
for value in positionArray:
print(value, end=' ')
# 参考力扣https://leetcode-cn.com/problems/sort-list/solution/sort-list-gui-bing-pai-xu-lian-biao-by-jyd/
12.30
import math
import numpy as np
class Empty(Exception):
pass
class _DoublyLinkedBase:
"""A base class providing a doubly linked list representation."""
class _Node:
"""Lightweight,nonpublic class for storing a doubly linked node."""
__slots__ = "_element", "_prev", "_next" # streaming memory
def __init__(self, element, prev, next): # initialize node's fields
self._element = element # use's element
self._prev = prev # previous node rederence
self._next = next # next node reference
def __init__(self):
"""Create an empty list."""
self._header = self._Node(None, None, None)
self._trailer = self._Node(None, None, None)
self._header._next = self._trailer # trailer is after header
self._trailer._prev = self._header # header is before trailer
self._size = 0 # number of elements
def __len__(self):
"""Return the number of elements in the list."""
return self._size
def is_empty(self):
"""Return True if list is empty."""
return self._size == 0
def _insert_between(self, e, predecessor, successor):
"""Add element e between two existing nodes and return new node."""
newest = self._Node(e, predecessor, successor)
predecessor._next = newest
successor._prev = newest
self._size += 1
return newest
def _delete_node(self, node):
"""Delete nonsentinel node from the list and return its element."""
predecessor = node._prev
successor = node._next
predecessor._next = successor
successor._prev = predecessor
self._size -= 1
element = node._element # record deleted element
node._prev = node._next = node._element = None # deprecate node
return element
class LinkedDeque(_DoublyLinkedBase): # note the use of inheritance
"""Double-ended queue implementation based on a doubly linked list."""
def first(self):
"""Return (but do not remove) the element at the front of the deque."""
if self.is_empty():
raise Empty("Deque is empty")
return self._header._next._element # real item just after header
def last(self):
"""Return (but do not remove) the element at the back of the deque."""
if self.is_empty():
raise Empty("Deque is empty")
return self._trailer._prev._element # readl item just before trailer
def insert_first(self, e):
"""Add an element to the front of the deuqe."""
self._insert_between(e, self._header, self._header._next) # after header
def insert_last(self, e):
"""Add an element to the back of the deque."""
self._insert_between(e, self._trailer._prev, self._trailer) # before trailer
def delete_first(self):
"""Remove and return the element from the front of the deque.
Raise Empty exception if the deque is empty.
"""
if self.is_empty():
raise Empty("Deque is empty")
return self._delete_node(self._header._next) # use inherited method
def delete_last(self):
"""Remove and return the element from the back of the deque.
Raise Empty exception if the deque is empty.
"""
if self.is_empty():
raise Empty("Deque is empty")
return self._delete_node(self._trailer._prev) # use inherited method
class PositionalList(_DoublyLinkedBase):
"""A sequential container of elements allowing positional accress."""
# ----------- nested Position class ------------
class Position:
"""An abstraction representing the location of a single element."""
def __init__(self, container, node):
"""Constructor should not be invoked by user."""
self._container = container
self._node = node
def element(self):
"""Return the element stored at this Position."""
return self._node._element
def __eq__(self, other):
"""Return True if other is a Position representing the same location."""
return type(other) is type(self) and other._node is self._node
def __ne__(self, other):
"""Return True if other does not represent the same location."""
return not (self == other) # opposite of __eq__
# --------------- utility method --------------------------------
def _validate(self, p):
"""Return position's node ,or raise appropriate error if invalid."""
if not isinstance(p, self.Position):
raise TypeError("p must be proper Position type")
if p._container is not self:
raise ValueError("p does not belong to this container")
if p._node._next is None:
raise ValueError("p is no longer valid")
return p._node
# ---------------------utility method -------------
def _make_position(self, node):
"""Return Position instance for given node (or None if sentinel)"""
if node is self._header or node is self._trailer:
return None # boundary violation
else:
return self.Position(self, node) # legitimate position
def first(self):
"""Return the first Position in the list (or None if list is empty)."""
return self._make_position(self._header._next)
def last(self):
"""Return the last Position in the list (or None if list is empty)."""
return self._make_position(self._trailer._prev)
def before(self, p):
"""Return the Position just before Position p (or None if p is first)."""
node = self._validate(p)
return self._make_position(node._prev)
def after(self, p):
"""Return the Position just after Position p (or None if p is last)."""
node = self._validate(p)
return self._make_position(node._next)
def __iter__(self):
"""Generate a forward iteration of the elements of the list."""
cursor = self.first()
while cursor is not None:
yield cursor.element()
cursor = self.after(cursor)
# -------------------mutators --------------------------
# override inherited version to return Position,rather than Node
def __insert_between(self, e, predecessor, successor):
"""Add element between existing nodes and return new Position."""
node = super()._insert_between(e, predecessor, successor)
return self._make_position(node)
def add_first(self, e):
"""Insert element e at the front of the list and return new Position."""
return self._insert_between(e, self._header, self._header._next)
def add_last(self, e):
"""Insert element e at the back of the list and return new Postion."""
return self.__insert_between(e, self._trailer._prev, self._trailer)
def add_before(self, p, e):
"""Insert element e into list before Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original._prev, original)
def add_after(self, p, e):
"""Insert element e into list after Position p and return new Position."""
original = self._validate(p)
return self._insert_between(e, original, original._next)
def delete(self, p):
"""Remove and return the element at Position p."""
original = self._validate(p)
return self._delete_node(original) # inherited method returns element
def replace(self, p, e):
"""Replace the element at Position p with e.
Return the element formerly at Position p.
"""
original = self._validate(p)
old_value = original._element # temporarily store old element
original._element = e # replace with new element
return old_value # return the old element value
def _swap(self, h1, h2):
h1_prev = h1._prev
h1_next = h1._next
h2_prev = h2._prev
h2_next = h2._next
if h1_prev:
h1_prev._next = h2
h2._next = h1_next if h1_next != h2 else h1
if h1_next:
h1_next._prev = h2 if h1_next != h2 else h1_prev
h2._prev = h1_prev if h1_next != h2 else h1_prev
if h2_prev:
h2_prev._next = h1 if h1_next != h2 else h2_next
h1._next = h2_next
if h2_next:
h2_next._prev = h1
h1._prev = h2_prev if h1_next != h2 else h2
def _dealPivot(self, start, left, right):
mid = left + (right - left) // 2 # 中间值
index = 0
head = start # 记录头,每次从头开始寻找
h1, h2, h3 = start, start, start
while left or right or index < mid:
if left: # 找到最左边
h1, left = h1._next, left - 1
if index < mid: # 找到中间位置
h2, index = h2._next, index + 1
if right: # 找到最右边
h3, right = h3._next, right - 1
# 分别按照升序的方式进行排序交换位置,这里使用head判断头部位置是否发生交换
if h1._element <= h3._element:
if h2._element < h1._element:
self._swap(h1, h2)
h1, h2 = h2, h1
if h2 == head:
head = h1
elif h2._element > h3._element:
self._swap(h2, h3)
h2, h3 = h3, h2
else:
pass
else:
if h2._element < h3._element:
self._swap(h2, h3)
h2, h3 = h3, h2
self._swap(h1, h3)
h1, h3 = h3, h1
if h3 == head:
head = h1
elif h1._element > h2._element > h3._element:
self._swap(h1, h3)
h1, h3 = h3, h1
if h3 == head:
head = h1
else:
self._swap(h1, h2)
h1, h2 = h2, h1
if h2 == head:
head = h1
self._swap(h1, h3)
h1, h3 = h3, h1
if h3 == head:
head = h1
return h1, h2, h3, head
def _partition(self, start, low, high):
h1, h2, h3, h4 = self._dealPivot(start, low, high) # 使用三数取中选择基准值并分别获取需要交换的左,mid,右,及头部
if h2 == h1: # 这里这么做是因为中点与当前的起点重合,防止再次执行交换操作
low += 1
else:
self._swap(h2, h3) # 基准值和最后一个金环互换
h2, h3 = h3, h2 # 更新指针
key = h3._element # 获取基准值
while low < high:
while low < high and h1 and h1._element <= key:
low += 1
h1 = h1._next
if low < high:
h3._element = h1._element
while low < high and h3 and h3._element >= key:
high -= 1
h3 = h3._prev
if low < high:
h1._element = h3._element
h1._element = key
return h4, low
def quick_sort(self, start):
left = 0
right = 0
head = start
while head:
head, right = head._next, right + 1
if right <= left:
return
stack = [left, right - 1]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
start, partition = self._partition(start, left, right)
if partition + 1 < right: # 先让右边进栈,这样的结果与递归的处理方式完全一致
stack.append(partition + 1)
stack.append(right)
if left < partition - 1:
stack.append(left)
stack.append(partition - 1)
return start
def sort(self):
start = self._header._next
self._header._next._prev = None
self._header._next = None
self._trailer._prev._next = None
self._trailer._prev = None
node = self.quick_sort(start)
self._header._next = node
node._prev = node
while node._next:
node = node._next
node._next = self._trailer
self._trailer._prev = node
if __name__ == '__main__':
np.random.seed(1)
array = np.random.randint(1, 100, 120)
positionArray = PositionalList()
for value in array:
positionArray.add_last(value)
print(array)
positionArray.sort() # 基于链表的原地非递归快速排序算法
for value in positionArray:
print(value, end=' ')
# 基准的选取参考CSDN博客
# https://blog.csdn.net/liuyi1207164339/article/details/50827608
# https://blog.csdn.net/weixin_30758821/article/details/97146889?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
12.31
import time
import numpy as np
def partition(data, left, right):
index = abs(right - 3) if abs(right - 3) < (right - left) else right # 防止每次超过当前队列的长度
pivot = data[index]
end = right
data[index], data[end] = data[end], data[index]
while left < right: # 双指针法
while left < right and data[left] <= pivot:
left += 1
while left < right and data[right] >= pivot:
right -= 1
data[left], data[right] = data[right], data[left]
data[left], data[end] = data[end], data[left]
return left
def quicksort(data, left, right):
if left < right:
mid = partition(data, left, right)
quicksort(data, left, mid - 1)
quicksort(data, mid + 1, right)
if __name__ == '__main__':
N = 10
data = list(np.random.randint(0, 100 * N, N))
now = time.time()
print(data)
quicksort(data, 0, N - 1)
print(data)
print(f"快速排序大小为{N}的数组花费时间{time.time() - now}")
12.33
import numpy as np
def inplaceQuickSort(S, left, right):
"""Sort the list from S[a] to S[b] inclusive using the quick-sort algorithm"""
if left >= right: # range is trivially sorted
return
pivot = S[right]
a, b = left, right
while left < right: # 挖坑法
while left < right and S[left] <= pivot:
left += 1
S[right] = S[left]
while left < right and S[right] >= pivot:
right -= 1
S[left] = S[right]
S[left] = pivot
inplaceQuickSort(S, a, left - 1)
inplaceQuickSort(S, left + 1, b)
if __name__ == '__main__':
array = np.random.randint(0, 10, 10)
print(array)
inplaceQuickSort(array, 0, len(array) - 1)
print(array)
12.34
import numpy as np
from abc import ABC
from collections import MutableMapping
class Tree:
"""Abstract base class representing a tree structure."""
# ----------------------------nested Position class -----------------------------
class Position:
"""An abstraction representing the location of a single element."""
def element(self):
"""return the element stored at this Position"""
raise NotImplementedError("must be implemented by subclass")
def __eq__(self, other):
"""Return True if other Position represents the same location."""
raise NotImplementedError("must be implemented by subclass")
def __ne__(self, other):
"""Return True if other does not represent the same location."""
return not (self == other)
# ---------- abstract methods that concrete subclass must support------------
def root(self):
"""Return Position representing the tree's root (or None if empty)."""
raise NotImplementedError("must be implemented by subclass")
def parent(self, p):
"""Return Position representing p's parent """
return NotImplementedError("must be implemented by subclass")
def num_children(self, p):
"""Return the number of children that Position p has."""
raise NotImplementedError("must be implemented by subclass")
def children(self, p):
"""Generate an iteration of Positions representing p's children."""
raise NotImplementedError("must be implemented by subclass")
def __len__(self):
"""Return the total number of elements in the tree."""
raise NotImplementedError("must be implemented by subclass")
# --------------------- concrete methods implemented in this class --------------
def is_root(self, p):
"Return True if Position p represents the root of the tree."
return self.root() == p
def is_leaf(self, p):
"""Return True if Position p does not have any children."""
return self.num_children(p) == 0
def is_empty(self):
"""Return True if the tree is empty."""
return len(self) == 0
def depth(self, p):
"""Return the number of levels separating Position p from the root."""
if self.is_root(p):
return 0
else:
return 1 + self.depth(self.parent(p))
# 定义 树的高度等于所有叶子结点的深度中的最大值
# 时间复杂度为n**2
def _height1(self):
"""Return the height of the tree."""
return max(self.depth(p) for p in self.positions() if self.is_leaf(p))
# 从根节点,自顶向下,效率比height快
# 时间复杂度为n
def _height2(self, p):
if self.is_leaf(p):
return 0
else:
return 1 + max(self._height2(c) for c in self.children(p))
def height(self, p=None):
"""Return the height of the subtree rooted at Position p.
If p is None,return height of the entire tree.
"""
if p is None:
p = self.root()
return self._height2(p) # start_height2 recursion
def __iter__(self):
"""Generate an iteration of the tree's elements."""
for p in self.positions(): # use same order as positions()
yield p.element() # but yield each element
class BinaryTree(Tree):
"""Abstract base class representing a binary tree structure."""
# -------------------additional abstract methods -------------------------
def left(self, p):
"""Return a Position representing p's left child.
Return None if p does not have a left child.
"""
raise NotImplementedError("must be implemented by subclass")
def right(self, p):
"""Return a Position representing p's right child.
Return None if p does not have a right child.
"""
raise NotImplementedError("must be implemented by subclass")
# ----------------------------concrete mehtods implemented in this class ===========
def sibling(self, p):
"""Return a Position representing p's sibling (or None if no sibling)。"""
parent = self.parent(p)
if parent is None: # p must be the root
return None # root has no sibling
else:
if p == self.left(parent):
return self.right(parent) # possibly None
else:
return self.left(parent) # possibly None
def children(self, p):
"""Generate an iteraiton of Positions representing p's children."""
if self.left(p) is not None:
yield self.left(p)
if self.right(p) is not None:
yield self.right(p)
class LinkedBinaryTree(BinaryTree):
"""Linked representation of binary tree structure."""
class _Node: # Lightweight ,nonpublic class for storing a node.
__slots__ = "_element", "_parent", "_left", "_right"
def __init__(self, element, parent=None, left=None, right=None):
self._element = element
self._parent = parent
self._left = left
self._right = right
class Position(BinaryTree.Position):
""" An abstraction representing the location of a single element."""
def __init__(self, container, node):
"""Constructor should not be invoked by user."""
self._container = container
self._node = node
def element(self):
"""Return the element stored at this Position."""
return self._node._element
def __eq__(self, other):
"""Return True if other is a Position representing the same location."""
return type(other) is type(self) and other._node is self._node
def _validate(self, p):
"""Return associated node ,if position is valid."""
if not isinstance(p, self.Position):
raise TypeError("p must be proper Position type")
if p._container is not self:
raise ValueError("p does not belong to this container")
if p._node._parent is p._node: # convention for deprecated nodes
raise ValueError("p is no longer valid")
return p._node
def _make_position(self, node):
"""Return Position instance for given node (or None if no node)."""
return self.Position(self, node) if node is not None else None
# ------------------------ binary tree constructor --------------------
def __init__(self):
"""Create an initially empty binary tree."""
self._root = None
self._size = 0
# --------------------public accessors ---------------------
def __len__(self):
"""return the total number of elements in the tree."""
return self._size
def root(self):
"""Return the root Position of the tree(or None if tree is empty)"""
return self._make_position(self._root)
def parent(self, p):
node = self._validate(p)
return self._make_position(node._parent)
def left(self, p):
"""Return the Position of p's left child (or None if no left child)."""
node = self._validate(p)
return self._make_position(node._left)
def right(self, p):
"""Return the Position of p's right child (or None if no right child)."""
node = self._validate(p)
return self._make_position(node._right)
def num_children(self, p):
"""Return the number of children of Position p."""
node = self._validate(p)
count = 0
if node._left is not None:
count += 1
if node._right is not None:
count += 1
return count
def _add_root(self, e):
"""Place element e at the root of an empty tree and return new Position.
Raise ValueError if tree nonempty.
"""
if self._root is not None:
raise ValueError("Root exists")
self._size += 1
self._root = self._Node(e)
return self._make_position(self._root)
def _add_left(self, p, e):
"""Create a new left child for Position p,storing element e.
Return the Position of new node.
Raise ValueError if Position p is invalid or p already has a left child.
"""
node = self._validate(p)
if node._left is not None:
raise ValueError("Left child exists.")
self._size += 1
node._left = self._Node(e, node)
return self._make_position(node._left)
def _add_right(self, p, e):
"""Create a new right child for Position p,storing element e.
Return the Position of new node.
Raise ValueError if Position p is invalid or p already has a left child.
"""
node = self._validate(p)
if node._right is not None:
raise ValueError("Right child exists")
self._size += 1
node._right = self._Node(e, node)
return self._make_position(node._right)
def _replace(self, p, e):
"""Replace the element at position p with e , and return old element."""
node = self._validate(p)
old = node._element
node._element = e
return old
def _delete(self, p):
"""Delete the node at Position p , and replace it with its child, if any.
Return the element that had been stored at Position p.
Raise ValueError if Position p is invalid or p has two children.
"""
node = self._validate(p)
if self.num_children(p) == 2:
raise ValueError("p has two children")
child = node._left if node._left else node._right # might be None
if child is not None:
child._parent = node._parent # child's grandparent becomes parent
if node is self._root:
self._root = child # child becomes root
else:
parent = node._parent
if node is parent._left:
parent._left = child
else:
parent._right = child
self._size -= 1
node._parent = node # convention for deprecated node 丢弃该节点
return node._element
def _attach(self, p, t1, t2):
"""Attach trees t1 and t2 as left and right subtrees of external p."""
node = self._validate(p)
if not self.is_leaf(p):
raise ValueError('position must be leaf')
if not type(self) is type(t1) is type(t2):
raise TypeError("Tree types must match")
self._size += len(t1) + len(t2)
if not t1.is_empty(): # attached t1 as left subtree of node
t1._root._parent = node
node._left = t1._root
t1._root = None
t1._size = 0
if not t2.is_empty(): # attached t2 as right subtree of node
t2._root._parent = node
node._right = t2._root
t2._root = None
t2._size = 0
pass
class MapBase(MutableMapping, ABC):
"""Our own abstract base class that includes a nonpublic _Item class"""
# ---------------------nested _Item class ---------------
class _Item:
"""Lightweight composite to store key-value pairs as map items."""
__slots__ = '_key', '_value'
def __init__(self, k, v):
self._key = k
self._value = v
def __eq__(self, other):
return self._key == other._key # compare items based on their keys
def __ne__(self, other):
return not (self == other) # opposite of __eq__
def __lt__(self, other):
return self._key < other._key # compare items based on their keys
class TreeMap(LinkedBinaryTree, MapBase):
"""Sorted map implementation using a binary search tree."""
# ------------override Position class -------------------
class Position(LinkedBinaryTree.Position):
def key(self):
"""Return key of map's key-value pair."""
return self.element()._key
def value(self):
"""Return value of map's key-value pair."""
return self.element()._value
def _subtree_search(self, p, k):
"""Return Position of p's subtree having key k, or last node searched."""
if k == p.key(): # found match
return p
elif k < p.key():
if self.left(p) is not None:
return self._subtree_search(self.left(p), k)
else:
if self.right(p) is not None:
return self._subtree_search(self.right(p), k)
return p
def _subtree_first_position(self, p):
"""Return Position of first item in subtree rooted at p."""
walk = p
while self.left(walk) is not None:
walk = self.left(walk) # keep walking left
return walk
def _subtree_last_position(self, p):
"""Return Position of last item in subtree rooted at p."""
walk = p
while self.right(walk) is not None: # walk walking right
walk = self.right(walk)
return walk
def first(self):
"""Return the first Position in the tree(or None if empty)."""
return self._subtree_first_position(self.root()) if len(self) > 0 else None
def last(self):
"""Return the last Position in the tree (or None if empty)."""
return self._subtree_last_position(self.root()) if len(self) > 0 else None
def before(self, p):
"""Return the Position just before p in the natural order.
Return None if p is the first position
"""
self._validate(p) # inherited from LinkedBinaryTree
if self.left(p):
return self._subtree_last_position(self.left(p))
else:
# walk upward
walk = p
above = self.parent(walk)
while above is not None and walk == self.left(above):
walk = above
above = self.parent(walk)
return above
def after(self, p):
"""Return the Position just after p in the natural order.
Return None if p is the last position.
"""
# symmetric to before(p)
self._validate(p)
if self.right(p):
return self._subtree_first_position(self.right(p))
else:
walk = p
above = self.parent(walk)
while above is not None and self.right(above) == walk:
walk = above
above = self.parent(walk)
return above
def find_position(self, k):
"""Return position with key k , or else neighbor (or None if empty)."""
if self.is_empty():
return None
else:
p = self._subtree_search(self.root(), k)
# self._rebalance_access(p) # hook for balanced tree subclasses
return p
def find_min(self):
"""Return (key,value) pair with minimum key (or None if empty)."""
if self.is_empty():
return None
else:
p = self.first()
return p.key(), p.value()
def find_ge(self, k):
"""Return (key,value) pair with least key greater than or equal to k.
Return None if there does not exist such a key.
"""
if self.is_empty():
return None
else:
p = self.find_position(k) # may not find exact match
if p.key() < k:
p = self.after(p)
return (p.key(), p.value()) if p is not None else None
def find_range(self, start, stop):
"""Iterate all (key , value ) pairs such that start <= key < stop.
If start is None ,iteration begins with minimum key of map.
If stop is None,iteration continues through the maximum key of map.
"""
if not self.is_empty():
if start is None:
p = self.first()
else:
# we initialize p with logic similar to find_ge
p = self.find_position(start)
if p.key() < start:
p = self.after(p)
while p is not None and (stop is None or p.key() < stop):
yield p.key(), p.value()
p = self.after(p)
def __getitem__(self, item):
"""Return value associated with key k (raise KeyError if not fount)."""
if self.is_empty():
raise KeyError("Key Error: " + repr(item))
else:
p = self._subtree_search(self.root(), item)
# self._rebalance_access(p) # hook for balanced tree subclassed
if item != p.key():
raise KeyError('Key Error:' + repr(item))
return p.value()
def __setitem__(self, key, value):
"""Assign value v to key k, overwriting existing value if present."""
if self.is_empty():
leaf = self._add_root(self._Item(key, value)) # from LinkedBinaryTree
else:
p = self._subtree_search(self.root(), key)
if p.key() == key:
p.element()._value = value # replace existing item's value
# self._rebalance_access(p) # hook for balanced tree subclasses
return
else:
item = self._Item(key, value)
if p.key() < key:
leaf = self._add_right(p, item) # inherited from LinkedBinaryTree
else:
leaf = self._add_left(p, item) # inherited from LinkedBinaryTree
# self._rebalance_insert(leaf) # hook for balanced tree subclasses
def __iter__(self):
"""Generate an iteration of all keys in the map in order."""
p = self.first()
while p is not None:
yield p.key(), p.value()
p = self.after(p)
def delete(self, p):
"""Remove the item at given Position."""
self._validate(p) # inherited from LinkedBinaryTree
if self.left(p) and self.right(p): # p has two children
replacement = self._subtree_last_position(self.left(p))
self._replace(p, replacement.element()) # from LinkedBinaryTree
p = replacement
# now p has at most one child
parent = self.parent(p)
self._delete(p) # inherited from LinkedBinaryTree
# self._rebalance_delete(parent) # if root deleted,parent is None
def __delitem__(self, key):
"""Remove item associated with key k (raise KeyError if not found)."""
if not self.is_empty():
p = self._subtree_search(self.root(), key)
if key == p.key():
self.delete(p) # rely on positional version
return # successful deletion complete
# self._rebalance_access(p) # hook for balanced tree subclasses
raise KeyError("Key Error: " + repr(key))
def _relink(self, parent, child, make_left_child):
"""Relink parent node with child node (we allow child to be None)."""
if make_left_child: # make it a left child
parent._left = child
else: # make it a right child
parent._right = child
if child is not None: # make child point to parent
child._parent = parent
def _rotate(self, p):
"""Rotate Position p above its parent."""
x = p._node
y = x._parent # we assume this exist
z = y._parent # grandparent (possibly None)
if z is None:
self._root = x # x becomes root
x._parent = None
else:
self._relink(z, x, y == z._left) # x becomes a direct child of z
# now rotate x and y ,including transfer of middle subtree
if x == y._left:
self._relink(y, x._right, True) # x._right becomes left child of y
self._relink(x, y, False) # y becomes right child of x
else:
self._relink(y, x._left, False) # x._left becomes right child of y
self._relink(x, y, True) # y becomes left child of x
def _restructure(self, x):
"""Perform trinode restructure of Position x with parent/grandparent."""
y = self.parent(x)
z = self.parent(y)
if (x == self.right(y)) == (y == self.right(z)): # matching alignments
self._rotate(y) # single rotation (of y)
return y
else:
self._rotate(x)
self._rotate(x)
return x # x is new subtree root
def change_redBlackTree(self):
stack = [self.root()]
if __name__ == '__main__':
tree = TreeMap()
array = np.random.randint(0,10,10)
for i in array:
tree[i] = i
for node in tree:
print(node)
print(tree.last().element()._key,tree.last().element()._value)
# print(tree.after(tree.root()).element()._key,tree.after(tree.root()).element()._value)
12.35
import numpy as np
from abc import ABC
from collections import MutableMapping
class Tree:
"""Abstract base class representing a tree structure."""
# ----------------------------nested Position class -----------------------------
class Position:
"""An abstraction representing the location of a single element."""
def element(self):
"""return the element stored at this Position"""
raise NotImplementedError("must be implemented by subclass")
def __eq__(self, other):
"""Return True if other Position represents the same location."""
raise NotImplementedError("must be implemented by subclass")
def __ne__(self, other):
"""Return True if other does not represent the same location."""
return not (self == other)
# ---------- abstract methods that concrete subclass must support------------
def root(self):
"""Return Position representing the tree's root (or None if empty)."""
raise NotImplementedError("must be implemented by subclass")
def parent(self, p):
"""Return Position representing p's parent """
return NotImplementedError("must be implemented by subclass")
def num_children(self, p):
"""Return the number of children that Position p has."""
raise NotImplementedError("must be implemented by subclass")
def children(self, p):
"""Generate an iteration of Positions representing p's children."""
raise NotImplementedError("must be implemented by subclass")
def __len__(self):
"""Return the total number of elements in the tree."""
raise NotImplementedError("must be implemented by subclass")
# --------------------- concrete methods implemented in this class --------------
def is_root(self, p):
"Return True if Position p represents the root of the tree."
return self.root() == p
def is_leaf(self, p):
"""Return True if Position p does not have any children."""
return self.num_children(p) == 0
def is_empty(self):
"""Return True if the tree is empty."""
return len(self) == 0
def depth(self, p):
"""Return the number of levels separating Position p from the root."""
if self.is_root(p):
return 0
else:
return 1 + self.depth(self.parent(p))
# 定义 树的高度等于所有叶子结点的深度中的最大值
# 时间复杂度为n**2
def _height1(self):
"""Return the height of the tree."""
return max(self.depth(p) for p in self.positions() if self.is_leaf(p))
# 从根节点,自顶向下,效率比height快
# 时间复杂度为n
def _height2(self, p):
if self.is_leaf(p):
return 0
else:
return 1 + max(self._height2(c) for c in self.children(p))
def height(self, p=None):
"""Return the height of the subtree rooted at Position p.
If p is None,return height of the entire tree.
"""
if p is None:
p = self.root()
return self._height2(p) # start_height2 recursion
def __iter__(self):
"""Generate an iteration of the tree's elements."""
for p in self.positions(): # use same order as positions()
yield p.element() # but yield each element
class BinaryTree(Tree):
"""Abstract base class representing a binary tree structure."""
# -------------------additional abstract methods -------------------------
def left(self, p):
"""Return a Position representing p's left child.
Return None if p does not have a left child.
"""
raise NotImplementedError("must be implemented by subclass")
def right(self, p):
"""Return a Position representing p's right child.
Return None if p does not have a right child.
"""
raise NotImplementedError("must be implemented by subclass")
# ----------------------------concrete mehtods implemented in this class ===========
def sibling(self, p):
"""Return a Position representing p's sibling (or None if no sibling)。"""
parent = self.parent(p)
if parent is None: # p must be the root
return None # root has no sibling
else:
if p == self.left(parent):
return self.right(parent) # possibly None
else:
return self.left(parent) # possibly None
def children(self, p):
"""Generate an iteraiton of Positions representing p's children."""
if self.left(p) is not None:
yield self.left(p)
if self.right(p) is not None:
yield self.right(p)
class LinkedBinaryTree(BinaryTree):
"""Linked representation of binary tree structure."""
class _Node: # Lightweight ,nonpublic class for storing a node.
__slots__ = "_element", "_parent", "_left", "_right"
def __init__(self, element, parent=None, left=None, right=None):
self._element = element
self._parent = parent
self._left = left
self._right = right
class Position(BinaryTree.Position):
""" An abstraction representing the location of a single element."""
def __init__(self, container, node):
"""Constructor should not be invoked by user."""
self._container = container
self._node = node
def element(self):
"""Return the element stored at this Position."""
return self._node._element
def __eq__(self, other):
"""Return True if other is a Position representing the same location."""
return type(other) is type(self) and other._node is self._node
def _validate(self, p):
"""Return associated node ,if position is valid."""
if not isinstance(p, self.Position):
raise TypeError("p must be proper Position type")
if p._container is not self:
raise ValueError("p does not belong to this container")
if p._node._parent is p._node: # convention for deprecated nodes
raise ValueError("p is no longer valid")
return p._node
def _make_position(self, node):
"""Return Position instance for given node (or None if no node)."""
return self.Position(self, node) if node is not None else None
# ------------------------ binary tree constructor --------------------
def __init__(self):
"""Create an initially empty binary tree."""
self._root = None
self._size = 0
# --------------------public accessors ---------------------
def __len__(self):
"""return the total number of elements in the tree."""
return self._size
def root(self):
"""Return the root Position of the tree(or None if tree is empty)"""
return self._make_position(self._root)
def parent(self, p):
node = self._validate(p)
return self._make_position(node._parent)
def left(self, p):
"""Return the Position of p's left child (or None if no left child)."""
node = self._validate(p)
return self._make_position(node._left)
def right(self, p):
"""Return the Position of p's right child (or None if no right child)."""
node = self._validate(p)
return self._make_position(node._right)
def num_children(self, p):
"""Return the number of children of Position p."""
node = self._validate(p)
count = 0
if node._left is not None:
count += 1
if node._right is not None:
count += 1
return count
def _add_root(self, e):
"""Place element e at the root of an empty tree and return new Position.
Raise ValueError if tree nonempty.
"""
if self._root is not None:
raise ValueError("Root exists")
self._size += 1
self._root = self._Node(e)
return self._make_position(self._root)
def _add_left(self, p, e):
"""Create a new left child for Position p,storing element e.
Return the Position of new node.
Raise ValueError if Position p is invalid or p already has a left child.
"""
node = self._validate(p)
if node._left is not None:
raise ValueError("Left child exists.")
self._size += 1
node._left = self._Node(e, node)
return self._make_position(node._left)
def _add_right(self, p, e):
"""Create a new right child for Position p,storing element e.
Return the Position of new node.
Raise ValueError if Position p is invalid or p already has a left child.
"""
node = self._validate(p)
if node._right is not None:
raise ValueError("Right child exists")
self._size += 1
node._right = self._Node(e, node)
return self._make_position(node._right)
def _replace(self, p, e):
"""Replace the element at position p with e , and return old element."""
node = self._validate(p)
old = node._element
node._element = e
return old
def _delete(self, p):
"""Delete the node at Position p , and replace it with its child, if any.
Return the element that had been stored at Position p.
Raise ValueError if Position p is invalid or p has two children.
"""
node = self._validate(p)
if self.num_children(p) == 2:
raise ValueError("p has two children")
child = node._left if node._left else node._right # might be None
if child is not None:
child._parent = node._parent # child's grandparent becomes parent
if node is self._root:
self._root = child # child becomes root
else:
parent = node._parent
if node is parent._left:
parent._left = child
else:
parent._right = child
self._size -= 1
node._parent = node # convention for deprecated node 丢弃该节点
return node._element
def _attach(self, p, t1, t2):
"""Attach trees t1 and t2 as left and right subtrees of external p."""
node = self._validate(p)
if not self.is_leaf(p):
raise ValueError('position must be leaf')
if not type(self) is type(t1) is type(t2):
raise TypeError("Tree types must match")
self._size += len(t1) + len(t2)
if not t1.is_empty(): # attached t1 as left subtree of node
t1._root._parent = node
node._left = t1._root
t1._root = None
t1._size = 0
if not t2.is_empty(): # attached t2 as right subtree of node
t2._root._parent = node
node._right = t2._root
t2._root = None
t2._size = 0
pass
class MapBase(MutableMapping, ABC):
"""Our own abstract base class that includes a nonpublic _Item class"""
# ---------------------nested _Item class ---------------
class _Item:
"""Lightweight composite to store key-value pairs as map items."""
__slots__ = '_key', '_value'
def __init__(self, k, v):
self._key = k
self._value = v
def __eq__(self, other):
return self._key == other._key # compare items based on their keys
def __ne__(self, other):
return not (self == other) # opposite of __eq__
def __lt__(self, other):
return self._key < other._key # compare items based on their keys
class TreeMap(LinkedBinaryTree, MapBase):
"""Sorted map implementation using a binary search tree."""
# ------------override Position class -------------------
class Position(LinkedBinaryTree.Position):
def key(self):
"""Return key of map's key-value pair."""
return self.element()._key
def value(self):
"""Return value of map's key-value pair."""
return self.element()._value
def _subtree_search(self, p, k):
"""Return Position of p's subtree having key k, or last node searched."""
if k == p.key(): # found match
return p
elif k < p.key():
if self.left(p) is not None:
return self._subtree_search(self.left(p), k)
else:
if self.right(p) is not None:
return self._subtree_search(self.right(p), k)
return p
def _subtree_first_position(self, p):
"""Return Position of first item in subtree rooted at p."""
walk = p
while self.left(walk) is not None:
walk = self.left(walk) # keep walking left
return walk
def _subtree_last_position(self, p):
"""Return Position of last item in subtree rooted at p."""
walk = p
while self.right(walk) is not None: # walk walking right
walk = self.right(walk)
return walk
def first(self):
"""Return the first Position in the tree(or None if empty)."""
return self._subtree_first_position(self.root()) if len(self) > 0 else None
def last(self):
"""Return the last Position in the tree (or None if empty)."""
return self._subtree_last_position(self.root()) if len(self) > 0 else None
def before(self, p):
"""Return the Position just before p in the natural order.
Return None if p is the first position
"""
self._validate(p) # inherited from LinkedBinaryTree
if self.left(p):
return self._subtree_last_position(self.left(p))
else:
# walk upward
walk = p
above = self.parent(walk)
while above is not None and walk == self.left(above):
walk = above
above = self.parent(walk)
return above
def after(self, p):
"""Return the Position just after p in the natural order.
Return None if p is the last position.
"""
# symmetric to before(p)
self._validate(p)
if self.right(p):
return self._subtree_first_position(self.right(p))
else:
walk = p
above = self.parent(walk)
while above is not None and self.right(above) == walk:
walk = above
above = self.parent(walk)
return above
def find_position(self, k):
"""Return position with key k , or else neighbor (or None if empty)."""
if self.is_empty():
return None
else:
p = self._subtree_search(self.root(), k)
# self._rebalance_access(p) # hook for balanced tree subclasses
return p
def find_min(self):
"""Return (key,value) pair with minimum key (or None if empty)."""
if self.is_empty():
return None
else:
p = self.first()
return p.key(), p.value()
def find_ge(self, k):
"""Return (key,value) pair with least key greater than or equal to k.
Return None if there does not exist such a key.
"""
if self.is_empty():
return None
else:
p = self.find_position(k) # may not find exact match
if p.key() < k:
p = self.after(p)
return (p.key(), p.value()) if p is not None else None
def find_range(self, start, stop):
"""Iterate all (key , value ) pairs such that start <= key < stop.
If start is None ,iteration begins with minimum key of map.
If stop is None,iteration continues through the maximum key of map.
"""
if not self.is_empty():
if start is None:
p = self.first()
else:
# we initialize p with logic similar to find_ge
p = self.find_position(start)
if p.key() < start:
p = self.after(p)
while p is not None and (stop is None or p.key() < stop):
yield p.key(), p.value()
p = self.after(p)
def __getitem__(self, item):
"""Return value associated with key k (raise KeyError if not fount)."""
if self.is_empty():
raise KeyError("Key Error: " + repr(item))
else:
p = self._subtree_search(self.root(), item)
# self._rebalance_access(p) # hook for balanced tree subclassed
if item != p.key():
raise KeyError('Key Error:' + repr(item))
return p.value()
def __setitem__(self, key, value):
"""Assign value v to key k, overwriting existing value if present."""
if self.is_empty():
leaf = self._add_root(self._Item(key, value)) # from LinkedBinaryTree
else:
p = self._subtree_search(self.root(), key)
if p.key() == key:
p.element()._value = value # replace existing item's value
# self._rebalance_access(p) # hook for balanced tree subclasses
return
else:
item = self._Item(key, value)
if p.key() < key:
leaf = self._add_right(p, item) # inherited from LinkedBinaryTree
else:
leaf = self._add_left(p, item) # inherited from LinkedBinaryTree
# self._rebalance_insert(leaf) # hook for balanced tree subclasses
def __iter__(self):
"""Generate an iteration of all keys in the map in order."""
p = self.first()
while p is not None:
yield p.key(), p.value()
p = self.after(p)
def delete(self, p):
"""Remove the item at given Position."""
self._validate(p) # inherited from LinkedBinaryTree
if self.left(p) and self.right(p): # p has two children
replacement = self._subtree_last_position(self.left(p))
self._replace(p, replacement.element()) # from LinkedBinaryTree
p = replacement
# now p has at most one child
parent = self.parent(p)
self._delete(p) # inherited from LinkedBinaryTree
# self._rebalance_delete(parent) # if root deleted,parent is None
def __delitem__(self, key):
"""Remove item associated with key k (raise KeyError if not found)."""
if not self.is_empty():
p = self._subtree_search(self.root(), key)
if key == p.key():
self.delete(p) # rely on positional version
return # successful deletion complete
# self._rebalance_access(p) # hook for balanced tree subclasses
raise KeyError("Key Error: " + repr(key))
def _relink(self, parent, child, make_left_child):
"""Relink parent node with child node (we allow child to be None)."""
if make_left_child: # make it a left child
parent._left = child
else: # make it a right child
parent._right = child
if child is not None: # make child point to parent
child._parent = parent
def _rotate(self, p):
"""Rotate Position p above its parent."""
x = p._node
y = x._parent # we assume this exist
z = y._parent # grandparent (possibly None)
if z is None:
self._root = x # x becomes root
x._parent = None
else:
self._relink(z, x, y == z._left) # x becomes a direct child of z
# now rotate x and y ,including transfer of middle subtree
if x == y._left:
self._relink(y, x._right, True) # x._right becomes left child of y
self._relink(x, y, False) # y becomes right child of x
else:
self._relink(y, x._left, False) # x._left becomes right child of y
self._relink(x, y, True) # y becomes left child of x
def _restructure(self, x):
"""Perform trinode restructure of Position x with parent/grandparent."""
y = self.parent(x)
z = self.parent(y)
if (x == self.right(y)) == (y == self.right(z)): # matching alignments
self._rotate(y) # single rotation (of y)
return y
else:
self._rotate(x)
self._rotate(x)
return x # x is new subtree root
def change_redBlackTree(self):
stack = [self.root()]
if __name__ == '__main__':
tree = TreeMap()
array = np.random.randint(0, 100, 10)
name = [str(i) for i in range(10)]
value = list(array)
vote = dict(zip(name, value))
for id in name: # 将所有的用户id放入平衡树
tree[id] = 0
for key,values in vote.items():
tree[key] += values
for val in tree:
print(val)
12.36
import numpy as np
def radix_sort(arr):
i = 0
j = len(str(max(arr)))
while i < j:
bucket = [[] for _ in range(10)]
for val in arr:
bucket[int(val / 10 ** i) % 10].append(val)
arr.clear() # 情况列表方便存入新的数据
for array in bucket:
for value in array:
arr.append(value)
i += 1
return arr
if __name__ == '__main__':
Array = list(np.random.randint(0, 100, 10))
print(Array)
print(radix_sort(Array))
# 由题意,使用非比较排序算法可以达到相应的效果
12.38
def intersection(arr1, arr2):
array1 = set(arr1)
array2 = set(arr2)
return array1 & array2
if __name__ == '__main__':
array1 = [1, 2, 3, 4, 5, 6]
array2 = [2, 3, 4, 5]
print(intersection(array1, array2))
# 参考力扣
# https://leetcode-cn.com/problems/intersection-of-two-arrays/solution/liang-ge-shu-zu-de-jiao-ji-by-leetcode/
# 时间复杂度最好是m+n,最坏是m*n
12.39
import numpy as np
def radix_sort(array):
i = 0
j = len(str(max(array)))
while i < j:
bucket = [[] for _ in range(10)]
for val in array:
bucket[int(val / 10 ** i) % 10].append(val)
array.clear()
for arr in bucket:
for val in arr:
array.append(val)
i += 1
return array
if __name__ == '__main__':
Array = list(np.random.randint(1, 10, 10))
print(Array)
print(radix_sort(Array))
12.40
import numpy as np
def bucket_sort(arr):
if len(arr) < 2:
return arr
max_num = max(arr)
bucket = [0] * (max_num + 1)
for val in arr:
bucket[val] += 1
result = []
for i in range(len(bucket)):
if bucket[i] != 0:
for j in range(bucket[i]):
result.append(i)
return result
if __name__ == '__main__':
array = [list(np.random.randint(0, 100, i)) for i in range(1, 11)]
print(array)
print([bucket_sort(arr) for arr in array])
12.41
import math
import numpy as np
def buildMaxHeap(arr):
for i in range(math.floor(len(arr) / 2), -1, -1): # 减少重构最大堆的循环次数
heapify(arr, i)
pass
def heapify(arr, index):
i = 2 * index + 1
j = 2 * index + 2
target = index
if i < currentLen and arr[i] > arr[target]:
target = i
if j < currentLen and arr[j] > arr[target]:
target = j
if target != index:
arr[target], arr[index] = arr[index], arr[target]
heapify(arr, target)
def heapSort(arr):
global currentLen
currentLen = len(arr) # 全局变量,防止最后更新的时候再次与尾结点一直交换,尾结点是每次更新完后减一
buildMaxHeap(arr)
for i in range(len(arr) - 1, 0, -1):
arr[i], arr[0] = arr[0], arr[i]
currentLen -= 1
heapify(arr, 0)
def is_repeat1(arr):
heapSort(arr)
for i in range(len(arr) - 1):
if arr[i] == arr[i + 1]:
return True
return False
def is_repeat2(arr):
return not len(set(arr)) == len(arr)
if __name__ == '__main__':
array = np.random.randint(1, 20, 10)
# 方法一 先排序在扫描,这样的复杂度为 n*log n
print(is_repeat1(array))
# 再给一个更快的Python拥有的判断函数,将数组放入元组,利用元组中没有重复项的特点进行判断
print(is_repeat2(array))
# 参考力扣
# https://leetcode-cn.com/problems/contains-duplicate/solution/cun-zai-zhong-fu-yuan-su-by-leetcode/
12.42
import numpy as np
def choose_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition(S, left, right):
mid = choose_mid(S, left, right)
pivot = S[mid]
end = right
S[end], S[mid] = S[mid], S[end]
count = 0
while left < right:
while left < right and S[left] <= pivot:
left += 1
while left < right and S[right] >= pivot:
right -= 1
S[left], S[right] = S[right], S[left]
if left != right:
count += 1
S[left], S[end] = S[end], S[left]
if left != end:
count += 1
return count, left
def inPlaceQuickSort(S, left, right):
total = 0
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
count, mid = partition(S, left, right)
total += count
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
print(total)
if __name__ == '__main__':
N = 5
data = list(np.random.randint(1, 100 * N, N))
print(data)
inPlaceQuickSort(data, 0, N - 1)
print(data)
# 只有快速排序这里才是用的交换的操作,我们只对执行了交换并且前项大于后项的书进行统计
12.43
import numpy as np
def choose_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition(S, left, right):
mid = choose_mid(S, left, right)
pivot = S[mid]
end = right
S[end], S[mid] = S[mid], S[end]
count = 0
while left < right:
while left < right and S[left] <= pivot:
left += 1
while left < right and S[right] >= pivot:
right -= 1
S[left], S[right] = S[right], S[left]
if left != right:
count += 1
S[left], S[end] = S[end], S[left]
if left != end:
count += 1
return count, left
def inPlaceQuickSort(S, left, right):
total = 0
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
count, mid = partition(S, left, right)
total += count
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
print(total)
if __name__ == '__main__':
N = 5
data = list(np.random.randint(1, 100 * N, N))
print(data)
inPlaceQuickSort(data, 0, N - 1)
print(data)
# 只有快速排序这里才是用的交换的操作,我们只对执行了交换并且前项大于后项的书进行统计
#基本内容与42一样,42即实现了统计转置,又进行了计数
12.45
import numpy as np
def get_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition(S, left, right):
mid = get_mid(S, left, right) # 三数区中
S[mid], S[right] = S[right], S[mid]
pivot = S[right]
while left < right: # 挖坑法
while left < right and S[left] <= pivot:
left += 1
S[right] = S[left]
while left < right and S[right] >= pivot:
right -= 1
S[left] = S[right]
S[left] = pivot
return left
def quick_sort(S, left, right):
if left < right:
mid = partition(S, left, right)
quick_sort(S, left, mid - 1)
quick_sort(S, mid + 1, right)
def binary_search(S, k):
left = 0
right = len(S) - 1
while left < right:
mid = left + (right - left + 1) // 2
if S[mid] < k:
left = mid + 1
else:
right = mid - 1
if S[left] == k:
return True
else:
return False
def search(S1, S2, k):
for val in S1:
target = k - val
if binary_search(S2, target):
return True
return False
if __name__ == '__main__':
a = list(np.random.randint(1, 10, 10))
b = list(np.random.randint(1, 10, 10))
quick_sort(b, 0, len(b) - 1)
# 要求b为有序,这样我们对b进行搜索的时候时间复杂度为log N
# 又因为a为N,对A中的每一个再b中进行二分搜索,时间复杂度为 N * logN
print(search(a, b, k=10))
12.46
import math
import numpy as np
def radix_sort(S):
if len(S) < 2:
return
i = 0
max_num = max(S)
j = len(str(max_num))
logN = math.log(len(S))
while i < j:
bucket = [[] for _ in range(10)]
for val in S:
bucket[int(val / 10 ** i) % 10].append(val)
S.clear()
for array in bucket:
for val in array:
S.append(val)
i += 1
# 二分查找有序数组
left = 0
right = len(S) - 1
while left < right:
mid = left + (right - left + 1) // 2
if S[mid] < logN:
left = mid
else:
right = mid - 1
if left == 0 or left == len(S) - 1:
if left == 0:
if abs(S[left] - logN) > abs(S[left + 1] - logN):
return S[left + 1]
else:
return S[left]
else:
if abs(S[left] - logN) > abs(S[left - 1] - logN):
return S[left - 1]
else:
return S[left]
else:
if abs(S[left - 1] - logN) > abs(S[left] - logN) > abs(S[left + 1] - logN):
return S[left]
elif abs(S[left] - logN) > abs(S[left - 1] - logN) > abs(S[left + 1] - logN):
return S[left - 1]
else:
return S[left + 1]
if __name__ == '__main__':
array = list(np.random.randint(1, 100, 10))
print(radix_sort(array))
#解题思路为先排序,这里的时间复杂度为n+m 最后是二分搜索 时间复杂度为logN
12.47
import numpy as np
def get_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition(S, left, right):
mid = get_mid(S, left, right) # 三数区中
S[mid], S[right] = S[right], S[mid]
pivot = S[right]
while left < right: # 挖坑法
while left < right and S[left] <= pivot:
left += 1
S[right] = S[left]
while left < right and S[right] >= pivot:
right -= 1
S[left] = S[right]
S[left] = pivot
return left
def quick_sort(S, left, right):
if left < right:
mid = partition(S, left, right)
quick_sort(S, left, mid - 1)
quick_sort(S, mid + 1, right)
if __name__ == '__main__':
data = list(np.random.randint(1, 10, 10))
print(data)
quick_sort(data, 0, len(data) - 1)
print(data)
# 实现了递归的快速排序
12.48
import numpy as np
def quick_sort(S):
n = len(S)
if n < 2:
return
pivot = S[0]
L = [i for i in S if i < pivot]
E = [i for i in S if i == pivot]
G = [i for i in S if i > pivot]
if len(L) > 1:
L = quick_sort(L)
if len(G) > 1:
G = quick_sort(G)
S = L + E + G
return S
if __name__ == '__main__':
data = list(np.random.randint(0, 100, 10))
print(data)
data = quick_sort(data)
print(data)
# 优化了一下递归的时候的数组大小,减少递归次数
12.49
import numpy as np
def get_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition(S, left, right):
mid = get_mid(S, left, right) # 三数区中
S[mid], S[right] = S[right], S[mid]
pivot = S[right]
while left < right: # 挖坑法
while left < right and S[left] <= pivot:
left += 1
S[right] = S[left]
while left < right and S[right] >= pivot:
right -= 1
S[left] = S[right]
S[left] = pivot
return left
def quick_sort(S):
left = 0
right = len(S) - 1
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
mid = partition(S, left, right)
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
if __name__ == '__main__':
data = list(np.random.randint(1, 10, 10))
print(data)
quick_sort(data)
print(data)
# 实现了原地的快速排序
12.50
import numpy as np
def get_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition(S, left, right):
# mid = get_mid(S, left, right) # 三数区中
# S[mid], S[right] = S[right], S[mid]
pivot = S[right] # 这样最快
while left < right:
while left < right and S[left] <= pivot:
left += 1
S[right] = S[left]
while left < right and S[right] >= pivot:
right -= 1
S[left] = S[right]
S[left] = pivot
return left
def quick_sort(S):
left = 0
right = len(S) - 1
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
mid = partition(S, left, right)
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
if __name__ == '__main__':
data = [i for i in range(10)]
# data = list(np.random.randint(1,10,10))
print(data)
quick_sort(data)
print(data)
# 快速排序有序情况下的时间复杂度为n,因为只需要遍历即可
# 快速排序在随机序列的情况下时间复杂度为n*long n,因为需要全部都排序
12.53
def reverse(func):
def wrapper(*args):
args = [i for i in reversed(*args)] # 逆置元组解包后的列表并重新赋值
return func(args)
return wrapper
@reverse
def show(data):
print(data)
pass
if __name__ == '__main__':
array = [i for i in range(10)]
show(array)
# 定义修饰器参考
# https://foofish.net/python-decorator.html
12.56
import time
import numpy as np
def choose_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition1(data, low, high):
mid = choose_mid(data, low, high) # 选择中位数
data[mid], data[high] = data[high], data[mid] # 中位数与最后一位进行换位置
key = data[high]
while low < high: # 挖坑法
while low < high and data[low] <= key:
low += 1
data[high] = data[low]
while low < high and data[high] >= key:
high -= 1
data[low] = data[high]
data[low] = key
return low
def partition2(data, low, high):
mid = choose_mid(data, low, high) # 三数区中
data[mid], data[high] = data[high], data[mid]
key = data[high]
end = high # 记录最后面的位置
while low < high: # 左右指针法
while low < high and data[low] <= key:
low += 1
while low < high and data[high] >= key:
high -= 1
data[low], data[high] = data[high], data[low]
data[low], data[end] = data[end], data[low]
return low
def inPlaceQuickSort(data):
left, right = 0, len(data) - 1
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
mid = partition2(data, left, right)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
def recursive_quick_sort(data, left, right):
if left < right:
partition = partition1(data, left, right)
recursive_quick_sort(data, left, partition - 1)
recursive_quick_sort(data, partition + 1, right)
if __name__ == '__main__':
N = 100000
Array1 = np.random.randint(0, 10000000, N)
Array2 = np.random.randint(0, 10000000, N)
now = time.time()
inPlaceQuickSort(Array1) # 原地非递归
print(f"原地非递归排序大小为{N}的数组花费时间{time.time() - now}")
now = time.time()
recursive_quick_sort(Array2, 0, len(Array2) - 1) # 递归原地
print(f"原地递归排序大小为{N}的数组花费时间{time.time() - now}")
12.57
import time
import numpy as np
def choose_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition1(data, low, high):
mid = choose_mid(data, low, high) # 选择中位数
data[mid], data[high] = data[high], data[mid] # 中位数与最后一位进行换位置
key = data[high]
while low < high: # 挖坑法
while low < high and data[low] <= key:
low += 1
data[high] = data[low]
while low < high and data[high] >= key:
high -= 1
data[low] = data[high]
data[low] = key
return low
def partition2(data, low, high):
mid = choose_mid(data, low, high) # 三数区中
data[mid], data[high] = data[high], data[mid]
key = data[high]
end = high # 记录最后面的位置
while low < high: # 左右指针法
while low < high and data[low] <= key:
low += 1
while low < high and data[high] >= key:
high -= 1
data[low], data[high] = data[high], data[low]
data[low], data[end] = data[end], data[low]
return low
def inPlaceQuickSort(data):
left, right = 0, len(data) - 1
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
mid = partition2(data, left, right)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
def recursive_quick_sort(data, left, right):
if left < right:
partition = partition1(data, left, right)
recursive_quick_sort(data, left, partition - 1)
recursive_quick_sort(data, partition + 1, right)
def quick_sort(data):
n = len(data)
if n < 2:
return data
mid = choose_mid(data, 0, len(data) - 1) # 三数区中
value = data[mid]
data1 = [i for i in data if i < value]
data2 = [i for i in data if i > value]
data3 = [i for i in data if i == value]
data1 = quick_sort(data1)
data2 = quick_sort(data2)
data = data1[:] + data3[:] + data2[:]
return data
if __name__ == '__main__':
N = 100000
# Array1 = np.random.randint(0, 10000000, N)
# Array2 = np.random.randint(0, 10000000, N)
# Array3 = np.random.randint(0, 10000000, N)
# Array4 = np.random.randint(0, 10000000, N)
Array1 = list(range(N))
Array2 = list(range(N))
Array3 = list(range(N))
Array4 = list(range(N))
now = time.time()
inPlaceQuickSort(Array1) # 原地非递归
print(f"原地非递归排序大小为{N}的数组花费时间{time.time() - now}")
now = time.time()
recursive_quick_sort(Array2, 0, len(Array2) - 1) # 递归原地
print(f"原地递归排序大小为{N}的数组花费时间{time.time() - now}")
now = time.time()
quick_sort(Array3) # 递归原地
print(f"原地递归排序大小为{N}的数组花费时间{time.time() - now}")
now = time.time()
np.sort(Array4,kind='quick_sort') # 递归原地
print(f"原地递归排序大小为{N}的数组花费时间{time.time() - now}")
12.58
import time
import numpy as np
def merge(S1, S2, S):
i = j = 0
while (i + j) < len(S):
if j == len(S2) or (i < len(S1) and S1[i] < S2[j]):
S[i + j] = S1[i]
i += 1
else:
S[i + j] = S2[j]
j += 1
def merge_sort(S):
n = len(S)
if n < 2:
return
mid = n // 2
S1 = S[:mid]
S2 = S[mid:n]
merge_sort(S1)
merge_sort(S2)
merge(S1, S2, S)
def partition1(data, left, right):
pivot = data[right]
end = right
while left < right: # 双指针法
while left < right and data[left] <= pivot:
left += 1
while left < right and data[right] >= pivot:
right -= 1
data[left], data[right] = data[right], data[left]
data[left], data[end] = data[end], data[left]
return left
def quicksort(data, left, right):
if left < right:
partition = partition1(data, left, right)
quicksort(data, left, partition - 1)
quicksort(data, partition + 1, right)
if __name__ == '__main__':
N = 100000
data1 = list(np.random.randint(0, 10000000, N))
data2 = list(np.random.randint(0, 10000000, N))
now = time.time()
merge_sort(data1)
print(f"归并排序大小为{N}的数组花费时间{time.time() - now}")
now = time.time()
quicksort(data2, 0, N - 1)
print(f"快速排序大小为{N}的数组花费时间{time.time() - now}")
12.59
import time
import numpy as np
def choose_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition1(S, left, right):
pivot = S[right]
end = right
while left < right:
while left < right and S[left] <= pivot:
left += 1
while left < right and S[right] >= pivot:
right -= 1
S[left], S[right] = S[right], S[left]
S[left], S[end] = S[end], S[left]
return left
def partition2(S, left, right):
temp = np.random.randint(left, right)
pivot = S[temp]
S[temp], S[right] = S[right], S[temp]
end = right
while left < right:
while left < right and S[left] <= pivot:
left += 1
while left < right and S[right] >= pivot:
right -= 1
S[left], S[right] = S[right], S[left]
S[left], S[end] = S[end], S[left]
return left
def partition3(S, left, right):
temp = choose_mid(S, left, right)
pivot = S[temp]
end = right
S[temp],S[end]=S[end],S[temp]
while left < right:
while left < right and S[left] <= pivot:
left += 1
while left < right and S[right] >= pivot:
right -= 1
S[left], S[right] = S[right], S[left]
S[left], S[end] = S[end], S[left]
return left
def quick_sort1(S, left, right):
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
mid = partition1(S, left, right)
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
def quick_sort2(S, left, right):
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
mid = partition2(S, left, right)
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
def quick_sort3(S, left, right):
stack = [left, right]
while len(stack) != 0:
right = stack.pop()
left = stack.pop()
if left < right:
mid = partition3(S, left, right)
if left < mid - 1:
stack.append(left)
stack.append(mid - 1)
if mid + 1 < right:
stack.append(mid + 1)
stack.append(right)
def quick_sort4(S, left, right):
if left < right:
partition = partition1(S, left, right)
quick_sort4(S, left, partition - 1)
quick_sort4(S, partition + 1, right)
def quick_sort5(S, left, right):
if left < right:
partition = partition2(S, left, right)
quick_sort5(S, left, partition - 1)
quick_sort5(S, partition + 1, right)
def quick_sort6(S, left, right):
if left < right:
partition = partition3(S, left, right)
quick_sort6(S, left, partition - 1)
quick_sort6(S, partition + 1, right)
if __name__ == '__main__':
N = 100000
data1 = list(np.random.randint(1, N * 100, N))
data2 = list(np.random.randint(1, N * 100, N))
data3 = list(np.random.randint(1, N * 100, N))
data4 = list(np.random.randint(1, N * 100, N))
data5 = list(np.random.randint(1, N * 100, N))
data6 = list(np.random.randint(1, N * 100, N))
now = time.time()
quick_sort1(data1, 0, N - 1)
print(f"非递归的原地确定化基数的快速排序算法排序大小{N}的数组花费时间{time.time() - now}")
now = time.time()
quick_sort2(data2, 0, N - 1)
print(f"非递归的原地随机化基数的快速排序算法排序大小{N}的数组花费时间{time.time() - now}")
now = time.time()
quick_sort3(data3, 0, N - 1)
print(f"非递归的原地取中点基数的快速排序算法排序大小{N}的数组花费时间{time.time() - now}")
quick_sort4(data4, 0, N - 1)
print(f"递归的原地确定化基数的快速排序算法排序大小{N}的数组花费时间{time.time() - now}")
now = time.time()
quick_sort5(data5, 0, N - 1)
print(f"递归的原地随机化基数的快速排序算法排序大小{N}的数组花费时间{time.time() - now}")
now = time.time()
quick_sort6(data6, 0, N - 1)
print(f"递归的原地取中点基数的快速排序算法排序大小{N}的数组花费时间{time.time() - now}")
12.60
import time
import numpy as np
def inPlaceInsertSort(data):
length = len(data) - 1
i = 0
while i < length:
j = i + 1
while j and data[j] < data[j - 1]:
data[j], data[j - 1] = data[j - 1], data[j]
j -= 1
i += 1
def choose_mid(data, left, right):
mid = left + (right - left) // 2
if data[left] > data[right]:
if data[right] > data[mid]:
return right
elif data[mid] > data[left]:
return left
else:
return mid
else:
if data[mid] < data[left]:
return left
elif data[mid] > data[right]:
return right
else:
return mid
def partition(S, left, right):
mid = choose_mid(S, left, right)
pivot = S[mid]
end = right
S[end], S[mid] = S[mid], S[end]
while left < right:
while left < right and S[left] <= pivot:
left += 1
while left < right and S[right] >= pivot:
right -= 1
S[left], S[right] = S[right], S[left]
S[left], S[end] = S[end], S[left]
return left
def inPlaceQuickSort(S, left, right):
if left < right:
mid = partition(S, left, right)
inPlaceQuickSort(S, left, mid - 1)
inPlaceQuickSort(S, mid + 1, right)
if __name__ == '__main__':
N1 = 1000
data1 = list(np.random.randint(1, 100 * N1, N1))
# data1 = list(range(N1))
N2 = 1000
data2 = list(np.random.randint(1, 100 * N2, N2))
# data2 = list(range(N2))
now = time.time()
inPlaceInsertSort(data1)
print(f"就地插入排序大小为{N1}的数组花费时间{time.time() - now}")
now = time.time()
inPlaceQuickSort(data2, 0, N2 - 1)
print(f"就地快速排序大小为{N2}的数组花费时间{time.time() - now}")
pass
12.61
import numpy as np
def bucket_sort(S):
buckets = [0] * (max(S) + 1)
for i in S:
buckets[i] += 1
sort_nums = []
for j in range(len(buckets)):
if buckets[j] != 0:
for y in range(buckets[j]): # 可能有重复值
sort_nums.append(j)
return sort_nums
if __name__ == '__main__':
array = np.random.randint(0, 1000, 10)
print(array)
print(bucket_sort(array))
到这里,我基本上把我所写的python数据结构的内容全部都发表出来了,在后面的文本处理、图等,对我来说比较难,这不仅仅是我没有写后续代码的原因,更多的原因还是要找工作实习,而实习所需要的是大数据生态下的内容,比如我花了这个暑假学习了Spark的内核,当然我也会在后续的文章中把自己总结的一些技巧和原理发表出来,所以这里Python的数据结构内容暂放一段时间吧,不过前面的都是很基础的东西,也有不少很难的东西,比如红黑树、B树、原地非递归的排序算法,所以呢,数据结构一定要用心,这是进入大厂必不可少的基础!