从冒泡到基数:排序算法全解析

声明:本文如有错误,感谢各位大佬指出,如有疑问请在评论区留言,我会看的,毕竟教学相长。

代码部分均为伪代码,实现代码后续会补充在评论区,需要代码可以在评论区评论哦。

写作目的:希望小白可以看明白,大佬看完能够给我评价

读前须知:大顶堆 递归 分治 时间复杂度 空间复杂度

前言:

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)

稳定

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值