I'm trying to animate a quick sort using matplotlib, but the code only loops correctly without the plot. The code logic is exactly the same

23 views Asked by At

Here is the one with the plotting removed, sorts correctly.



def quicksort(arr):


    boundary_stack = [(0, len(arr) - 1)]  # Initialize with full range

    def update(i, arr):



        low_idx, high_idx = boundary_stack.pop()
        low = low_idx
        high = high_idx
        pivot_index = (low + high) // 2
        pivot = arr[pivot_index]


        while low <= high:
            while arr[low] < pivot:
                low += 1
            while arr[high] > pivot:
                high -= 1

            if low <= high:
                arr[low], arr[high] = arr[high], arr[low]
                low += 1
                high -= 1

            print(f"low: {low}, {arr[low]}, high: {high}, {arr[high]} , arr: {arr}")
        # Check if the partitioning is complete based on max and min values
        print(f"low_idx {low_idx} low_val {arr[low_idx]}")
        print(f"high_idx {high_idx} high_val {arr[high_idx]}")
        print(f"pivot {pivot_index} pivot_val {arr[pivot_index]}")
        print(f"subarray{arr[low_idx:high_idx]}")
        if low_idx == pivot_index:
            left_max = arr[low_idx]
        else:
            left_max = max(arr[low_idx:pivot_index])

        if high_idx == pivot_index:
            right_min = arr[high_idx]
        else:
            right_min = min(arr[pivot_index:high_idx])

        if left_max <= pivot <= right_min and (pivot_index - low_idx) > 0 and (
            high_idx - pivot_index) > 0:
            # Partitioning is complete, add boundaries to the stack for further processing
            boundary_stack.append((low_idx, pivot_index - 1))
            boundary_stack.append((pivot_index + 1, high_idx))

        elif low_idx != high_idx and not (left_max <= pivot <= right_min):
            boundary_stack.append((low_idx, high_idx))



        return arr
    while arr != arr.sort():
        update(0,arr)



numbers = [824, 829, 855, 824, 863, 860]

quicksort(numbers)


Here is the one that has plotting include and gets stuck"

from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation


def animate_quicksort(arr):
    fig, ax = plt.subplots()
    ax.set_xlim([0, len(arr)])  # Set x-axis limits
    ax.set_ylim([min(arr), max(arr)])  # Set y-axis limits
    ax.bar(range(len(arr)), arr, width=1)
    ax.set_title('Quick Sort Animation')
    ax.set_xlabel('Index')
    ax.set_ylabel('Value')

    boundary_stack = [(0, len(arr) - 1)]  # Initialize with full range

    def update(i, arr):

        ax.clear()
        ax.set_xlim([0, len(arr)])  # Restore x-axis limits
        ax.set_ylim([min(arr), max(arr)])  # Restore y-axis limits
        ax.bar(range(len(arr)), arr, width=1)
        ax.set_title('Quick Sort Animation')
        ax.set_xlabel('Index')
        ax.set_ylabel('Value')

        low_idx, high_idx = boundary_stack.pop()
        low = low_idx
        high = high_idx
        pivot_index = (low + high) // 2
        pivot = arr[pivot_index]

        # Add a green dotted line for the pivot element
        ax.plot([pivot_index, pivot_index], [min(arr), max(arr)], 'g--', label='Pivot')

        while low <= high:
            while arr[low] < pivot:
                low += 1
            while arr[high] > pivot:
                high -= 1

            if low <= high:
                arr[low], arr[high] = arr[high], arr[low]
                low += 1
                high -= 1

            print(f"low: {low}, {arr[low]}, high: {high}, {arr[high]} , arr: {arr}")
        # Check if the partitioning is complete based on max and min values
        print(f"low_idx {low_idx} low_val {arr[low_idx]}")
        print(f"high_idx {high_idx} high_val {arr[high_idx]}")
        print(f"pivot {pivot_index} pivot_val {arr[pivot_index]}")
        print(f"subarray{arr[low_idx:high_idx]}")
        if low_idx == pivot_index:
            left_max = arr[low_idx]
        else:
            left_max = max(arr[low_idx:pivot_index])

        if high_idx == pivot_index:
            right_min = arr[high_idx]
        else:
            right_min = min(arr[pivot_index:high_idx])

        if left_max <= pivot <= right_min and (pivot_index - low_idx) > 0 and (
            high_idx - pivot_index) > 0:
            # Partitioning is complete, add boundaries to the stack for further processing
            boundary_stack.append((low_idx, pivot_index - 1))
            boundary_stack.append((pivot_index + 1, high_idx))
        elif low_idx != high_idx and not (left_max <= pivot <= right_min):
            boundary_stack.append((low_idx, high_idx))

    anim = FuncAnimation(fig, update, frames=range(len(arr)), fargs=(arr,))

    plt.show()


numbers = [824, 829, 855, 824, 863, 860]

animate_quicksort(numbers)

I noticed in the test print for the animated one it's missing the element 863

low: 3, 855, high: 2, 824 , arr: [824, 829, 824, 855, 863, 860]
low_idx 0 low_val 824
high_idx 5 high_val 860
pivot 2 pivot_val 824
subarray[824, 829, 824, 855, 863]

But for the test print in the non-animated code it's correctly identifying 863 as the high value.

low: 3, 855, high: 1, 824 , arr: [824, 824, 829, 855, 860, 863]
low_idx 0 low_val 824
high_idx 5 high_val 863
pivot 2 pivot_val 829
subarray[824, 824, 829, 855, 860]

Thanks in advance

0

There are 0 answers