Example #1
0
    def max_heapify(self, index):
        """
        Algorithm: We move downwards(bottom) in the heap in each step until heap is in it's correct form.

        Max-Heapify (A, i):
            left = 2*i // = means "assignment"
            right = 2*i + 1
            largest = i

            if left < len(A) and A[left] > A[largest] then:
                largest = left
            if right < len(A) and A[right] > A[largest] then:
                largest = right

            if largest != i then:
                swap A[i] and A[largest]
                Max-Heapify(A, largest)
        :param index:
        :return:
        """
        l_idx = MaxHeap.left(index)
        r_idx = MaxHeap.right(index)
        largest = index

        if l_idx < self.capacity and self.get(l_idx) is not None and self.get(l_idx) > self.get(largest):
            largest = l_idx
        if r_idx < self.capacity and self.get(r_idx) is not None and self.get(r_idx) > self.get(largest):
            largest = r_idx

        if largest != index:
            swap(self.harr, largest, index)
            self.max_heapify(largest)
def dutch_national_flag(arr):
    """
    Algorithm - Dutch national flag or three way partitioning
    Lo := 1; Mid := 1; Hi := N;
    while Mid <= Hi do
        Invariant: a[1..Lo-1]=0 and a[Lo..Mid-1]=1 and a[Hi+1..N]=2; a[Mid..Hi] are unknown.
        case a[Mid] in
            0: swap a[Lo] and a[Mid]; Lo++; Mid++
            1: Mid++
            2: swap a[Mid] and a[Hi]; Hi--
    :param arr:
    """
    from Array import swap
    mid = low = 0
    high = len(arr) - 1
    while mid <= high:
        curr = arr[mid]
        if curr == 0:
            swap(arr, low, mid)
            low += 1
            mid += 1
        elif curr == 1:
            mid += 1
        else:
            swap(arr, mid, high)
            high -= 1
Example #3
0
    def min_heapify(self, index):
        """
        Algorithm: We move downwards(bottom) in the heap in each step until heap is in it's correct form.

        Min-Heapify (A, i):
            left = 2*i          # `=` means `assignment`
            right = 2*i + 1
            smallest = i

            if left < len(A) and A[left] < A[smallest] then:
                smallest = left
            if right < len(A) and A[right] < A[smallest] then:
                smallest = right

            if smallest != i then:
                swap A[i] and A[smallest]
                Min-Heapify(A, smallest)

        :param index:
        :return:
        """
        l_idx = MinHeap.left(index)
        r_idx = MinHeap.right(index)
        smallest = index

        if l_idx < self.capacity and self.get(l_idx) is not None and self.get(l_idx) < self.get(smallest):
            smallest = l_idx
        if r_idx < self.capacity and self.get(r_idx) is not None and self.get(r_idx) < self.get(smallest):
            smallest = r_idx

        if smallest != index:
            swap(self.harr, smallest, index)
            self.min_heapify(smallest)
Example #4
0
    def max_heapify(self, index):
        """
        Algorithm: We move downwards(bottom) in the heap in each step until heap is in it's correct form.

        Max-Heapify (A, i):
            left = 2*i // = means "assignment"
            right = 2*i + 1
            largest = i

            if left < len(A) and A[left] > A[largest] then:
                largest = left
            if right < len(A) and A[right] > A[largest] then:
                largest = right

            if largest != i then:
                swap A[i] and A[largest]
                Max-Heapify(A, largest)
        :param index:
        :return:
        """
        l_idx = MaxHeap.left(index)
        r_idx = MaxHeap.right(index)
        largest = index

        if l_idx < self.capacity and self.get(
                l_idx) is not None and self.get(l_idx) > self.get(largest):
            largest = l_idx
        if r_idx < self.capacity and self.get(
                r_idx) is not None and self.get(r_idx) > self.get(largest):
            largest = r_idx

        if largest != index:
            swap(self.harr, largest, index)
            self.max_heapify(largest)
def separate_v2(arr):
    # Similar to quick-sort partition.
    ip = -1; pivot = 0
    for i in range(0, len(arr)):
        if arr[i] < pivot:  # if we use `arr[i] <= pivot`, then `0` will be placed somewhere between the -ve numbers.
            ip += 1
            swap(arr, i, ip)
