三、排序
1. 冒泡排序
- 思想:每次都是相邻元素进行比较,当后面的元素小于前面元素时,就进行交换位置 。
- 时间复杂度:O(N^2) 空间复杂度:O(1)
- 稳定性:稳定
def bubble_sort_mod(array):
for i in range(len(array)):
is_sorted = True
for j in range(1, len(array) - i):
if (array[j] < array[j - 1]):
array[j], array[j - 1] = array[j - 1], array[j]
is_sorted = False
if (is_sorted): break
return array
2. 选择排序
- 思想:是对冒泡排序的改进,每一轮仅进行一次交换,把最大值换到最后面即可。
- 时间复杂度:O(N^2) 空间复杂度:O(1)
- 稳定性:不稳定
# 这里是每一轮换最大值,把最大值换到数组最后面去
def selection_sort(nums):
for i in range(len(nums)):
pos_max = 0
for j in range(1, len(nums) - i):
if nums[j] > nums[pos_max]:
pos_max = j
nums[len(nums)-i-1], nums[pos_max] = nums[pos_max], nums[len(nums)-i-1]
return nums
3. 插入排序
- 思想:类似于打牌的时候人们插牌的方式,来一张新牌就把它与前面排好的牌进行比对,找到合适的插入位置。
- 时间复杂度:O(N^2) 空间复杂度:O(1)
- 稳定性:稳定
def insert_sort(nums):
for i in range(1, len(nums)):
current_value = nums[i]
position = i
while position > 0 and nums[position-1] > current_value: # while 循环实现
nums[position] = nums[position-1] # 移动操作仅一次赋值,是交换操作的三分之一,此时性能会好一些
position -= 1
nums[position] = current_value # 插入
return nums
4. 希尔排序
- 思想:希尔排序就是再插入排序的基础上多了个gap而已。
- 时间复杂度:O(N^1.3) 空间复杂度:O(1)
- 稳定性:不稳定
def shell_sort(nums):
sublistcount = len(nums) // 2
while sublistcount > 0:
for startposition in range(sublistcount):
gapInsertionSort(nums, startposition, sublistcount)
print("After increments of size", sublistcount, "The list is", nums)
sublistcount = sublistcount // 2
return nums
def gapInsertionSort(nums, start, gap): #插入排序
for i in range(start+gap, len(nums), gap):
currentvalue = nums[i]
position = i
while position >= gap and nums[position-gap] > currentvalue:
nums[position] = nums[position-gap]
position -= gap
nums[position] = currentvalue
5. 计数排序
- 思想:首先找到数组的最大值和最小值,根据这两个值制造一定长度的抽屉。其次要把数字一个个的放到抽屉里面,然后再按顺序拿出来。
- 时间复杂度:O(N) 空间复杂度:O(K), K表示最大值与最小值之差
- 稳定性:稳定
def count_sort(items):
mmax, mmin = max(items), min(items)
nums = mmax - mmin + 1
counts = [0] * nums
for i in range(len(items)):
counts[items[i]-mmin] = counts[items[i] - mmin] + 1
pos = 0
for i range(nums): # 只是从抽屉里把所有的数都拿出来,O(n)复杂度
for j in range(counts[i]):
items[pos] = i + mmin
pos += 1
return items
6. 归并排序
- 思想:将数组持续分为两半,分别对两半运用双指针的办法进行归并排序。是一种递归的方法
- 时间复杂度:O(N) 空间复杂度:O(1)
- 稳定性:稳定
# 更python的写法
def merge_sort(nums):
if len(nums) <= 1: # base情况 也就是递归的结束条件
return nums
# 分解问题,并递归调用
middle = len(nums) // 2
left = merg_sort(nums[:middle]) # 左半部
right = merg_sort(nums[middle:]) # 右半部
# 合并左右半步,完成排序
merged = []
while left and right:
if left[0] <= right[0]:
merged.append(left.pop(0))
else:
merged.append(right.pop(0))
merged.extend(right if right else left)
return merged
7. 快速排序
- 思想:依据一个“中值”数据项把数组分为两半:小于中值的一半和大于中值的一半。然后分别对两半进行快速排序。
- 时间复杂度:O(NlgN) 空间复杂度: 首先就地快速排序使用的空间是O(1)的,也就是个常数级;而真正消耗空间的就是递归调用了,因为每次递归就要保持一些数据;
- 稳定性:不稳定
def quickSort(nums):
quickSortHelper(nums, 0, len(nums)-1)
def quickSortHelper(nums, first, last):
if first < last:
splitpoint = partition(nums, first, last) # 先找到中点
quickSortHelper(nums, first, splitpoint-1)
quickSortHelper(nums, splitpoint+1, last)
def partition(nums, first, last):
pivotvalue = nums[first]
leftmark = first + 1
rightmark = last
done = False
while not done:
while leftmark <= rightmark and nums[leftmark] <= pivotvalue:
leftmark += 1
while leftmark <= rightmark and nums[rightmark] >= pivotvalue:
rightmark -= 1
if rightmark < leftmark:
done = True
else:
nums[leftmark], nums[rightmark] = nums[rightmark], nums[leftmark]
nums[first], nums[rightmark] = nums[rightmark], nums[first]
return rightmark

浙公网安备 33010602011771号