排序
文章目录
1、交换排序
1.1 冒泡排序(Bubble Sort)
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
- 针对所有的元素重复以上的步骤,除了最后一个;
- 重复步骤1~3,直到排序完成。
def bubbleSort(nums):
for i in range(len(nums)):
for j in range(1, len(nums)-i):
if nums[j] < nums[j-1]:
nums[j], nums[j-1] = nums[j-1], nums[j]
return nums
1.2 快速排序(Quick Sort)
-
从数列中挑出一个元素,称为 “基准”(pivot);
-
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
-
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
def quickSort(nums):
if not nums:
return []
l = nums[0]
nums_left = [i for i in nums if i < l]
nums_right = [i for i in nums if i > l]
return nums_left + [l] + nums[right]
2、插入排序
2.1 简单插入排序(类似于抓牌)
- 从第一个元素开始,该元素可以认为已经被排序;
- 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 如果该元素(已排序)大于新元素,将该元素移到下一位置;
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
- 将新元素插入到该位置后;
- 重复步骤2~5。
def SimpleSort(nums):
for i in range(1, len(nums)):
while i > 0 and nums[i] < nums[i-1]:
nums[i], nums[i-1] = nums[i-1], nums[i]
i -= 1
return nums
2.2 希尔排序(shell sort)
先将整个待排序的记录序列分割成若干子序列分别进行直接插入排序, 具体算法描述:
- 将待排序分割成2个子序列, 对这2个子序列的对应位置进行排序(
i, i+gap
) - 分割成4个子序列,
gap
缩减一半, 对应位置排序(i, i+gap
) - 直到
gap
为1, 也就是简单插入排序
def shellSort(nums):
n = len(nums)
gap = n // 2 ### 一开始间隔为序列的一半, 逐渐减小间隔至1
while gap >= 1:
for i in range(gap, n):
while i - gap >= 0 and nums[i] < nums[i - gap]:
nums[i], nums[i - gap] = nums[i - gap], nums[i]
i -= gap
gap //= 2
3、选择排序
3.1 直接选择排序(Select Sort)
第i次迭代过程中,在[i, n]区间的数据中选取最小的作为第i个的值(交换最小的到第i个索引)
def selectSort(nums):
for i in range(0, len(nums)-1):
index = i
for j in range(i+1, len(nums)):
if nums[j] < nums[index]:
index = j
if index != i:
nums[index], nums[i] = nums[i], nums[index]
return nums
3.2 堆排序
- 建立大顶堆
- 将堆顶元素与最后一个元素交换, 此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];每次进行一轮调整, 会增加最后一个位置的有序区。
def heapSort(nums):
def heapjust(nums, start, end):
temp = nums[start]
son = 2 * start + 1
while son <= end:
if son < end and nums[son] < nums[son + 1]:
son += 1
if temp > nums[son]:
break
nums[start] = nums[son]
start = son
son = 2 * start + 1
nums[start] = temp
n = len(nums)
root = n // 2 - 1
while root >= 0 :
heapjust(nums, root, n - 1)
root -= 1
i = n - 1
while i >= 0:
nums[0], nums[i] = nums[i], nums[0]
heapjust(nums, 0, i-1)
i -= 1
return nums
4、归并排序
归并排序是建立在归并操作上的一种有效的排序算法, 该算法是采用分治法的一种典型的应用。将已有序的子序列合并, 得到完全有序的序列;即先使每个子序列有序, 再使子序列段间有序。
- 分割子序列, 直到子序列剩一个(有序)
- 有序序列合并, 使用额外的进行append
def merge(left_nums, right_nums):
left_index, right_index, merge_nums = 0, 0 , []
while left_index < len(left_nums) and right_index < len(right_nums):
if left_nums[left_index] < right_nums[right_index]:
merge_nums.append(right_nums[right_index])
right_index += 1
else:
merge_nums.append(left_nums[left_index])
left_index += 1
return merge_nums + left_nums[left_index:] + right_nums[right_index:]
def mergeSort(nums):
if len(nums) == 1:
return nums
left_nums = mergeSort(nums[:len(nums)//2])
right_nums = mergeSort(nums[len(nums)//2 :])
return merge(left_nums, right_nums)
排序方法 | 时间复杂度(平均) | 时间复杂度(最坏) | 时间复杂度(最好) | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 稳定 |
快速排序 | O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n) | O ( n 2 ) O(n^2) O(n2) | O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n) | O ( n l o g 2 n ) O(n log_2 n) O(nlog2n) | 不稳定 |
简单插入排序 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 稳定 |
希尔排序 | O ( n 3 ) O(n^3) O(n3) | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( 1 ) O(1) O(1) | 不稳定 |
直接选择排序 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | 不稳定 |
堆排序 | O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n) | O ( 1 ) O(1) O(1) | 不稳定 |
归并排序 | O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n) | O ( n l o g 2 n ) O(nlog_2 n) O(nlog2n) | O ( n ) O(n) O(n) | 稳定 |
- 稳定: 如果a原本在b前面, 而a=b,排序之后a仍然在b的前面
- 不稳定: 如果a原本在b前面, 而a=b, 排序之后a可能在b的前面
- 时间复杂度: 对排序数据的总的操作次数。反映当n变化时, 操作次数呈现什么规律
- 空间复杂度: 是指算法在计算机执行时所需存储空间的度量, 它也是数据规模n的函数。