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

9.5

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


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class UnsortedPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with an unsorted list."""

    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = PositionalList()

    def add(self, key, value):
        """Add a key-value pair."""
        newest = self._Item(key, value)  # make new item instance
        walk = self._data.last()  # walk backward looking for smaller key
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)  # new key is smallest
        else:
            self._data.add_after(walk, newest)  # new goes after walk

    def min(self):
        """Return but do not remove(k,v) tuple with minimum key."""
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        p = self._data.first()
        item = p.element()
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key."""
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data.delete(self._data.first())
        return item._key, item._value

    def __len__(self):
        """Return the number of items in the priotity queue."""
        return len(self._data)


if __name__ == '__main__':
    priorityQueue = UnsortedPriorityQueue()
    priorityQueue.add(1, 2)
    priorityQueue.add(2, 3)
    priorityQueue.add(3, 4)
    print(priorityQueue.min())

9.6

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


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class UnsortedPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with an unsorted list."""

    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = PositionalList()

    def add(self, key, value):
        """Add a key-value pair."""
        newest = self._Item(key, value)  # make new item instance
        walk = self._data.last()  # walk backward looking for smaller key
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)  # new key is smallest
        else:
            self._data.add_after(walk, newest)  # new goes after walk

    def min(self):
        """Return but do not remove(k,v) tuple with minimum key."""
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        p = self._data.first()
        item = p.element()
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key."""
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data.delete(self._data.first())
        return item._key, item._value

    def __len__(self):
        """Return the number of items in the priotity queue."""
        return len(self._data)


if __name__ == '__main__':
    priorityQueue = UnsortedPriorityQueue()
    priorityQueue.add(1, 2)
    priorityQueue.add(2, 3)
    priorityQueue.add(3, 4)
    priorityQueue.add(4, 5)
    priorityQueue.add(5, 6)
    print(priorityQueue.min())

9.12

