python数据结构第十二章课后习题答案

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树、原地非递归的排序算法,所以呢,数据结构一定要用心,这是进入大厂必不可少的基础!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北漂的阿狸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值