Example #6
0
    def min_heapify(self, index):
        """
        Algorithm: We move downwards(bottom) in the heap in each step until heap is in it's correct form.

        Min-Heapify (A, i):
            left = 2*i          # `=` means `assignment`
            right = 2*i + 1
            smallest = i

            if left < len(A) and A[left] < A[smallest] then:
                smallest = left
            if right < len(A) and A[right] < A[smallest] then:
                smallest = right

            if smallest != i then:
                swap A[i] and A[smallest]
                Min-Heapify(A, smallest)

        :param index:
        :return:
        """
        l_idx = MinHeap.left(index)
        r_idx = MinHeap.right(index)
        smallest = index

        if l_idx < self.capacity and self.get(
                l_idx) is not None and self.get(l_idx) < self.get(smallest):
            smallest = l_idx
        if r_idx < self.capacity and self.get(
                r_idx) is not None and self.get(r_idx) < self.get(smallest):
            smallest = r_idx

        if smallest != index:
            swap(self.harr, smallest, index)
            self.min_heapify(smallest)
Example #7
0
    def replace_weight(self, data: T, new_weight: K) -> True:

        heap_node_idx: int = self._data_position_mapping_.get(data)
        if heap_node_idx is None:
            print("No such element -", data)
            return False

        heap_node: HeapNode[T, K] = self._harr_[heap_node_idx]
        curr_weight = heap_node.weight
        heap_node.weight = new_weight

        curr_idx = heap_node_idx
        parent_idx = MinBinaryHeap.parent(curr_idx)
        if new_weight < curr_weight:
            while self._harr_[curr_idx] < self._harr_[parent_idx]:
                self._data_position_mapping_[data] = parent_idx  # Update curr node data index to point to it's parent
                self._data_position_mapping_[self._harr_[parent_idx].data] = curr_idx  # Update parent index to point to curr_idx.

                swap(self._harr_, parent_idx, curr_idx)
                curr_idx = parent_idx
                parent_idx = MinBinaryHeap.parent(curr_idx)
                # curr_idx, parent_idx = parent_idx, MinBinaryHeap.parent(curr_idx)
        elif new_weight > curr_weight:
            self.min_heapify(curr_idx)
        else:
            print("Old weight({}) and new weight({}) are same".format(curr_weight, new_weight))
            return False

        return True
Example #8
0
def left_rotate_v3(arr, d):
    from Array import swap
    n = len(arr)
    for di in xrange(0, d):
        first = arr[0]
        for i in xrange(1, n):
            swap(arr, i, i - 1)
        arr[n - 1] = first
Example #9
0
def left_rotate_v3(arr, d):
    from Array import swap
    n = len(arr)
    for di in xrange(0, d):
        first = arr[0]
        for i in xrange(1, n):
            swap(arr, i, i-1)
        arr[n-1] = first
def separate_v2(arr):
    # Similar to quick-sort partition.
    ip = -1
    pivot = 0
    for i in range(0, len(arr)):
        if arr[i] < pivot:  # if we use `arr[i] <= pivot`, then `0` will be placed somewhere between the -ve numbers.
            ip += 1
            swap(arr, i, ip)
Example #11
0
def reverse_arr(arr, start=0, end=-1):
    from Array import swap
    alen = len(arr)
    end = (alen - 1) if end < 0 else end

    while start < end:
        swap(arr, start, end)
        start += 1
        end -= 1
def segregate_v2(arr):
    start = 0
    end = len(arr) - 1
    mid = (start + end) / 2

    while start < end:
        if arr[mid] == 0:
            swap(arr, mid, start)
            start += 1
        elif arr[mid] == 1:
            swap(arr, mid, end)
            end -= 1
def segregate_v1(arr):
    """
    Similar to quick sort partition by considering 0 as pivot.
    :param arr:
    :return:
    """
    pivot = 0
    ip = -1
    for i in range(0, len(arr)):
        if arr[i] <= pivot:
            ip += 1
            swap(arr, i, ip)
    return ip
Example #14
0
    def extract_min(self) -> HeapNode[T, K]:
        if len(self._harr_) == 0:
            return None

        min_idx = 0
        last_idx = -1
        min_heap_node = self._harr_[min_idx]
        last_heap_node = self._harr_[last_idx]

        self._data_position_mapping_.pop(min_heap_node.data)    # Remove first node
        self._data_position_mapping_[last_heap_node.data] = min_idx # Update last_node index to min_idx

        swap(self._harr_, min_idx, last_idx) # Move last node to the first index(min_idx)
        self._harr_.pop(last_idx) # Remove last node
        self.min_heapify(min_idx)
        return min_heap_node