class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with a binary heap."""

    # --------------------nonpublic behaviors ----------------------------
    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < len(self._data)  # index beyond end of list?

    def _has_right(self, j):
        return self._right(j) < len(self._data)  # index beyond end of list?

    def _swap(self, i, j):
        """Swap the elements at indices i and j of array."""
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _upheap(self, j):
        parent = self._parent(j)
        if j > 0 and self._data[j] > self._data[parent]:
            self._swap(j, parent)
            self._upheap(parent)  # recur at position of parent

    def _downheap(self, j):
        if self._has_left(j):
            left = self._left(j)
            small_child = left  # although right may by smaller
            if self._has_right(j):
                right = self._right(j)
                if self._data[right] > self._data[left]:
                    small_child = right
            if self._data[small_child] > self._data[j]:
                self._swap(j, small_child)
                self._downheap(small_child)  # recur at position of small child

    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = []

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        self._data.append(self._Item(key, value))
        self._upheap(len(self._data) - 1)  # upheap newly added position

    def min(self):
        """Return but do not remove (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_max(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._downheap(0)
        return item._key, item._value

    def __str__(self):
        temp = []
        for data in self._data:
            temp.append(data._key)
        return str(temp)


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(1, 10)
    priorityQueue.add(3, 5)
    priorityQueue.add(4, 12)
    priorityQueue.add(2, 7)
    priorityQueue.add(5, 4)
    priorityQueue.add(7, 1)
    priorityQueue.add(6, 2)
    priorityQueue.add(9, 3)
    priorityQueue.add(8, 8)
    print(priorityQueue)
    print(priorityQueue.remove_max())
    print(priorityQueue)
    print(priorityQueue.remove_max())
    print(priorityQueue)
    print(priorityQueue.remove_max())
    print(priorityQueue)
    print(priorityQueue.remove_max())
    print(priorityQueue)
    print(priorityQueue.remove_max())
    print(priorityQueue)
    print(priorityQueue.remove_max())
    print(priorityQueue)
    print(priorityQueue.remove_max())
    print(priorityQueue)
    print(priorityQueue.remove_max())
    print(priorityQueue)

9.26

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


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

        def __cmp__(self, other):
            return self._key == other.key

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class SortedPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with a sorted list."""

    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = PositionalList()

    def __len__(self):
        """Return the number of items in the priotity queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair."""
        newest = self._Item(key, value)  # make new item instance
        walk = self._data.last()  # walk backward looking for smaller key
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)  # new key is smallest
        else:
            self._data.add_after(walk, newest)  # new goes after walk

    def min(self):
        """Return but do not remove(k,v) tuple with minimum key."""
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        p = self._data.first()
        item = p.element()
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key."""
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data.delete(self._data.first())
        return item._key, item._value

    def replace(self, key, value):
        walk = self._data.first()
        while walk is not None:
            if walk == key:
                walk._value = value
                break
            walk = self._data.after(walk)
        else:
            return None


class AdaptHeapPriorityQueue:

    def __init__(self):
        self._data = SortedPriorityQueue()
        self._index = 0

    def __len__(self):
        return self._index

    def push(self, key, value):
        # 默认从小到大排列,如果需要从大到小,那么key取负数
        self._data.add(key, value)
        self._index += 1

    def pop(self):
        if self._index == 0:
            raise IndexError
        self._index -= 1
        return self._data.remove_min()

    def replace(self, key, value):
        self._data._replace(key, value)


if __name__ == "__main__":
    Heap = AdaptHeapPriorityQueue()
    Heap.push(4, 1)
    Heap.push(1, 0)
    Heap.push(2, 1)
    Heap.push(3, 2)
    print(Heap.pop())
    print(Heap.pop())
    print(Heap.pop())

9.27

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


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

        def __cmp__(self, other):
            return self._key == other.key

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class SortedPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with a sorted list."""

    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = PositionalList()

    def __len__(self):
        """Return the number of items in the priotity queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair."""
        newest = self._Item(key, value)  # make new item instance
        walk = self._data.last()  # walk backward looking for smaller key
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)  # new key is smallest
        else:
            self._data.add_after(walk, newest)  # new goes after walk

    def min(self):
        """Return but do not remove(k,v) tuple with minimum key."""
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        p = self._data.first()
        item = p.element()
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key."""
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data.delete(self._data.first())
        return item._key, item._value

    def replace(self, key, value):
        walk = self._data.first()
        while walk is not None:
            if walk == key:
                walk._value = value
                break
            walk = self._data.after(walk)
        else:
            return None


class FIFOQueue:

    def __init__(self):
        self._data = SortedPriorityQueue()
        self._index = 0

    def __len__(self):
        return self._index

    def push(self, value):
        # 默认从小到大排列,如果需要从大到小,那么key取负数
        self._data.add(self._index, value)
        self._index += 1

    def pop(self):
        if self._index == 0:
            raise IndexError
        self._index -= 1
        return self._data.remove_min()

    def replace(self, key, value):
        self._data._replace(key,value)


if __name__ == "__main__":
    Fifoqueue = FIFOQueue()
    Fifoqueue.push(1)
    Fifoqueue.push(0)
    Fifoqueue.push(1)
    Fifoqueue.push(2)
    print(Fifoqueue.pop())
    print(Fifoqueue.pop())
    print(Fifoqueue.pop())

9.29

class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

        def __cmp__(self, other):
            return self._key == other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class SortedPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority implemented with a sorted list."""

    def __init__(self):
        self._data = []

    def __len__(self):
        return len(self._data)

    def is_empty(self):
        return len(self._data) == 0

    def add(self, key, value):
        Item = self._Item(key, value)
        if self.is_empty():
            self._data.append(Item)
        else:
            walk = 0
            while walk < len(self._data):
                if self._data[walk] < Item:
                    break
                walk += 1
            self._data = self._data[:walk] + [Item] + self._data[walk:]

    def min(self):
        return self._data[-1]._key, self._data[-1]._value

    def remove_min(self):
        if len(self._data) == 0:
            raise Empty
        temp = self._data.pop()
        return temp._key, temp._value


if __name__ == "__main__":
    priorityQueue = SortedPriorityQueue()
    priorityQueue.add(6, 1)
    priorityQueue.add(2, 2)
    priorityQueue.add(1, 2)
    priorityQueue.add(3, 2)
    priorityQueue.add(9, 2)
    print(priorityQueue.min())

9.30

class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with a binary heap."""

    # --------------------nonpublic behaviors ----------------------------
    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < len(self._data)  # index beyond end of list?

    def _has_right(self, j):
        return self._right(j) < len(self._data)  # index beyond end of list?

    def _swap(self, i, j):
        """Swap the elements at indices i and j of array."""
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _upheap(self, j):
        now = j
        parent = self._parent(j)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        if self._has_left(j):
            left = self._left(j)
            small_child = left  # although right may by smaller
            if self._has_right(j):
                right = self._right(j)
                if self._data[right] < self._data[left]:
                    small_child = right
            if self._data[small_child] < self._data[j]:
                self._swap(j, small_child)
                self._downheap(small_child)  # recur at position of small child

    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = []

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        self._data.append(self._Item(key, value))
        self._upheap(len(self._data) - 1)  # upheap newly added position

    def min(self):
        """Return but do not remove (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._downheap(0)
        return item._key, item._value


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(2, 3)
    priorityQueue.add(1, 2)
    priorityQueue.add(4, 3)
    priorityQueue.add(3, 3)
    priorityQueue.add(5, 4)
    print(priorityQueue.min())

9.31

class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with a binary heap."""

    # --------------------nonpublic behaviors ----------------------------
    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < len(self._data)  # index beyond end of list?

    def _has_right(self, j):
        return self._right(j) < len(self._data)  # index beyond end of list?

    def _swap(self, i, j):
        """Swap the elements at indices i and j of array."""
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _upheap(self, j):
        now = j
        parent = self._parent(j)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        while True:
            if self._has_left(now):
                left = self._left(now)
                small_child = left  # although right may by smaller
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
                    continue
            break

    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = []

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        self._data.append(self._Item(key, value))
        self._upheap(len(self._data) - 1)  # upheap newly added position

    def min(self):
        """Return but do not remove (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._downheap(0)
        return item._key, item._value


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(2, 3)
    priorityQueue.add(1, 2)
    priorityQueue.add(4, 3)
    priorityQueue.add(3, 3)
    priorityQueue.add(5, 4)
    print(priorityQueue.remove_min())

9.32

class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        while True:
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
                    continue
            break

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def last(self):
        return self._trailer._key, self._trailer._value


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(2, 3)
    print(priorityQueue.last())
    priorityQueue.add(1, 2)
    print(priorityQueue.last())
    priorityQueue.add(4, 3)
    print(priorityQueue.last())
    priorityQueue.add(3, 3)
    print(priorityQueue.last())
    priorityQueue.add(5, 4)
    print(priorityQueue.last())

9.33

from collections import deque


class Empty(Exception):
    pass


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):
        """ An abstraction representing the location of a single element."""

        def __init__(self, container, node):
            """Constructor should not be invoked by yser."""
            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 _set_root(self, node):
        node = self._validate(node)
        self._root = node
        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

    def _swap(self, p, q):
        node_p = self._validate(p)
        node_q = self._validate(q)
        node_p_parent = node_p._parent
        node_q_parent = node_q._parent
        node_p_left = node_p._left
        node_p_right = node_p._right
        node_q_left = node_q._left
        node_q_right = node_q._right
        node_p._parent = node_q_parent if node_q_parent != node_p else node_q
        node_q._parent = node_p_parent if node_p_parent != node_q else node_p
        node_p._left = node_q_left if node_q_left != node_p else node_q
        try:
            if node_p_left != node_q:
                node_p_left._parent = node_q
        except Exception:
            pass
        node_p._right = node_q_right if node_q_right != node_p else node_q
        try:
            if node_p_right != node_q:
                node_p_right._parent = node_q
        except Exception:
            pass
        node_q._left = node_p_left if node_p_left != node_q else node_p
        try:
            if node_q_left != node_p:
                node_q_left._parent = node_p
        except Exception:
            pass
        node_q._right = node_p_right if node_p_right != node_q else node_p
        try:
            if node_q_right != node_p:
                node_q_right._parent = node_p
        except Exception:
            pass
        try:
            if node_p_parent is None or node_q_parent is None:
                if node_p_parent is None:
                    if node_q_parent is None:
                        pass
                    else:
                        self._root = node_q
                        if node_p_left == node_q:
                            node_q._left = node_p
                        elif node_p_right == node_q:
                            node_q._right = node_p
                        else:
                            pass
                else:
                    self._root = node_p
                    if node_q_left == node_p:
                        node_p._left = node_q
                    elif node_q_right == node_p:
                        node_p._right = node_q
                    else:
                        pass
            try:
                if node_p_parent._left is node_p and node_p_parent is not node_q:
                    node_p_parent._left = node_q
                elif node_p_parent._right is node_p and node_p_parent is not node_q:
                    node_p_parent._right = node_q
                else:
                    pass
            except Exception:
                pass
            try:
                if node_q_parent._left is node_q and node_q_parent is not node_p:
                    node_q_parent._left = node_p
                elif node_q_parent._right is node_q:
                    node_q_parent._right = node_p
                else:
                    pass
            except Exception:
                pass
        except Exception:
            pass


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = LinkedBinaryTree()
        self._trailer = None

    def __iter__(self):
        data = deque()
        root = self._data.root()
        data.append(root)
        while len(data) != 0:
            node = data.popleft()
            yield node
            for child in self._data.children(node):
                data.append(child)

    def _parent(self, p):
        return self._data.parent(p)

    def _left(self, p):
        return self._data.left(p)

    def _right(self, p):
        return self._data.right(p)

    def _has_left(self, p):
        return self._left(p) is not None

    def _has_right(self, p):
        return self._right(p) is not None

    def _uphead(self, p):
        now = p
        parent = self._parent(now)
        while parent is not None and now is not None:
            if now.element() < parent.element():
                if now.element() is self._trailer.element():
                    self._trailer = parent
                self._data._swap(now, parent)
                parent = self._parent(now)
            else:
                now = parent
                parent = self._parent(now)

    def _downheap(self, p):
        now = p
        while True:
            if self._data.left(now) is not None:
                left = self._data.left(now)
                small_child = left
                if self._data.right(now) is not None:
                    right = self._data.right(now)
                    if right.element() < left.element():
                        small_child = right
                if small_child.element() < now.element():
                    if now.element() is self._trailer.element():
                        self._trailer = now
                    self._data._swap(now, small_child)
                    continue
            break

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def _push_node_position(self):
        """确定插入的父节点"""
        root = self._data.root()
        if root is None:
            raise Empty("root is None")
        data = deque()
        data.append(root)
        while True:  # 使用队列来找父节点
            node = data.popleft()
            if self._data.num_children(node) != 2:
                return node
            for child in self._data.children(node):
                data.append(child)

    def _update_trailer(self):
        """更新尾结点用来做删除操作"""
        root = self._data.root()
        if root is None:
            raise Empty("root is None")
        data = deque()
        temp = [root]
        data.append(root)
        while len(data) != 0:  # 使用队列来找父节点
            node = data.popleft()
            for child in self._data.children(node):
                data.append(child)
                temp.append(child)
        if len(data) == 1:
            self._trailer = root
        else:
            self._trailer = temp[-1]

        pass

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        if self._data.root() is None:
            self._data._add_root(items)
            self._trailer = self._data.root()
        else:
            get_node = self._push_node_position()  # 申明这里的时间复杂度不是(1)是(n)
            if self._data.left(get_node) is None:
                self._data._add_left(get_node, items)
                self._trailer = self._data.left(get_node)
            else:
                self._data._add_right(get_node, items)
                self._trailer = self._data.right(get_node)
            self._uphead(self._trailer)

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        return self._trailer.element()._key, self._trailer.element()._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        root = self._data.root()
        self._data._swap(root, self._trailer)  # 交换到最后一个位置
        self._data._delete(root)  # 从尾巴删掉
        self._update_trailer()  # 更新尾结点
        self._downheap(self._data.root())  # 向下更新
        return root.element()._key, root.element()._value


if __name__ == '__main__':
    heapPriorityQueue = HeapPriorityQueue()
    heapPriorityQueue.add(7, 7)
    heapPriorityQueue.add(2, 8)
    heapPriorityQueue.add(3, 7)
    heapPriorityQueue.add(1, 9)
    heapPriorityQueue.add(5, 7)
    heapPriorityQueue.add(6, 7)
    print(heapPriorityQueue.remove_min())
    for node in heapPriorityQueue:
        print(node.element()._key, node.element()._value)
    pass

9.34

from collections import deque


class Empty(Exception):
    pass


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):
        """ An abstraction representing the location of a single element."""

        def __init__(self, container, node):
            """Constructor should not be invoked by yser."""
            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 _set_root(self, node):
        node = self._validate(node)
        self._root = node
        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

    def _swap(self, p, q):
        node_p = self._validate(p)
        node_q = self._validate(q)
        node_p_parent = node_p._parent
        node_q_parent = node_q._parent
        node_p_left = node_p._left
        node_p_right = node_p._right
        node_q_left = node_q._left
        node_q_right = node_q._right
        node_p._parent = node_q_parent if node_q_parent != node_p else node_q
        node_q._parent = node_p_parent if node_p_parent != node_q else node_p
        node_p._left = node_q_left if node_q_left != node_p else node_q
        try:
            if node_p_left != node_q:
                node_p_left._parent = node_q
        except Exception:
            pass
        node_p._right = node_q_right if node_q_right != node_p else node_q
        try:
            if node_p_right != node_q:
                node_p_right._parent = node_q
        except Exception:
            pass
        node_q._left = node_p_left if node_p_left != node_q else node_p
        try:
            if node_q_left != node_p:
                node_q_left._parent = node_p
        except Exception:
            pass
        node_q._right = node_p_right if node_p_right != node_q else node_p
        try:
            if node_q_right != node_p:
                node_q_right._parent = node_p
        except Exception:
            pass
        try:
            if node_p_parent is None or node_q_parent is None:
                if node_p_parent is None:
                    if node_q_parent is None:
                        pass
                    else:
                        self._root = node_q
                        if node_p_left == node_q:
                            node_q._left = node_p
                        elif node_p_right == node_q:
                            node_q._right = node_p
                        else:
                            pass
                else:
                    self._root = node_p
                    if node_q_left == node_p:
                        node_p._left = node_q
                    elif node_q_right == node_p:
                        node_p._right = node_q
                    else:
                        pass
            try:
                if node_p_parent._left is node_p and node_p_parent is not node_q:
                    node_p_parent._left = node_q
                elif node_p_parent._right is node_p and node_p_parent is not node_q:
                    node_p_parent._right = node_q
                else:
                    pass
            except Exception:
                pass
            try:
                if node_q_parent._left is node_q and node_q_parent is not node_p:
                    node_q_parent._left = node_p
                elif node_q_parent._right is node_q:
                    node_q_parent._right = node_p
                else:
                    pass
            except Exception:
                pass
        except Exception:
            pass

    def last(self):
        root = self.root()
        depth = 0
        while root is not None:
            root = self.left(root)
            depth += 1
        root = self.root()
        level = 0
        path = ""  # path 用来记录路线
        while root is not None:
            now_node = root
            level += 1
            # 判断是否有右孩子
            if level == depth:
                break
            if self.right(now_node) is not None:
                current_node = self.right(now_node)
                tempdepth = level + 1  # 临时深度,用来判断是否与最大深度一致
                parent = current_node  # 用来记录最左边节点的父节点
                temppath = ""
                while self.left(current_node) is not None:
                    tempdepth += 1
                    parent = current_node
                    current_node = self.left(current_node)
                    temppath = temppath[:] + "0"
                if tempdepth < depth:
                    # 只要当前深度小于最大深度,
                    # 说明该位置不对,应该在当前节点的起点往左走而不是由走
                    root = self.left(root)
                    path = path[:] + "0"
                elif self.right(parent) is None and tempdepth == depth:
                    # 如果循环到最大位置处是,该深度与树的最大深度一致则返回
                    if temppath is not None:
                        return path[:] + "1" + temppath[:]
                    else:
                        return path[:] + "1"
                else:
                    # 上诉所有不满足者即有可能有右孩子,从root右孩子继续遍历
                    root = self.right(root)
                    path = path[:] + "1"
            else:
                # 没有就进入左孩子
                root = self.left(root)
                path = path[:] + "0"
        return path


if __name__ == "__main__":
    tree = LinkedBinaryTree()
    tree._add_root(1)
    tree._add_left(tree.root(), 2)
    tree._add_right(tree.root(), 3)
    tree._add_left(tree.left(tree.root()), 4)
    tree._add_right(tree.left(tree.root()), 5)
    tree._add_left(tree.right(tree.root()), 6)
    tree._add_right(tree.right(tree.root()), 7)
    tree._add_left(tree.left(tree.left(tree.root())), 8)
    tree._add_right(tree.left(tree.left(tree.root())), 9)
    tree._add_left(tree.right(tree.left(tree.root())), 10)
    tree._add_right(tree.right(tree.left(tree.root())), 11)
    tree._add_left(tree.left(tree.right(tree.root())), 12)
    tree._add_right(tree.left(tree.right(tree.root())), 13)
    print(tree.last())

9.35

from collections import deque


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(2, 'B')
    priorityQueue.add(4, "C")
    priorityQueue.add(5, "A")
    priorityQueue.add(9, "F")
    priorityQueue.add(15, "K")
    priorityQueue.add(6, "Z")
    priorityQueue.add(7, "Q")
    priorityQueue.add(25, "J")
    priorityQueue.add(16, "X")
    priorityQueue.add(12, "H")
    priorityQueue.add(14, "E")
    priorityQueue.add(8, "W")
    priorityQueue.add(20, "B")
    priorityQueue.add(11, "S")
    priorityQueue.add(10, "L")
    print(priorityQueue.find_all_min(7))

9.38

from collections import deque


class Empty(Exception):
    pass


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):
        """ An abstraction representing the location of a single element."""

        def __init__(self, container, node):
            """Constructor should not be invoked by yser."""
            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 _set_root(self, node):
        node = self._validate(node)
        self._root = node
        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
        return node

    def _swap(self, p, q):
        node_p = self._validate(p)
        node_q = self._validate(q)
        node_p_parent = node_p._parent
        node_q_parent = node_q._parent
        node_p_left = node_p._left
        node_p_right = node_p._right
        node_q_left = node_q._left
        node_q_right = node_q._right
        node_p._parent = node_q_parent if node_q_parent != node_p else node_q
        node_q._parent = node_p_parent if node_p_parent != node_q else node_p
        node_p._left = node_q_left if node_q_left != node_p else node_q
        try:
            if node_p_left is not node_q:
                node_p_left._parent = node_q
        except Exception:
            pass
        node_p._right = node_q_right if node_q_right != node_p else node_q
        try:
            if node_p_right is not node_q:
                node_p_right._parent = node_q
        except Exception:
            pass
        node_q._left = node_p_left if node_p_left != node_q else node_p
        try:
            if node_q_left is not node_p:
                node_q_left._parent = node_p
        except Exception:
            pass
        node_q._right = node_p_right if node_p_right != node_q else node_p
        try:
            if node_q_right is not node_p:
                node_q_right._parent = node_p
        except Exception:
            pass
        try:
            if node_p_parent is None or node_q_parent is None:
                if node_p_parent is None:
                    if node_q_parent is None:
                        pass
                    else:
                        self._root = node_q
                        if node_p_left == node_q:
                            node_q._left = node_p
                        elif node_p_right == node_q:
                            node_q._right = node_p
                        else:
                            pass
                else:
                    self._root = node_p
                    if node_q_left == node_p:
                        node_p._left = node_q
                    elif node_q_right == node_p:
                        node_p._right = node_q
                    else:
                        pass
            try:
                if node_p_parent._left is node_p and node_p_parent is not node_q:
                    node_p_parent._left = node_q
                elif node_p_parent._right is node_p and node_p_parent is not node_q:
                    node_p_parent._right = node_q
                else:
                    pass
            except Exception:
                pass
            try:
                if node_q_parent._left is node_q and node_q_parent is not node_p:
                    node_q_parent._left = node_p
                elif node_q_parent._right is node_q:
                    node_q_parent._right = node_p
                else:
                    pass
            except Exception:
                pass
        except Exception:
            pass


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = LinkedBinaryTree()
        self._trailer = None

    def __iter__(self):
        data = deque()
        root = self._data.root()
        data.append(root)
        while len(data) != 0:
            node = data.popleft()
            yield node
            for child in self._data.children(node):
                data.append(child)

    def _parent(self, p):
        return self._data.parent(p)

    def _left(self, p):
        return self._data.left(p)

    def _right(self, p):
        return self._data.right(p)

    def _has_left(self, p):
        return self._left(p) is not None

    def _has_right(self, p):
        return self._right(p) is not None

    def _uphead(self, p):
        now = p
        parent = self._parent(now)
        while parent is not None and now is not None:
            if now.element() < parent.element():
                if now.element() is self._trailer.element():
                    self._trailer = parent
                self._data._swap(now, parent)
                parent = self._parent(now)
            else:
                now = parent
                parent = self._parent(now)

    def _downheap(self, p):
        now = p
        while True:
            if self._data.left(now) is not None:
                left = self._data.left(now)
                small_child = left
                if self._data.right(now) is not None:
                    right = self._data.right(now)
                    if right.element() < left.element():
                        small_child = right
                if small_child.element() < now.element():
                    if now.element() is self._trailer.element():
                        self._trailer = now
                    self._data._swap(now, small_child)
                    continue
            break

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def _push_node_position(self):
        """确定插入的父节点"""
        root = self._data.root()
        if root is None:
            raise Empty("root is None")
        data = deque()
        data.append(root)
        while True:  # 使用队列来找父节点
            node = data.popleft()
            if self._data.num_children(node) != 2:
                return node
            for child in self._data.children(node):
                data.append(child)

    def _update_trailer(self):
        """更新尾结点用来做删除操作"""
        root = self._data.root()
        if root is None:
            raise Empty("root is None")
        data = deque()
        temp = [root]
        data.append(root)
        while len(data) != 0:  # 使用队列来找父节点
            node = data.popleft()
            for child in self._data.children(node):
                data.append(child)
                temp.append(child)
        if len(data) == 1:
            self._trailer = root
        else:
            self._trailer = temp[-1]

        pass

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        if self._data.root() is None:
            self._data._add_root(items)
            self._trailer = self._data.root()
        else:
            get_node = self._push_node_position()  # 申明这里的时间复杂度不是(1)是(n)
            if self._data.left(get_node) is None:
                self._data._add_left(get_node, items)
                self._trailer = self._data.left(get_node)
            else:
                self._data._add_right(get_node, items)
                self._trailer = self._data.right(get_node)
            self._uphead(self._trailer)

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        return self._trailer.element()._key, self._trailer.element()._value

    def remove_min(self, position=False):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        root = self._data.root()
        self._data._swap(root, self._trailer)  # 交换到最后一个位置
        self._data._delete(root)  # 从尾巴删掉
        self._update_trailer()  # 更新尾结点
        self._downheap(self._data.root())  # 向下更新
        if position:
            return root
        else:
            return root.element()._key, root.element()._value

    def attch(self, heap):
        root = self._data.root()
        self._data._swap(root, self._trailer)  # 交换到最后一个位置
        if root._node is root._node._parent._left:
            root._node._parent._left = None
        else:
            root._node._parent._right = None
        self._update_trailer()  # 更新尾结点
        self._downheap(self._data.root())  # 向下更新
        root._node._left = self._data._root
        root._node._right = heap._data._root
        self._data._root = root._node
        self._update_trailer()  # 更新尾结点
        self._downheap(self._data.root())  # 向下更新


if __name__ == '__main__':
    heapPriorityQueue1 = HeapPriorityQueue()
    heapPriorityQueue2 = HeapPriorityQueue()
    heapPriorityQueue1.add(7, 7)
    heapPriorityQueue1.add(2, 8)
    heapPriorityQueue1.add(3, 7)
    heapPriorityQueue1.add(1, 9)
    heapPriorityQueue1.add(5, 7)
    heapPriorityQueue1.add(6, 7)
    heapPriorityQueue2.add(1, 2)
    heapPriorityQueue2.add(5, 2)
    heapPriorityQueue2.add(2, 2)
    heapPriorityQueue2.add(3, 2)
    heapPriorityQueue1.attch(heapPriorityQueue2)
    for node in heapPriorityQueue1:
        print(node.element()._key, node.element()._value)
    pass

9.39

from collections import deque


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)

    def heappushpop(self, key, value):
        nowKey, nowValue = self.min()
        items = self._Item(key, value)
        if nowKey < key:
            self._data = [items] + self._data[:]
            self._trailer = self._data[-1]
            return nowKey
        else:
            pop = self._data[0]
            self._data[0] = items
            return pop._key, pop._value


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(2, 'B')
    priorityQueue.add(4, "C")
    priorityQueue.add(5, "A")
    priorityQueue.add(9, "F")
    priorityQueue.add(15, "K")
    priorityQueue.add(6, "Z")
    priorityQueue.add(7, "Q")
    priorityQueue.add(25, "J")
    priorityQueue.add(16, "X")
    priorityQueue.add(12, "H")
    priorityQueue.add(14, "E")
    priorityQueue.add(8, "W")
    priorityQueue.add(20, "B")
    priorityQueue.add(11, "S")
    priorityQueue.add(10, "L")
    print(priorityQueue.remove_min())
    print(priorityQueue.heappushpop(1, 'A'))

9.40

from collections import deque


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)

    def heappushpop(self, key, value):
        nowKey, nowValue = self.min()
        items = self._Item(key, value)
        if nowKey < key:
            self._data = [items] + self._data[:]
            self._trailer = self._data[-1]
            return nowKey
        else:
            pop = self._data[0]
            self._data[0] = items
            return pop._key, pop._value

    def heapreplace(self, key, value):
        items = self._Item(key, value)
        pop = self._data[0]
        self._data[0] = items
        return pop._key, pop._value
        pass


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(2, 'B')
    priorityQueue.add(4, "C")
    priorityQueue.add(5, "A")
    priorityQueue.add(9, "F")
    priorityQueue.add(15, "K")
    priorityQueue.add(6, "Z")
    priorityQueue.add(7, "Q")
    priorityQueue.add(25, "J")
    priorityQueue.add(16, "X")
    priorityQueue.add(12, "H")
    priorityQueue.add(14, "E")
    priorityQueue.add(8, "W")
    priorityQueue.add(20, "B")
    priorityQueue.add(11, "S")
    priorityQueue.add(10, "L")
    print(priorityQueue.heappushpop(1, 'A'))
    print(priorityQueue.heapreplace(11, '22'))

9.41

import math
from collections import deque


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self, N):
        self._data = []
        self._n = 0
        self._trailer = None
        self._log = math.log(N, 2)

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        if self._n < self._log:
            self._data.append(items)
            self._n += 1
            self._uphead(self._n - 1)
            self._trailer = self._data[-1]
        else:
            if key > self.min():
                self._data[0] = items
                self._downheap(0)

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._n -= 1
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)

    def heappushpop(self, key, value):
        nowKey, nowValue = self.min()
        items = self._Item(key, value)
        if nowKey < key:
            self._data = [items] + self._data[:]
            self._trailer = self._data[-1]
            return nowKey
        else:
            pop = self._data[0]
            self._data[0] = items
            return pop._key, pop._value

    def heapreplace(self, key, value):
        items = self._Item(key, value)
        pop = self._data[0]
        self._data[0] = items
        return pop._key, pop._value
        pass


def top():
    pass


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue(N=16)
    priorityQueue.add(2, 'B')
    priorityQueue.add(4, "C")
    priorityQueue.add(5, "A")
    priorityQueue.add(11, "F")
    priorityQueue.add(917, "F")
    priorityQueue.add(23, "F")
    priorityQueue.add(76, "F")
    priorityQueue.add(34, "F")
    priorityQueue.add(29, "F")
    priorityQueue.add(87, "F")
    priorityQueue.add(65, "F")
    priorityQueue.add(12, "F")
    print(priorityQueue)

9.44

import math
from collections import deque


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._n -= 1
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)

    def heappushpop(self, key, value):
        nowKey, nowValue = self.min()
        items = self._Item(key, value)
        if nowKey < key:
            self._data = [items] + self._data[:]
            self._trailer = self._data[-1]
            return nowKey
        else:
            pop = self._data[0]
            self._data[0] = items
            return pop._key, pop._value

    def heapreplace(self, key, value):
        items = self._Item(key, value)
        pop = self._data[0]
        self._data[0] = items
        return pop._key, pop._value
        pass

    def top(self, ):
        temp = []
        for i in range(int(math.log(self._n))):
            temp.append(self.remove_min())
        return temp


class MaxPriorityQueue(HeapPriorityQueue):
    """A locator-based priority queue implemented with  a binary heap."""

    def add(self, key, value):
        self._data.append(self._Item((-1) * key, value))
        self._uphead(len(self._data) - 1)
        self._n += 1

    def min(self):
        if self.is_empty():
            raise Empty("Priority queue is empty")
        item = self._data[0]
        return item._key * (-1), item._value

    def remove_min(self):
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._n -= 1
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key * (-1), item._value


if __name__ == '__main__':
    maxPriorityQueue = MaxPriorityQueue()
    maxPriorityQueue.add(2, 'B')
    maxPriorityQueue.add(4, "C")
    maxPriorityQueue.add(5, "A")
    maxPriorityQueue.add(9, "F")
    maxPriorityQueue.add(15, "K")
    maxPriorityQueue.add(6, "Z")
    maxPriorityQueue.add(7, "Q")
    print(maxPriorityQueue.remove_min())

9.45

def count_bits(k):
    numOnes = 0
    temp = k
    while temp != 0:
        bit = temp & 1
        if bit == 1:
            numOnes += 1
        temp = temp >> 1
    return numOnes


def binaryNumber(number):
    """把原来的数字与减一后的值做与运算,只要当前值的最右边为1,
    做完与运算后,该位置就会变成0,依次类推"""
    count = 0
    while number != 0:
        count += 1
        number = number & number - 1
    return count
    pass


if __name__ == '__main__':
    print(count_bits(15))
    print(binaryNumber(15))

9.46

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


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue"""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = '_key', "_value"

        def __init__(self, k, v):
            self._key = k
            self._value = v

        def __lt__(self, other):
            return self._key < other._key  # compare items based on their keys

    def is_empty(self):
        """Return True if the priority queue is empty"""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with a binary heap."""

    # --------------------nonpublic behaviors ----------------------------
    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < len(self._data)  # index beyond end of list?

    def _has_right(self, j):
        return self._right(j) < len(self._data)  # index beyond end of list?

    def _swap(self, i, j):
        """Swap the elements at indices i and j of array."""
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _upheap(self, j):
        parent = self._parent(j)
        if j > 0 and self._data[j] < self._data[parent]:
            self._swap(j, parent)
            self._upheap(parent)  # recur at position of parent

    def _downheap(self, j):
        if self._has_left(j):
            left = self._left(j)
            small_child = left  # although right may by smaller
            if self._has_right(j):
                right = self._right(j)
                if self._data[right] < self._data[left]:
                    small_child = right
            if self._data[small_child] < self._data[j]:
                self._swap(j, small_child)
                self._downheap(small_child)  # recur at position of small child

    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = []

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        self._data.append(self._Item(key, value))
        self._upheap(len(self._data) - 1)  # upheap newly added position

    def min(self):
        """Return but do not remove (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._downheap(0)
        return item._key, item._value


def pq_sort(C):
    """Sort a collection of elements stored in a positional list."""
    n = len(C)
    P = HeapPriorityQueue
    for j in range(n):
        element = C.delete(C.first())
        P.add(int(str(element)), int(str(element)))  # use element as key and value
        for j in range(n):
            k, v = P.remove_min()
        C.add_last(v)  # store smallest remaining element in C


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(2, 'B')
    priorityQueue.add(4, "C")
    priorityQueue.add(5, "A")
    priorityQueue.add(9, "F")
    priorityQueue.add(15, "K")
    priorityQueue.add(6, "Z")
    priorityQueue.add(7, "Q")

9.47

import numpy as np


def pickSort(data):
    for i in range(len(data)):
        min = i
        for j in range(i+1,len(data)):
            if data[j] < data[min]:
                min = j
        data[i],data[min] = data[min],data[i]
    return data


if __name__ == '__main__':
    target = np.random.randint(0,100,size=10)
    print(pickSort(list(target)))
    pass

9.48

import numpy as np


def insertSort(data):
    for i in range(1, len(data)):
        while i > 0 and data[i] < data[i - 1]:
            data[i], data[i - 1] = data[i - 1], data[i]
            i -= 1
    return data
    pass


if __name__ == '__main__':
    target = np.random.randint(0, 100, size=10)
    print(insertSort(list(target)))

9.49

import math
import numpy as np
from collections import deque



class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._n -= 1
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)

    def heappushpop(self, key, value):
        nowKey, nowValue = self.min()
        items = self._Item(key, value)
        if nowKey < key:
            self._data = [items] + self._data[:]
            self._trailer = self._data[-1]
            return nowKey
        else:
            pop = self._data[0]
            self._data[0] = items
            return pop._key, pop._value

    def heapreplace(self, key, value):
        items = self._Item(key, value)
        pop = self._data[0]
        self._data[0] = items
        return pop._key, pop._value

    def toString(self):
        return self._data

    def _heapify(self, index):
        largest = index
        lchild = 2*largest + 1
        rchild = 2 * largest + 2
        if lchild < trailer and self._data[lchild] < self._data[largest]:
            largest = lchild
        if rchild < trailer and self._data[rchild] < self._data[largest]:
            largest = rchild
        if largest != index:
            self._swap(index,largest)
            self._heapify(largest)

    def heapSort(self):
        global  trailer
        trailer = self._n
        for i in range(self._n-1,0,-1):
            self._swap(0,i)
            trailer -= 1
            self._heapify(0)


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    priorityQueue.add(7, 'B')
    priorityQueue.add(4, "C")
    priorityQueue.add(6, "A")
    priorityQueue.add(11, "F")
    priorityQueue.add(917, "F")
    priorityQueue.add(23, "F")
    priorityQueue.add(76, "F")
    priorityQueue.add(34, "F")
    priorityQueue.add(29, "F")
    priorityQueue.add(87, "F")
    priorityQueue.add(65, "F")
    priorityQueue.add(12, "F")
    print(priorityQueue)
    priorityQueue.heapSort()
    print(priorityQueue)

9.53

import time
import numpy as np
from collections import deque


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] < self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] < self._data[left]:
                        small_child = right
                if self._data[small_child] < self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._n -= 1
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)

    def heappushpop(self, key, value):
        nowKey, nowValue = self.min()
        items = self._Item(key, value)
        if nowKey < key:
            self._data = [items] + self._data[:]
            self._trailer = self._data[-1]
            return nowKey
        else:
            pop = self._data[0]
            self._data[0] = items
            return pop._key, pop._value

    def heapreplace(self, key, value):
        items = self._Item(key, value)
        pop = self._data[0]
        self._data[0] = items
        return pop._key, pop._value

    def toString(self):
        return self._data

    def _heapify(self, index):
        largest = index
        lchild = 2 * largest + 1
        rchild = 2 * largest + 2
        if lchild < trailer and self._data[lchild] < self._data[largest]:
            largest = lchild
        if rchild < trailer and self._data[rchild] < self._data[largest]:
            largest = rchild
        if largest != index:
            self._swap(index, largest)
            self._heapify(largest)

    def Swap(self, data, i, j):
        data[i], data[j] = data[j], data[i]

    def Heapify(self, data, i):
        largest = i
        lchild = 2 * largest + 1
        rchild = 2 * largest + 2
        if lchild < trailer and data[lchild] < data[largest]:
            largest = lchild
        if rchild < trailer and data[rchild] < data[largest]:
            largest = rchild
        if largest != i:
            self.Swap(data, i, largest)
            self.Heapify(data,largest)

    def heapSort1(self):
        data = []
        temp = self._data.copy()
        global trailer
        trailer = self._n
        for i in range(len(temp) - 1, 0, -1):
            self.Swap(temp, 0, i)
            trailer -= 1
            self.Heapify(temp,0)
            data.append(temp.pop())
        return data.reverse()

    def heapSort2(self):
        global trailer
        trailer = self._n
        for i in range(self._n - 1, 0, -1):
            self._swap(0, i)
            trailer -= 1
            self._heapify(0)


