美文网首页
各种排序算法

各种排序算法

作者: Dragon_boy | 来源:发表于2020-08-20 17:51 被阅读0次

    冒泡排序

    从第一个数开始,相邻两个数比较,前一个大于后一个,则调换,重复这个过程。代码实现:
    python:

    def bubbling_sort(array):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
    
        for i in range(0, array_len):
            swap_flag = True
            for j in range(0, array_len - i - 1):
                if array[j] > array[j+1]:
                    temp = num[j]
                    num[j] = num[j+1]
                    num[j+1] = temp
                    swap_flag = False
            if swap_flag:
                return
    

    嵌套循环,时间复杂度为O(n^2)

    其次,介绍算法稳定性概念,比如一个数组,a[i]=a[j],使用排序算法后,如果二者位置没有交换,则算法稳定。

    因此,冒泡算法稳定。

    选择排序

    从数组第一个开始,从下一个元素开始遍历找到最小元素,然后和第一个交换,以此类推,代码实现:
    python:

    def chose_sort(array):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
    
        for i in range(0, array_len):
            min = array[i]
            temp_index = i
            for j in range(i+1, array_len):
                if array[j] < min:
                    min = array[j]
                    temp_index = j
            if i != temp_index:
                temp = array[i]
                array[i] = array[temp_index]
                array[temp_index] = temp
    

    时间复杂度为O(n^2),不过算法不稳定,比如(2,2,1),第一个2会和1交换。

    插入排序

    从数组第一个元素开始,如果第二个元素小于第一个元素,则放到第一个元素的位置,如果第三个元素小于第二个元素,则放到第二个元素的位置,其它元素的索引加1,依次类推。代码实现:
    python:

    def insert_sort(array):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
    
        for i in range(1, array_len):
            for j in range(0, i + 1):
                if array[i] < array[j]:
                    break
                if j <= i:
                    temp_index = i
                    current = array[i]
                    while temp_index > j:
                        temp = array[temp_index]
                        array[temp_index] = array[temp_index - 1]
                        array[temp_index - 1] = current
                        temp_index -= 1
                    array[j] = current
    

    快速排序

    将第一个元素作为基准参考,将其保存到临时变量中,然后start和end指定数组开头序号+1和数组末尾序号,从end开始和临时变量比较,如果array[end]>=临时变量,end向前移一位,然后继续比较,否则较其作为临时变量,然后从start那里开始比较,重复上面过程,直到start成为临时变量,然后换到end那里,直到start>=end结束,结果就是以当前临时变量为基准,小于或等于该值的都在左边,其它的在右边,然后对两边执行上述操作即可,代码实现:
    python:

    def quick_sort(array, start=0, end=0):
        if not array or len(array) <= 1 or start > end:
            return
    
        if start ==0 and end == 0:
            end = len(array) - 1
    
        start_temp = start
        end_temp = end
        temp = array[start_temp]
        while start_temp < end_temp:
            while start_temp < end_temp and array[end_temp] >= temp:
                end_temp -= 1
            if start_temp < end_temp:
                array[start_temp] = array[end_temp]
                start_temp += 1
            while start_temp < end_temp and array[start_temp] <= temp:
                start_temp += 1
            if start_temp < end_temp:
                array[end_temp] = array[start_temp]
                end_temp -= 1
        array[start_temp] = temp
        quick_sort(array, start, start_temp - 1)
        quick_sort(array, start_temp + 1, end);
    

    算法时间复杂度为O(nlogn),不过这是平均复杂度,极端情况可能为O(n^2),其次算法稳定性也很差。

    归并排序

    先递归分解数组,然后合并有序数组,代码实现:
    python:

    def merge_array(array, first, middle, last, array_temp):
        i = first
        j = middle + 1
        temp = 0
        while i <= middle and j <= last:
            if array[i] <= array[j]:
                array_temp[temp] = array[i]
                i += 1
            else:
                array_temp[temp] = array[j]
                j += 1
            temp += 1
        while i <= middle:
            array_temp[temp] = array[i]
            i += 1
            temp += 1
        while j <= last:
            array_temp[temp] = array[j]
            j += 1
            temp += 1
        for k in range(0, temp):
            array[first + k] = array_temp[k]
    
    def rec_merge_sort(array, first, last, array_temp):
        if first < last:
            middle = (first + last) / 2
            rec_merge_sort(array, first, middle, array_temp)
            rec_merge_sort(array, middle + 1, last, array_temp)
            merge_array(array, first, middle, last, array_temp)
    
    def merge_sort(array):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
        array_temp = [0] * array_len
        rec_merge_sort(array, 0, array_len - 1, array_temp)
    

    时间复杂度为O(nlogn),算法稳定。

    堆排序

    先将数组最大堆初始化,然后将最大堆的顶部数和最后面的待交换数交换,然后进行最大堆调整,调整后最大的数位于顶部,持续交换到根部位置。

    最大堆的概念是节点要大于等于左右子节点的值。同时,堆中,如果父节点索引为i,则左子节点为2i+1,右子节点为2i+2,若子节点为i,则父节点为(i-1)/2。调整最大堆就是从第一个非叶子节点开始,使用相关函数调整,一直调整到根节点。

    调整最大堆,对于索引i,则和它的左右子节点比较,如果左右子节点的值大于该节点,则交换,然后继续下去。代码实现:
    python:

    def swap(array, array_a, array_b):
        temp = array[array_a]
        array[array_a] = array[array_b]
        array[array_b] = temp
    
    def max_heap_down(array, current, last):
        max = current
        while True:
            if 2 * current + 1 <= last and array[2 * current + 1] > array[max]:
                max = 2 * current + 1
            if 2 * current + 2 <= last and array[2 * current + 2] > array[max]:
                max = 2 * current + 2
            if max != current:
                swap(array, current, max)
                current = max
            else:
                return
    
    def initial_max_heap(array, array_len):
        for i in range((array_len - 1) / 2, -1, -1):
            max_heap_down(array, i, array_len - 1)
    
    
    def heap_sort(array):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
        initial_max_heap(array, array_len)
        swap(array, 0, array_len - 1)
        for i in range(array_len - 2, 0, -1):
            max_heap_down(array, 0, i)
            swap(array, 0, i)
    

    算法复杂度为O(nlogn),算法不太稳定。

    计数排序

    适合有特性的数组,比如正整数排序。设最大范围为m,建立一个m+1长的数组,用于记录某个正整数有几个,然后遍历要排序数组,把对应数字的个数记录下来,再通过该数组进行排序。代码实现:
    python:

    def counting_sort(array, max):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
        temp_array = [0] * (max + 1)
        for i in range(0, array_len):
            temp_array[array[i]] += 1
        temp = 0
        for i in range(0, max + 1):
            if temp >= array_len:
                break
            while temp_array[i] > 0:
                array[temp] = i
                temp_array[i] -= 1
                temp += 1
    

    算法时间复杂度为O(n+m),算法比较稳定。

    桶排序

    将一段区间分为n等分,比如100个数字,设置10个桶,1-10再第一个桶,依次类推。然后遍历数组,将对应的数字放在对应桶中,对每个桶中的数组进行排序,然后回到原数组。代码实现:
    python:

    def bucket_sort(array):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
        max_num = max(array)
        min_num = min(array)
        bucket_num = 10
        if (max_num - min_num + 1) < 10:
            bucket_num = max_num - min_num
        avg_num = (max_num - min_num) / bucket_num
        temp_array = [[] for i in range(bucket_num)]
        for i in range(array_len):
            bucket_pos = (array[i] - min_num + 1) / avg_num
            if bucket_pos >= bucket_num:
                bucket_pos = bucket_num - 1
            temp_array[bucket_pos].append(array[i])
    
        temp = 0
        for i in range(bucket_num):
            quick_sort(temp_array[i])
            for j in temp_array[i]:
                array[temp] = j
                temp += 1
    

    若有n个数字,m个桶,每个桶存k个数,则时间复杂度为O(n)+O(m)*klgk,算法稳定性取决于每个桶使用什么排序算法。

    基数排序

    基数排序可以理解为一种桶排序,它从最低位数字开始排序,依次到高位数字结束,代码实现:
    python:

    def radix_sort(array):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
        i = 0   # 最低位
        max_num = max(array)
        j = len(str(max_num)) # 最大值位数
        while i < j:
            bucket_list = [[] for i in range(10)]
            for num in array:
                bucket_list[int(x / (10**i)) % 10].append(num)
    
            array.clear()
            for i in bucket_list:
                for j in i:
                    array.append(j)
    
            i += 1
    

    时间复杂度位O(n),算法稳定。

    希尔排序

    这是一种插入排序的改良。希尔排序会先设定一个步长,这里选择数组长度的一半,每个一个步长,组成一个要排序的数组进行排序,然后多个数组进行插入排序,一轮排序后,步长除以2,重复上面的步骤,直到步长为1,就是整个数组进行一次插入排序,终止。代码实现:
    python:

    def shell_sort(array):
        if not array or len(array) <= 1:
            return
        array_len = len(array)
        step = array_len / 2
        while step > 0:
            for i in range(step):
                for j in range(i + step, array_len, step):
                    for k in range(i ,j, step):
                        if array[j] < array[k]:
                            break
                        else: 
                            k += step
    
                        if k < j:
                            temp_k = k
                            temp = array[i]
                            while temp_k >= k:
                                tmp = array[temp_k]
                                array[temp_k] = array[temp_k + step]
                                array[temp_k + step] = tmp
                                temp_k -= step
                            array[k] = tmp
    
            step /= 2
    

    时间复杂度上比插入排序好,算法稳定。

    相关文章

      网友评论

          本文标题:各种排序算法

          本文链接:https://www.haomeiwen.com/subject/wjtejktx.html