比较类排序
- 交换排序
- 冒泡排序
- 快速排序
- 插入排序
- 简单插入排序
- 希尔排序
- 选择排序
- 简单选择排序
- 堆排序
- 归并排序
- 二路归并排序
- 多路归并排序
选择排序
每次遍历数组 将最小的元素追加到数组的头部 平均复杂度是O(n^2)
插入排序
遍历原始列表 每次选中一个元素 加入到新的排序列表中
非比较类排序
- 计数排序
- 桶排序
- 基数排序
冒泡排序
两层for循环 每次比较相邻的两个 只要 右边 小于左边 就交换位置
这样每次循环后 会将最大的值放到最右边
def solve(list_data):
for loop_no in range(0, len(list_data)):
for index in range(0, len(list_data) - 1):
if index == len(list_data) - 1:
break
if list_data[index] > list_data[index+1]:
list_data[index], list_data[index+1] = list_data[index+1], list_data[index]
return list_data
list_data = [1, 33, 9, 2, 6, 4, 8, 2, 5, 8, 2, 1, 6, 77,0]
res = solve(list_data)
print(res)
快速排序
思路: 采用分治的思想, 将数组切割成2个子数组 然后每个子数组再拆分成2孙子数组, 然后继续拆分...
定义基准pivot 将小于pivot的放到左边 将大于pivot的放到右边。 这样左边的部分 一定比右边的部分小
然后依次对左边和右边的子数组进行快排即递归调用, 直到整体有序
java快速排序代码示例
// Java
// 调用方法 quickSort([xxx,xxx,xxx])
public static void quickSort(int[] array, int begin, int end) {
if (end <= begin) return;
// 找到标杆
int pivot = partition(array, begin, end);
// 左边进行排序
quickSort(array, begin, pivot - 1);
// 右边进行排序
quickSort(array, pivot + 1, end);
}
static int partition(int[] a, int begin, int end) {
// pivot: 标杆位置
// counter: 小于pivot的元素的个数, [0:counter]必须是 小于pivot
int pivot = end;
int counter = begin;
for (int i = begin; i < end; i++) {
// 如果当前元素小于标杆 则将当前元素移动至 [0:counter]的后面
// 即将a[counter] 和 a[i]进行对调
if (a[i] < a[pivot]) {
int temp = a[counter]; a[counter] = a[i]; a[i] = temp;
counter++;
}
}
// 最后将a[pivot] 挪动到[0:counter]的后边 这样就形成了 左侧元素小于a[pivot] 右侧元素大于 a[pivot]
int temp = a[pivot]; a[pivot] = a[counter]; a[counter] = temp;
// 返回; counter的下标就是a[pivot]所在的位置, 即新的标杆位置
return counter;
}
python快速排序代码示例 不开辟新数组
def quick_sort(begin, end, nums):
# 分治的模版
# step1 中断条件
if begin >= end:
return nums
# step2 当前层的处理逻辑
# 找一个标杆
# 将小于标杆的元素 放到左边; 将大于标杆的元素 放到右边
pivot_index = partition(begin, end, nums)
# step3 拆分子任务 继续下探
# 左半部分排序
quick_sort(begin, pivot_index-1, nums)
# 右半部分排序
quick_sort(pivot_index+1, end, nums)
# 整个数据
return nums
def partition(begin, end, nums):
# 初始化标杆值 就找第一个值
# 初始的标杆下标为begin
pivot = nums[begin]
# 标记比标杆值小的个数
mark = begin
for i in range(begin + 1, end + 1):
# 当前值比标杆值小的话
if nums[i] < pivot:
mark += 1
# 将当前值移动到pivot的左侧
nums[mark], nums[i] = nums[i], nums[mark]
# 最后将标杆值移动到 mark的右侧, 即形成了[0:mark]部分小于标杆值, [mark:end] 大于标杆值
nums[begin], nums[mark] = nums[mark], nums[begin]
return mark
新开辟数组的方案
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
list_data = [1, 33, 9, 2, 6, 4, 8, 2, 5, 8, 2, 1, 6, 77,0]
res = quick_sort(list_data)
print(res)
归并排序
- 将数组一分为二
- 将两个子序列进行归并排序
- 将排序好的子序列 合并
归并排序是一种采用分治法(Divide and Conquer)的典型应用,它是一种稳定的排序方法。这种算法利用了分治的思想,将大问题拆解成为小问题,然后将这些小问题分解,再将分解后的问题进行解决。
归并排序的具体步骤如下:
- 1 分解(Divide):首先将要排序的数组递归地分解为两个子序列,每个子序列包含原数组一半的元素。
- 2 解决(Conquer):对每一个子序列分别使用归并排序进行排序。
- 3 合并(Combine):其次,将已排序的两个子序列合并成一个有序的序列。
在合并过程中,由于两个子序列都是有序的,所以可以采用双指针的方式,
- 一个指针指向左边子序列的起始元素,
- 另一个指针指向右边子序列的起始元素,
- 比较两个指针所指向的元素大小,将较小的元素放入新的数组中,然后移动对应的指针。
- 重复此过程,直到所有元素都被放入新的数组中
归并排序代码示例
public static void mergeSort(int[] array, int left, int right) {
if (right <= left) return;
# 找到中间点
int mid = (left + right) >> 1; // (left + right) / 2
# 将两个子序列进行归并排序
# 左侧部分归并排序 左子数组变得有序
mergeSort(array, left, mid);
# 右侧部分归并排序 右子数组变得有序
mergeSort(array, mid + 1, right);
# 将两个有序的子数组进行合并
merge(array, left, mid, right);
}
public static void merge(int[] arr, in intt left, mid, int right) {
# left, mid 是有序的
# mid, right 是有序的
# 申请一段额外的内存空间
int[] temp = new int[right - left + 1]; // 中间数组
# 定义两个下标 i, 表示左子数组的起始位置
int i = left;
# 定义两个下标 j, 表示右子数组的起始位置
int j = mid + 1;
# 表示已经填入的元素个数
int k = 0;
while (i <= mid && j <= right) {
i 和 j的较小者 取出给temp, 较小者的指针++
temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
}
while (i <= mid) temp[k++] = arr[i++];
while (j <= right) temp[k++] = arr[j++];
for (int p = 0; p < temp.length; p++) {
arr[left + p] = temp[p];
}
// 也可以用 System.arraycopy(a, start1, b, start2, length)
}
python示例
def mergesort(nums, left, right):
if right <= left:
return
mid = (left+right) >> 1
mergesort(nums, left, mid)
mergesort(nums, mid+1, right)
merge(nums, left, mid, right)
def merge(nums, left, mid, right):
temp = []
i = left
j = mid+1
while i <= mid and j <= right:
if nums[i] <= nums[j]:
temp.append(nums[i])
i +=1
else:
temp.append(nums[j])
j +=1
while i<=mid:
temp.append(nums[i])
i +=1
while j<=right:
temp.append(nums[j])
j +=1
nums[left:right+1] = temp
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
arr = [3, 2, 1, 5, 4]
sorted_arr = merge_sort(arr)
print(sorted_arr)