if __name__ == '__main__':
    priorityQueue = HeapPriorityQueue()
    N = 100
    for i in range(N):
        priorityQueue.add(key=np.random.randint(1, 100, size=1), value=np.random.random())
    start = time.time()
    priorityQueue.heapSort1()
    send = time.time()
    print(f"非原地排序 : {send - start}s")
    priorityQueue.heapSort2()
    print(priorityQueue)
    print(f'原地排序: {time.time() - send}s')
    #实验证明很奇怪,为什么开辟了一个新的空间反而更快?

9.54

import math
from collections import deque


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] > self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] > self._data[left]:
                        small_child = right
                if self._data[small_child] > self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._n -= 1
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)

    def heappushpop(self, key, value):
        nowKey, nowValue = self.min()
        items = self._Item(key, value)
        if nowKey < key:
            self._data = [items] + self._data[:]
            self._trailer = self._data[-1]
            return nowKey
        else:
            pop = self._data[0]
            self._data[0] = items
            return pop._key, pop._value

    def heapreplace(self, key, value):
        items = self._Item(key, value)
        pop = self._data[0]
        self._data[0] = items
        return pop._key, pop._value
        pass

    def _heapify(self, index):
        largest = index
        lchild = 2 * largest + 1
        rchild = 2 * largest + 2
        if lchild < trailer and self._data[lchild] > self._data[largest]:
            largest = lchild
        if rchild < trailer and self._data[rchild] > self._data[largest]:
            largest = rchild
        if largest != index:
            self._swap(index, largest)
            self._heapify(largest)

    def heapSort(self):
        global trailer
        trailer = self._n
        for i in range(self._n - 1, 0, -1):
            self._swap(0, i)
            trailer -= 1
            self._heapify(0)