Example #15
0
    def push(self, data: T, weight: K, *args, **kwargs) -> HeapNode[T, K]:
        heap_node = HeapNode(data, weight, *args, **kwargs)
        self._harr_.append(heap_node)
        curr_idx = len(self._harr_) - 1
        parent_idx = MinBinaryHeap.parent(curr_idx)
        self._data_position_mapping_[data] = curr_idx

        while self._harr_[curr_idx] < self._harr_[parent_idx]:
            self._data_position_mapping_[data] = parent_idx     # Update curr node data index to point to it's parent
            self._data_position_mapping_[self._harr_[parent_idx].data] = curr_idx # Update parent index to point to curr_idx.

            swap(self._harr_, parent_idx, curr_idx)

            curr_idx = parent_idx
            parent_idx = MinBinaryHeap.parent(curr_idx)

        return heap_node
Example #16
0
    def insert(self, elt):
        if self.is_full():
            print("Heap is full, can't insert key")
            return False

        # First insert the new key at the end.
        self.harr.append(elt)
        self.heap_size += 1
        elt_idx = self.heap_size - 1

        # Fix the min heap property if it is violated
        # Algorithm: We move upwards(top) step-by-step until heap is in it's correct form.
        # while parent(elt) >=0 and harr[parent(elt)] > elt:
        #   swap(parent, elt)
        #   index(elt) = parent(elt)
        while Heap.parent(elt_idx) >= 0 and self.get(Heap.parent(elt_idx)) > elt:
            swap(self.harr, Heap.parent(elt_idx), elt_idx)
            elt_idx = Heap.parent(elt_idx)
        return True
Example #17
0
    def insert(self, elt):
        if self.is_full():
            print("Heap is full, can't insert key")
            return False

        # First insert the new key at the end.
        self.harr.append(elt)
        self.heap_size += 1
        elt_idx = self.heap_size - 1

        # Fix the max heap property if it is violated.
        # Algorithm: We move upwards(top) step-by-step until heap is in it's correct form.
        # while parent(elt) >=0 and harr[parent(elt)] < elt:
        #   swap(parent, elt)
        #   index(elt) = parent(elt)
        while Heap.parent(elt_idx) >= 0 and self.get(
                Heap.parent(elt_idx)) < elt:
            swap(self.harr, Heap.parent(elt_idx), elt_idx)
            elt_idx = Heap.parent(elt_idx)
        return True
Example #18
0
    def min_heapify(self, curr_index: int):
        left_idx = MinBinaryHeap.left_child(curr_index)
        right_idx = MinBinaryHeap.right_child(curr_index)

        left_elt = None
        right_elt = None
        if len(self._harr_) >= (left_idx + 1): left_elt = self._harr_[left_idx]
        if len(self._harr_) >= (right_idx + 1): right_elt = self._harr_[right_idx]

        smallest_elt_idx = curr_index

        if left_elt and left_elt < self._harr_[smallest_elt_idx]:
            smallest_elt_idx = left_idx

        if right_elt and right_elt < self._harr_[smallest_elt_idx]:
            smallest_elt_idx = right_idx

        if smallest_elt_idx != curr_index:
            self._data_position_mapping_[self._harr_[smallest_elt_idx].data] = curr_index
            self._data_position_mapping_[self._harr_[curr_index].data] = smallest_elt_idx
            swap(self._harr_, smallest_elt_idx, curr_index)
def rearrange_v1(arr):
    from Array import swap

    # Partitioning array same as quick sort partition by taking 0 as pivot so that all the -ve numbers
    # will be at left and +ve numbers will be at right.
    pindex = -1
    pivot = 0
    for i in range(0, len(arr)):
        if arr[i] < pivot:
            pindex += 1
            swap(arr, i, pindex)

    print(pindex)
    print(arr)
    # Since -ve and +ve numbers are separated, we start from the first -ve number and first +ve number,
    # and swap every alternate negative number with next positive number
    i_pos = pindex + 1
    for i in range(0, len(arr), 2):
        if i_pos >= len(arr) or arr[i] > 0:
            break
        swap(arr, i, i_pos)
        i_pos += 1