声明:本文如有错误,感谢各位大佬指出,如有疑问请在评论区留言,我会看的,毕竟教学相长。
代码部分均为伪代码,实现代码后续会补充在评论区,需要代码可以在评论区评论哦。
写作目的:希望小白可以看明白,大佬看完能够给我评价
读前须知:大顶堆 递归 分治 时间复杂度 空间复杂度
前言:
1.时间复杂度:就像做一件事的步骤数:步骤越少(如O(1)),效率越高;步骤随问题规模增加而增加(如O(n²)),效率越低。
2.空间复杂度:就像做这件事时需要的工具数量:工具越少(如O(1)),越节省空间;工具随问题规模增加而增加(如O(n)),占用空间越多。
3.大顶堆是一种特殊的二叉树结构,每个父节点的值都大于或等于其子节点的值。这种结构常用于快速获取最大值,例如优先队列的实现。堆顶元素始终是最大值,插入或删除元素后,通过“上浮”或“下沉”操作重新调整堆的结构以保持性质。
4.递归是指函数直接或间接调用自身的过程。它通过将问题分解为更小的同类子问题来解决复杂任务。递归需要明确的终止条件,否则会导致无限循环。例如计算阶乘:n! = n * (n-1)!,递归会不断分解问题直到n=1时停止。
5.分治是一种算法设计策略,将问题拆解为多个独立子问题,分别解决后再合并结果。典型例子是归并排序:将数组一分为二,分别排序后再合并。分治通常包含三步:分解、解决、合并,适合处理大规模或嵌套结构的问题。
第一章:循规蹈矩 - 基础排序
第一节:冒泡排序
思想:像冒泡一样,把最大的数慢慢“冒”到末尾。
过程:重复比较相邻的两个数,如果前面的比后面的大,就交换它们。
for i = 0 to n-1 do
for j = 0 to n-2-i do
if arr[j] > arr[j+1] then
swap(arr[j], arr[j+1])
end if
end for
end for
第二节:选择排序
思想:每次从未排序的部分中选出最小的数,放到已排序部分的末尾。
过程:遍历数组,找到最小值,与当前位置交换。
for i = 0 to n-2 do
min_index = i
for j = i+1 to n-1 do
if arr[j] < arr[min_index] then
min_index = j
end if
end for
swap(arr[i], arr[min_index])
end for
第三节:插入排序
思想:像整理扑克牌一样,把每个新元素插入到已排序部分的正确位置。
过程:从第二个元素开始,与前面的元素比较并插入合适位置。
for i = 1 to n-1 do
key = arr[i]
j = i-1
while j >= 0 and arr[j] > key do
arr[j+1] = arr[j]
j = j-1
end while
arr[j+1] = key
end for
第二章:分而治之 - 进阶排序
第一节:希尔排序
思想:插入排序的升级版,先按大间隔比较,再逐步缩小间隔。
过程:选择一个间隔序列,对每个间隔进行插入排序。
gap = n / 2
while gap > 0 do
for i = gap to n-1 do
temp = arr[i]
j = i
while j >= gap and arr[j-gap] > temp do
arr[j] = arr[j-gap]
j = j - gap
end while
arr[j] = temp
end for
gap = gap / 2
end while
第二节:快速排序
思想:分治法,选一个基准,把小于基准的放左边,大于基准的放右边,再递归处理左右两部分。
过程:选择基准,分区,递归排序。
function quicksort(arr, low, high)
if low < high then
pi = partition(arr, low, high)
quicksort(arr, low, pi-1)
quicksort(arr, pi+1, high)
end if
end function
function partition(arr, low, high)
pivot = arr[high]
i = low - 1
for j = low to high-1 do
if arr[j] < pivot then
i = i + 1
swap(arr[i], arr[j])
end if
end for
swap(arr[i+1], arr[high])
return i+1
end function
第三节:归并排序
思想:分治法,把数组分成两半,分别排序,再合并成一个有序数组。
过程:递归分割,再合并。
function mergeSort(arr, left, right)
if left < right then
mid = (left + right) / 2
mergeSort(arr, left, mid)
mergeSort(arr, mid+1, right)
merge(arr, left, mid, right)
end if
end function
function merge(arr, left, mid, right)
n1 = mid - left + 1
n2 = right - mid
create arrays L[0..n1] and R[0..n2]
for i = 0 to n1-1 do
L[i] = arr[left+i]
end for
for j = 0 to n2-1 do
R[j] = arr[mid+1+j]
end for
i = 0
j = 0
k = left
while i < n1 and j < n2 do
if L[i] <= R[j] then
arr[k] = L[i]
i = i + 1
else
arr[k] = R[j]
j = j + 1
end if
k = k + 1
end while
while i < n1 do
arr[k] = L[i]
i = i + 1
k = k + 1
end while
while j < n2 do
arr[k] = R[j]
j = j + 1
k = k + 1
end while
end function
第四节:堆排序
思想:利用堆这种数据结构进行排序,先建最大堆,再逐个取出堆顶元素。
过程:建堆,交换堆顶与末尾元素,调整堆。
function heapSort(arr)
n = length(arr)
for i = n/2 - 1 down to 0 do
heapify(arr, n, i)
end for
for i = n-1 down to 1 do
swap(arr[0], arr[i])
heapify(arr, i, 0)
end for
end function
function heapify(arr, n, i)
largest = i
left = 2*i + 1
right = 2*i + 2
if left < n and arr[left] > arr[largest] then
largest = left
end if
if right < n and arr[right] > arr[largest] then
largest = right
end if
if largest != i then
swap(arr[i], arr[largest])
heapify(arr, n, largest)
end if
end function
第三章:另辟蹊径 - 非比较排序
第一节:计数排序
思想:统计每个元素出现的次数,然后按顺序输出。
过程:统计频次,累加频次,反向填充结果数组。
function countingSort(arr, k)
n = length(arr)
create array count[0..k] and output[0..n-1]
for i = 0 to k do
count[i] = 0
end for
for i = 0 to n-1 do
count[arr[i]] = count[arr[i]] + 1
end for
for i = 1 to k do
count[i] = count[i] + count[i-1]
end for
for i = n-1 down to 0 do
output[count[arr[i]]-1] = arr[i]
count[arr[i]] = count[arr[i]] - 1
end for
for i = 0 to n-1 do
arr[i] = output[i]
end for
end function
第二节:桶排序
思想:把元素分配到多个桶中,对每个桶分别排序,再合并。
过程:确定桶的数量和范围,分配元素到桶,排序每个桶,合并结果。
function bucketSort(arr, k)
n = length(arr)
create array buckets[0..k-1]
for i = 0 to k-1 do
buckets[i] = empty list
end for
for i = 0 to n-1 do
bucket_index = arr[i] / k
add arr[i] to buckets[bucket_index]
end for
for i = 0 to k-1 do
sort(buckets[i])
end for
concatenate all buckets into arr
end function
第三节:基数排序
思想:按位数从最低位到最高位进行排序。
过程:从个位开始,依次对每一位进行稳定排序。
function radixSort(arr)
max = maximum(arr)
exp = 1
while max / exp > 0 do
countingSort(arr, exp)
exp = exp * 10
end while
end function
function countingSort(arr, exp)
n = length(arr)
create array output[0..n-1] and count[0..9]
for i = 0 to 9 do
count[i] = 0
end for
for i = 0 to n-1 do
digit = (arr[i] / exp) mod 10
count[digit] = count[digit] + 1
end for
for i = 1 to 9 do
count[i] = count[i] + count[i-1]
end for
for i = n-1 down to 0 do
digit = (arr[i] / exp) mod 10
output[count[digit]-1] = arr[i]
count[digit] = count[digit] - 1
end for
for i = 0 to n-1 do
arr[i] = output[i]
end for
end function
总结:
以上三章,由浅入深,由常法至巧思,恰如求学之路:始于规矩,进于智慧,终于通达。
算法 使用场景 时间复杂度 是否稳定 冒泡 选择 插入 小数据 O(n^2) 插入稳定 希尔 中等数据 O(n logn)~O(n^2) 不稳定 快速 通用 O(n logn) 不稳定 归并 稳定排序 O(n logn) 稳定 堆 堆结构 O(n logn) 不稳定 计数 桶 基数 特定数据 O(n+k) 稳定
221

被折叠的 条评论
为什么被折叠?