class FavoritesListMTF(HeapPriorityQueue):
    def top(self, k):
        if not 1 <= k <= len(self):
            raise ValueError("illegel value for k ")
        self.heapSort()
        for i in range(k):
            key,value = self._data[i]._key,self._data[i]._value
            yield key,value

if __name__ == '__main__':
    favoritesListMTF = FavoritesListMTF()
    favoritesListMTF.add(2, 'B')
    favoritesListMTF.add(4, "C")
    favoritesListMTF.add(5, "A")
    favoritesListMTF.add(11, "F")
    favoritesListMTF.add(917, "F")
    favoritesListMTF.add(23, "F")
    favoritesListMTF.add(76, "F")
    favoritesListMTF.add(34, "F")
    favoritesListMTF.add(29, "F")
    favoritesListMTF.add(87, "F")
    favoritesListMTF.add(65, "F")
    favoritesListMTF.add(12, "F")
    for favorites in favoritesListMTF.top(5):
        print(favorites)

9.58

import math
import numpy as np
from collections import deque


class Empty(Exception):
    pass


class PriorityQueueBase:
    """Abstract base class for a priority queue."""

    class _Item:
        """Lightweight composite to store priority."""
        __slots__ = "_key", '_value'

        def __init__(self, key, value):
            self._key = key
            self._value = value

        def __lt__(self, other):
            return self._key < other._key

    def is_empty(self):
        """Return True if the priority queue is empty."""
        return len(self) == 0


