igozhang

——

    shell_sort

    用shell语言实现插入排序,希尔排序,冒泡排序,堆排序,选择排序,快速排序,归并排序算法并注释说明时间复杂度及原理
    
    插入排序:
    # 时间复杂度:O(n^2)
    # 原理:插入排序是一种简单的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
    #!/bin/bash
    # 插入排序
    insertion_sort() {
        arr=($@)
        for ((i=1; i<${#arr[@]}; i++))
        do
            tmp=${arr[$i]}
            j=$(($i-1))
            while [ $j -ge 0 -a ${arr[$j]} -gt $tmp ]
            do
                arr[$(($j+1))]=${arr[$j]}
                j=$(($j-1))
            done
            arr[$(($j+1))]=$tmp
        done
        echo ${arr[@]}
    }
    arr=(5 4 3 2 1)
    echo "排序前:${arr[@]}"
    echo "排序后:$(insertion_sort ${arr[@]})"
    希尔排序:
    # 时间复杂度:O(n^1.3)
    # 原理:希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
    #!/bin/bash
    # 希尔排序
    shell_sort() {
        arr=($@)
        gap=${#arr[@]}
        while [ $((gap/=2)) -gt 0 ]
        do
            for ((i=$gap; i<${#arr[@]}; i++))
            do
                tmp=${arr[$i]}
                j=$(($i-$gap))
                while [ $j -ge 0 -a ${arr[$j]} -gt $tmp ]
                do
                    arr[$(($j+$gap))]=${arr[$j]}
                    j=$(($j-$gap))
                done
                arr[$(($j+$gap))]=$tmp
            done
        done
        echo ${arr[@]}
    }
    arr=(5 4 3 2 1)
    echo "排序前:${arr[@]}"
    echo "排序后:$(shell_sort ${arr[@]})"
    冒泡排序:
    # 时间复杂度:O(n^2)
    # 原理:冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
    #!/bin/bash
    # 冒泡排序
    bubble_sort() {
        arr=($@)
        for ((i=0; i<${#arr[@]}; i++))
        do
            for ((j=0; j<$((${#arr[@]}-i-1)); j++))
            do
                if [ ${arr[$j]} -gt ${arr[$(($j+1))]} ]
                then
                    tmp=${arr[$j]}
                    arr[$j]=${arr[$(($j+1))]}
                    arr[$(($j+1))]=$tmp
                fi
            done
        done
        echo ${arr[@]}
    }
    arr=(5 4 3 2 1)
    echo "排序前:${arr[@]}"
    echo "排序后:$(bubble_sort ${arr[@]})"
    堆排序:
    # 时间复杂度:O(nlogn)
    # 原理:堆排序是一种树形选择排序,是对直接选择排序的有效改进。堆的定义如下:具有n个元素的序列(h1,h2,…,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,…,n/2)时称之为堆。
    #!/bin/bash
    # 堆排序
    heap_sort() {
        arr=($@)
        # 建堆
        for ((i=${#arr[@]}/2-1; i>=0; i--))
        do
            heapify $i ${#arr[@]}
        done
        # 堆排序
        for ((i=${#arr[@]}-1; i>=0; i--))
        do
            tmp=${arr[0]}
            arr[0]=${arr[$i]}
            arr[$i]=$tmp
            heapify 0 $i
        done
        echo ${arr[@]}
    }
    # 堆调整
    heapify() {
        start=$1
        end=$2
        root=${arr[$start]}
        while [ $(($start*2+1)) -lt $end ]
        do
            child=$(($start*2+1))
            if [ $child -lt $(($end-1)) -a ${arr[$child]} -lt ${arr[$(($child+1))]} ]
            then
                child=$(($child+1))
            fi
            if [ $root -lt ${arr[$child]} ]
            then
                arr[$start]=${arr[$child]}
                start=$child
            else
                break
            fi
        done
        arr[$start]=$root
    }
    arr=(5 4 3 2 1)
    echo "排序前:${arr[@]}"
    echo "排序后:$(heap_sort ${arr[@]})"
    选择排序:
    # 时间复杂度:O(n^2)
    # 原理:选择排序是一种简单直观的排序算法,它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
    #!/bin/bash
    # 选择排序
    selection_sort() {
        arr=($@)
        for ((i=0; i<${#arr[@]}; i++))
        do
            min=$i
            for ((j=$(($i+1)); j<${#arr[@]}; j++))
            do
                if [ ${arr[$j]} -lt ${arr[$min]} ]
                then
                    min=$j
                fi
            done
            tmp=${arr[$i]}
            arr[$i]=${arr[$min]}
            arr[$min]=$tmp
        done
        echo ${arr[@]}
    }
    arr=(5 4 3 2 1)
    echo "排序前:${arr[@]}"
    echo "排序后:$(selection_sort ${arr[@]})"
    快速排序:
    # 时间复杂度:O(nlogn)
    # 原理:快速排序是对冒泡排序的一种改进,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
    #!/bin/bash
    # 快速排序
    quick_sort() {
        arr=($@)
        __quick_sort 0 $((${#arr[@]}-1))
        echo ${arr[@]}
    }
    # 快速排序递归函数
    __quick_sort() {
        start=$1
        end=$2
        if [ $start -lt $end ]
        then
            i=$start
            j=$end
            base=${arr[$i]}
            while [ $i -lt $j ]
            do
                while [ $i -lt $j -a ${arr[$j]} -ge $base ]
                do
                    j=$(($j-1))
                done
                arr[$i]=${arr[$j]}
                while [ $i -lt $j -a ${arr[$i]} -le $base ]
                do
                    i=$(($i+1))
                done
                arr[$j]=${arr[$i]}
            done
            arr[$i]=$base
            __quick_sort $start $(($i-1))
            __quick_sort $(($i+1)) $end
        fi
    }
    arr=(5 4 3 2 1)
    echo "排序前:${arr[@]}"
    echo "排序后:$(quick_sort ${arr[@]})"
    归并排序:
    # 时间复杂度:O(nlogn)
    # 原理:归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
    #!/bin/bash
    # 归并排序
    merge_sort() {
        arr=($@)
        __merge_sort 0 $((${#arr[@]}-1))
        echo ${arr[@]}
    }
    # 归并排序递归函数
    __merge_sort() {
        start=$1
        end=$2
        if [ $start -lt $end ]
        then
            mid=$((($start+$end)/2))
            __merge_sort $start $mid
            __merge_sort $(($mid+1)) $end
            __merge $start $mid $end
        fi
    }
    # 合并函数
    __merge() {
        start=$1
        mid=$2
        end=$3
        i=$start
        j=$(($mid+1))
        k=0
        tmp=()
        while [ $i -le $mid -a $j -le $end ]
        do
            if [ ${arr[$i]} -lt ${arr[$j]} ]
            then
                tmp[$k]=${arr[$i]}
                i=$(($i+1))
            else
                tmp[$k]=${arr[$j]}
                j=$(($j+1))
            fi
            k=$(($k+1))
        done
        while [ $i -le $mid ]
        do
            tmp[$k]=${arr[$i]}
            i=$(($i+1))
            k=$(($k+1))
        done
        while [ $j -le $end ]
        do
            tmp[$k]=${arr[$j]}
            j=$(($j+1))
            k=$(($k+1))
        done
        for ((i=$start; i<=$end; i++))
        do
            arr[$i]=${tmp[$(($i-$start))]}
        done
    }
    arr=(5 4 3 2 1)
    echo "排序前:${arr[@]}"
    echo "排序后:$(merge_sort ${arr[@]})"
    

    MP3