冒泡排序
冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
步骤:
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
时间复杂度:平均:O(n^2) ,最好情况:当输入数据正序时,为O(n); 最坏情况:当输入的数据是反序时,为 O(n^2)
稳定性:因为array[j]==array[j+1]的时候,我们可以不移动array[i]和array[j],所以冒泡排序是稳定的。
def bubbleSort(arr):
for i in range(1, len(arr)):
for j in range(0, len(arr)-i):
if arr[j] > arr[j+1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
快速排序
时间复杂度:平均为O(nlogn),最坏情况O(n^2),每次所选的中间数是当前序列中的最大或最小元素;
最好情况:每次划分所选择的中间数恰好将当前序列几乎等分,整个算法的时间复杂度为O(nlogn)。
最坏情况:每次划分所选的数都很偏,为数组的最大值或最小值,此时相当于冒泡排序(每次排好一个元素的位置),时间复杂度为O(n^2)。解决办法:选pivot的时候可以随机选,而不是每次选第一个或者最后一个。
挖坑填数的思想
快排就是一个选定基准点后不断和基准点比较的过程,比基准大的放到右边,比基准小的或相等的放到左边。
1、i =left; j = right;首先选定数组第一个数为基准数nums[i],并把它赋值给temp, 相当于挖了一个坑,把坑中原来的数用temp保存起来。
2、要先从后往前找。先从后往前找一个比他小的数nums[j],找到这个数之后将其挖出此数填到之前的坑中nums[i]=nums[j],这时nums[j]又有了一个坑。再从前往后找比基准数大的,填到刚才挖的坑中,两种行为交替进行,直到i>=j;这个时候基准temp就找到了它正确的位置 i,所以num[i]=temp;
3、然后进行递归,递归进行时要求left<right,即递归的出口时left>=right
def quick_sort(num, left, right):
if left<right:
temp = num[left]
print(num)
print('left ', left)
print('right ', right)
i = left
j = right
while i<j:
while i<j and num[j]>temp:
j -= 1
num[i] = num[j]
while i<j and num[i]<=temp:
i += 1
num[j] = num[i]
# 基准找到了它正确的位置
num[i] = temp
# 再对基准的左边进行排序
quick_sort(num, left, i-1)
# 对基准的右边进行排序
quick_sort(num, i+1, right)
if __name__ == "__main__":
num = [4,1,2,7,3,5,4,8,6,44,0,23]
quick_sort(num, 0, len(num)-1)
print(num)
归并排序
时间复杂度为O(nlogn),最好最坏情况都一样。空间复杂度为O(n)。
思路:归并排序的根本思路就是将两个有序数组合并为一个有序数组。问题的关键就是如何将无序数组分为有序数组。可以采用递归的方式,当一直递归到每个数组中只有一个数时,这个数组就相当于排好序了。
def mergeSort(arr):
if(len(arr)<2):
return arr
# 二分
middle = len(arr) // 2
left, right = arr[0:middle], arr[middle:]
# 递归
return merge(mergeSort(left), mergeSort(right))
# 合并两个排好序的数组
# left,right两个数组均已经排好序
def merge(left,right):
result = []
while left and right:
if left[0] <= right[0]:
result.append(left.pop(0))
else:
result.append(right.pop(0))
while left:
result.append(left.pop(0))
while right:
result.append(right.pop(0))
return result
arr = [3,2,5,8,9,6,4,1]
temp = mergeSort(arr)
print(temp)