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)
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]
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]
# 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]))
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)
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]
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]
# 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]))