quicksort in python always return a unsorted array

Question:

i defined a quicksort in python.It printed a sorted list, but the return list is unsorted.
[1, 5, 7, 8] #this is result of print(array) in quicksort
[7, 5, 8, 1] #this is result of testing
it’s so weired

def quickSort(array):
    if len(array) <= 1:
        return array

    p = 0  #pivot
    pointer = p + 1
    left = []
    pivot = []
    right = []
    pivot.append(array[p])
    
    #devide array into 3 arrays
    while pointer < len(array):
        if array[pointer] < array[p]:
            left.append(array[pointer])
        elif array[pointer] > array[p]:
            right.append(array[pointer])
        else:
            pivot.append(array[pointer])
            #pointer moves towards right
        pointer += 1
    
    print(left)
    print(pivot)
    print(right)
    array = quickSort(left) + pivot + quickSort(right)
    print(array)
    #concatenation of the 3 arrays
    return (array)
    
array = [7,5,8,1] 
quickSort(array)
print(array)
Asked By: LiiiiilteChick

||

Answers:

You are confusing pointer and reference in Java (or C# or C++) language. Your problem is the functional programming paradigm. Python supports 3 paradigms simultaneously. Therefore, when you give an argument to a function, the value of the argument does not normally change.

You need to assign function return to variable to use it.

def quickSort(array):
    if len(array) <= 1:
        return array

    p = 0  # pivot
    pointer = p + 1
    left = []
    pivot = []
    right = []
    pivot.append(array[p])

    # devide array into 3 arrays
    while pointer < len(array):
        if array[pointer] < array[p]:
            left.append(array[pointer])
        elif array[pointer] > array[p]:
            right.append(array[pointer])
        else:
            pivot.append(array[pointer])
            # pointer moves towards right
        pointer += 1

    print(left)
    print(pivot)
    print(right)
    array = quickSort(left) + pivot + quickSort(right)
    print(array)
    # concatenation of the 3 arrays
    return array


array = [7, 5, 8, 1]
array = quickSort(array)
print(array)
# or
response_array = quickSort(array)
print(response_array)

(edit) EXTRA COMMENT ADDED:

if you want to change your argument value without using global variable, let me explain more before revised your code. first you look at below code:

def sample():
    x = 0
    print(id(x), x.y_var)
    increment2(x)
    print(id(x), x.y_var)

def increment(x):
    print(id(x), x)
    x = x + 1
    print(id(x), x)

sample()

the sample output will be like

2421700716816 0
2421700716816 0
2421700716848 1
2421700716816 0

as you could realize python created new variable, you need to return it for reach its value, but if you create a class as you will see below:

class Y:
    y_var = 0

def sample():
    x = Y()
    print(id(x), x.y_var)
    increment(x)
    print(id(x), x.y_var)

def increment(x:Y):
    print(id(x), x.y_var)
    x.y_var = x.y_var + 1
    print(id(x), x.y_var)

sample()

the object created from the Y class id is not changed after calling function, so you can use it without need to return it. Sample output is:

1594815643600 0
1594815643600 0
1594815643600 1
1594815643600 1

I changed your code as below with using @soudipta-dutta sample code; it is more pythonic:

class MyArray:
    my_list = []


def quick_sort(array: MyArray):
    if len(array.my_list) < 2:
        return array.my_list
    else:
        pivot = array.my_list[0]
        left = MyArray()
        left.my_list = [i for i in array.my_list[1:] if i <= pivot]
        right = MyArray()
        right.my_list = [i for i in array.my_list[1:] if i > pivot]
        array.my_list = quick_sort(left) + [pivot] + quick_sort(right)
        return array.my_list
    
    
my_array = MyArray()
my_array.my_list = [7, 5, 8, 1]
quick_sort(my_array)
print(my_array.my_list)

output is

[1, 5, 7, 8]
Answered By: Ferhat Mousavi

In the event that you pass arguments like whole numbers, strings or tuples to a function, the passing is like call-by-value because you can not change the value of the immutable objects being passed to the function.

Example:-

string = "Yash"
def test(string):
    string = "Yash Mehta"
    print("Inside Function:", string)

test(string)  #Yash Mehta
print("Outside Function:", string) #Yash

you can store the answer by making another variable which store list..

def quickSort(array):
    if len(array) <= 1:
        return array
    p = 0  #pivot
    pointer = p + 1
    left = []
    pivot = []
    right = []
    pivot.append(array[p])
    
    #dvide array into 3 arrays
    while pointer < len(array):
        if array[pointer] < array[p]:
            left.append(array[pointer])
        elif array[pointer] > array[p]:
            right.append(array[pointer])
        else:
            pivot.append(array[pointer])
            #pointer moves towards right
        pointer += 1
    
    print(left)
    print(pivot)
    print(right)
    array = quickSort(left) + pivot + quickSort(right)
    print(array)
    #concatenation of the 3 arrays
    return array
    
array = [7,5,8,1] 
sorted_array=quickSort(array)
print(sorted_array)

Output:

[5, 1]
[7]
[8]
[1]
[5]
[]
[1, 5]
[1, 5, 7, 8]
[1, 5, 7, 8]
Answered By: Yash Mehta
# a is an array 
def quickSort(a):
    if len(a) <2 : return a
    else:
        pivot = a[0]
        less = [i for i in a[1:] if i <= pivot]
        print("less :", less)
        greater = [i for i in a[1:] if i > pivot]
        print("greater : " , greater)
        return quickSort(less) + [pivot] + quickSort(greater)
print(quickSort([10, 5, 2,100, 3,7,9])) 
Answered By: Soudipta Dutta