Пример #1
0
def quick_sort_helper(array: List[int], start: int, end: int) -> None:
    if start >= end:
        return
    pivot = start
    ptr_l = start + 1
    ptr_r = end

    while ptr_l <= ptr_r:
        if array[ptr_l] > array[pivot] and array[pivot] > array[ptr_r]:
            swap(array, ptr_l, ptr_r)
            ptr_l += 1
            ptr_r -= 1

        elif array[ptr_l] <= array[pivot]:
            ptr_l += 1

        elif array[ptr_r] >= array[pivot]:
            ptr_r -= 1

    swap(array, pivot, ptr_r)
    if end - (ptr_r + 1) > (ptr_r - 1) - start:
        quick_sort_helper(array, start, ptr_r - 1)
        quick_sort_helper(array, ptr_r + 1, end)

    else:
        quick_sort_helper(array, ptr_r + 1, end)
        quick_sort_helper(array, start, ptr_r - 1)
    def _sift_up(self, heap: List[object], start: int, end: int) -> None:
        """ This method has the responsibility of ensuring the heap
        property is met when elements are inserted into the heap.

        When an element is inserted into the heap, the heap property
        will most likely be violated. This method moves the inserted
        element up the heap until the heap property is satisifed.

        Args:
            heap:
                Array holding objects that represents a heap

            start:
                Integer representing the index in the array to start sifting
                up from

            end:
                Integer representing the last index in the array to sift up to
        """
        parent_idx = (start - 1) // 2
        while parent_idx >= end:
            # if heap property is not met, then we swap and continue upwards
            # if its true that heap[start] is less than heap[parent], we swap
            # for min-heaps. if its true that heap[start] is greater than
            # heap[parent], we swap for max-heaps
            if self.comparator_func(heap[start], heap[parent_idx]):
                swap(heap, start, parent_idx)
                start = parent_idx
                parent_idx = (start - 1) // 2
            else:
                break
    def remove(self, heap: List[object]) -> object:
        """ Removes the highest priority element from the heap using the
        sift_down helper method and returns it.

        Time:
            O(logN) best/average/worst

        Space:
            O(1) best/average/worst

        Where N is the number of elements inside of the heap

        Args:
            heap:
                Array holding objects that represents a heap

        Returns:
            The object with the highest priority in the heap
        """
        if not heap:
            return
        swap(heap, 0, len(heap) - 1)
        removed_val = heap.pop()
        self.sift_down(heap, 0, len(heap) - 1)
        return removed_val
Пример #4
0
def heap_sort(array: List[int]) -> List[int]:
    """ This algorithm represents the heap sort algorithm, used to
    sort an array of integers in ascending order. This algorithm relies
    on a data structure called a max-heap to efficiently sort an array
    of elements in-place.

    This algorithm does not produce a stable sort. This algorithm also
    has an additional operation of max-heapifying the input array, so
    on average it will run slower than quicksort, but has the advantage
    of having a worst case time complexity better then quicksort
    along with not using any space.

    Time:
        O(NlogN) best/avg/worst

    Space:
        O(1) best/avg/worst

    Where N represents the length of the input array

    Args:
        array:
            List of integers to sort in ascending order

    Returns:
        The input list of integers sorted in ascending order in place
    """
    if not array:
        return []
    # heap sort relies on the array being a max-heap -
    # therefore we have to heapify the array before
    # performing any swap operations
    heap = Heap(type_heap=1)
    heap.heapify(array)
    # endIdx represents the idx which the current largest element
    # in the max heap will swap to first iteration, this will be the
    # largest element in the heap so it should go in the last
    # idx spot, and so on from there
    end_idx = len(array) - 1
    while end_idx > 0:
        swap(array, 0, end_idx)
        end_idx -= 1
        # have to maintain heap property - every parent node has to have a value
        # greater than or equal to children nodes
        heap.sift_down(array, 0, end_idx)
    return array
    def sift_down(self, heap: List[object], start: int, end: int) -> None:
        """ This method has the responsibility of ensuring the heap property
        is met when elements are removed from the heap.

        When the root element is removed from the heap, a new element is
        placed at the root. This method will move that element down the heap
        until the heap property is satisfied.

        Args:
            heap:
                Array holding objects that represents a heap

            start:
                Integer representing the index in the array to start sifting
                down from

            end:
                Integer representing the last index in the array to sift down to
        """
        curr_idx = start
        first_child_idx = start * 2 + 1
        while first_child_idx <= end:
            second_child_idx = (curr_idx * 2 +
                                2 if curr_idx * 2 + 2 <= end else -1)
            # If val at second_child_idx is less than val at first_child_idx in
            # minHeaps,then its candidate to consider when swapping. If val at
            # second_child_idx is greater than val at first_child_idx in
            # maxHeaps, then its candidate to consider when swapping
            if second_child_idx != -1 and self.comparator_func(
                    heap[second_child_idx], heap[first_child_idx]):
                idx_to_swap = second_child_idx
            else:
                idx_to_swap = first_child_idx
            if self.comparator_func(heap[idx_to_swap], heap[curr_idx]):
                swap(heap, idx_to_swap, curr_idx)
                curr_idx = idx_to_swap
                first_child_idx = curr_idx * 2 + 1
            else:
                break