class HeapPriorityQueue(PriorityQueueBase):
    """A min-oriented priority queue implemented with a binary heap."""

    def __init__(self):
        self._data = []
        self._n = 0
        self._trailer = None

    def _parent(self, j):
        return (j - 1) // 2

    def _left(self, j):
        return 2 * j + 1

    def _right(self, j):
        return 2 * j + 2

    def _has_left(self, j):
        return self._left(j) < self._n

    def _has_right(self, j):
        return self._right(j) < self._n

    def _swap(self, i, j):
        self._data[i], self._data[j] = self._data[j], self._data[i]

    def _uphead(self, j):
        now = j
        parent = self._parent(now)
        while parent >= 0 and now > 0:
            if self._data[now] > self._data[parent]:
                self._swap(now, parent)
            now = parent
            parent = self._parent(now)

    def _downheap(self, j):
        now = j
        history = None
        small_child = None
        while history != now:
            history = now
            if self._has_left(now):
                left = self._left(now)
                small_child = left
                if self._has_right(now):
                    right = self._right(now)
                    if self._data[right] > self._data[left]:
                        small_child = right
                if self._data[small_child] > self._data[now]:
                    self._swap(now, small_child)
            now = small_child

    def __len__(self):
        """Return the number of items in the priority queue."""
        return self._n

    def add(self, key, value):
        """Add a key-value pair to the priority queue."""
        items = self._Item(key, value)
        self._data.append(items)
        self._n += 1
        self._uphead(self._n - 1)
        self._trailer = self._data[-1]

    def min(self):
        """Return but do not remove (k,v) tuple  with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        item = self._data[0]
        return item._key

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty("Priority queue is empty.")
        self._swap(0, len(self._data) - 1)  # put minimum item at the end
        item = self._data.pop()  # and remove it from the list.
        self._n -= 1
        self._downheap(0)
        self._trailer = self._data[-1]
        return item._key, item._value

    def __str__(self):
        return '  '.join(str(items._key) + "," + str(items._value) for items in self._data)

    def find_all_min(self, key):
        root = 0
        data = deque()
        data.append(root)
        result = []
        while len(data) != 0:
            node = data.popleft()
            if self._data[node]._key > key:
                pass
            else:
                result.append(node)
                if self._has_left(node):
                    data.append(self._left(node))
                if self._has_right(node):
                    data.append(self._right(node))
        return "  ".join(str(self._data[i]._key) for i in result)

    def heappushpop(self, key, value):
        nowKey, nowValue = self.min()
        items = self._Item(key, value)
        if nowKey < key:
            self._data = [items] + self._data[:]
            self._trailer = self._data[-1]
            return nowKey
        else:
            pop = self._data[0]
            self._data[0] = items
            return pop._key, pop._value

    def heapreplace(self, key, value):
        items = self._Item(key, value)
        pop = self._data[0]
        self._data[0] = items
        return pop._key, pop._value
        pass

    def _heapify(self, index):
        largest = index
        lchild = 2 * largest + 1
        rchild = 2 * largest + 2
        if lchild < trailer and self._data[lchild] > self._data[largest]:
            largest = lchild
        if rchild < trailer and self._data[rchild] > self._data[largest]:
            largest = rchild
        if largest != index:
            self._swap(index, largest)
            self._heapify(largest)

    def heapSort(self):
        global trailer
        trailer = self._n
        for i in range(self._n - 1, 0, -1):
            self._swap(0, i)
            trailer -= 1
            self._heapify(0)


class AdaptPriorityQueue:
    def __init__(self, data):
        self._array = HeapPriorityQueue()
        self._temp = data  # 原数组
        self._n = len(data)

    def __len__(self):
        return self._n

    def initializeData(self):
        heapify = []  # 存放排序好的数组
        for array in self._temp:
            self._array.add(array,array)
        for array in self._array._data:
            heapify.append(array._key)
        return heapify

    def heapify(self):
        array = self.initializeData()
        return array

    def heappush(self, e):
        self._array.add(e, e)
        self._n += 1

    def heappop(self):
        print(self._array.remove_min())
        self._n -= 1

    def heappushpop(self, key, value):
        nowKey, nowValue = self._array.min()
        items = self._array._Item(key, value)
        if nowKey < key:
            self._array._data = [items] + self._array._data[:]
            self._array.trailer = self._array._data[-1]
            return nowKey
        else:
            pop = self._array._data[0]
            self._array._data[0] = items
            return pop._key, pop._value

    def heapreplace(self, key, value):
        items = self._array._Item(key, value)
        pop = self.array._data[0]
        self._array._data[0] = items
        return pop._key, pop._value


if __name__ == '__main__':
    np.random.seed(100)
    data = list(np.random.randint(1, 100, size=10))
    adaptPriorityQueue = AdaptPriorityQueue(data)
    print(data)
    print(adaptPriorityQueue.heapify())

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

北漂的阿狸

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

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

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

打赏作者

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

抵扣说明:

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

余额充值