algo 01. 归并排序和快速排序

开始的话:
从基础做起,不断学习,坚持不懈,加油。
一位爱生活爱技术来自火星的程序汪

1. 归并排序

用到了分治思想:将一个大问题分解成小问题,小问题解决了,大问题也就解决了。用到了分治思想:将一个大问题分解成小问题,小问题解决了,大问题也就解决了。
这个和递归recursion很像,分治一般都是用递归来实现。

分治是一种解决问题的处理思想
递归是一种编程技巧

写递归的技巧:

  1. 递推公式;
  2. 终止条件

思想:
把一个数组从中间拆分开,一直拆分到length为1,然后 比较 合并,得到最终的排序好的数组。
有一个拆分( p a r t part part) 合并( m e r g e merge merge)的过程
给定一个从p到r的数组

递推公式:
merge_sort(p…r) = merge(merge_sort_part(p…q), merge_sort_part(q+1…r))

终止条件:
p == r 不用再继续分解

细节
在merge中,分别遍历两个数组进行比较,每次把小的值放到一个临时数组中,比较完把非空的数组中的值拷贝到临时数组。并最终把临时数组复制到原始数组中。

s h o w show show m y my my c o d e code code

# -*- coding:utf-8 -*-
"""
@contact: adonis_wu@outlook.com
@file: myMergeSort.py
@time: 2018/11/29 09:41
"""
__author__ = '? adowu ?'


def merge_sort(arr: list, n: int):
    """
    :param arr: array
    :param n: array size
    :return: sorted array
    """
    merge_sort_part(arr, 0, n - 1)

    return arr


def merge_sort_part(arr: list, start: int, end: int):
    """
    :param arr: array
    :param start: current start
    :param end:  current end
    :return: sorted array
    """
    if start == end:
        return
    mid_left = int((start + end) / 2)
    mid_right = int((start + end) / 2) + 1
    merge_sort_part(arr, start, mid_left)
    merge_sort_part(arr, mid_right, end)
    merge(arr, start, mid_left, mid_right, end)


def merge(original_array: list, left_index: int, mid_left_index: int, mid_right_index: int, right_index: int):
    """
    :param original_array:  original array
    :param left_index:  current left index
    :param mid_left_index:   current mid left index
    :param mid_right_index:   current mid right index
    :param right_index: current right index
    :return:
    """
    tmp_array = [0] * (right_index - left_index + 1)
    tmp_index = 0
    p, q, j, k = left_index, mid_left_index, mid_right_index, right_index

    while (p <= q) and (j <= k):
        if original_array[p] <= original_array[j]:
            tmp_array[tmp_index] = original_array[p]
            p += 1
        else:
            tmp_array[tmp_index] = original_array[j]
            j += 1
        tmp_index += 1
    #   rest elements copy to original array
    start, end = p, q
    if j <= k:
        start, end = j, k
    tmp_array[tmp_index:] = original_array[start:end + 1]
    original_array[left_index:right_index + 1] = tmp_array
    return original_array

if __name__ == '__main__':
    a1 = [3, 5, 6, 7, 8]
    a2 = [2, 2, 2, 2]
    a3 = [4, 3, 2, 1]
    a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9]
    merge_sort(a1, len(a1))
    print(a1)
    merge_sort(a2, len(a2))
    print(a2)
    merge_sort(a3, len(a3))
    print(a3)
    merge_sort(a4, len(a4))
    print(a4)

2. 快速排序

快速排序,简称为“快排”,运用的也是分治思想。

思想:
给定一个从p到r的数组,首先会随机选择一个值作为分区点:pivot,
然后遍历 余下 的数据, 小的放左边,大的放右边,一直这样分下去。

递推公式:
quick_sort(p…r) = quick_sort_part(p,q-1) + quick_sort_part(q+1, r)

终止条件:
p >= r

细节:
归并中有一个merge,快排中有一个partition在partition中为了保证是原地排序:利用两个下标,将小的值放在pivot的左边,大值放在右边。

s h o w show show m y my my c o d e code code

# -*- coding:utf-8 -*-
"""
@contact: adonis_wu@outlook.com
@file: myQuickSort.py
@time: 2018/11/29 14:26
"""
__author__ = '? adowu ?'
import random


def quick_sort(arr: list, n: int):
    """
    :param arr: array
    :param n:  len array
    :return: sorted array
    """
    quick_sort_part(arr, 0, n - 1)


def quick_sort_part(arr: list, start: int, end: int):
    """
    :param arr: original array
    :param start: current start index
    :param end: current  end index
    :return:
    """
    if start >= end:
        return

    pivot_index = partition(arr, start, end)
    quick_sort_part(arr, start, pivot_index - 1)
    quick_sort_part(arr, pivot_index + 1, end)


def partition(arr: list, start: int, end: int):
    """
    :param arr: original array
    :param start: current start index
    :param end:  current end index
    :return: partition index
    """
    k = random.randint(start, end)
    arr[end], arr[k] = arr[k], arr[end]
    pivot = arr[end]
    first_big_index = start
    for i in range(start, end):
        if arr[i] < pivot:
            arr[first_big_index], arr[i] = arr[i], arr[first_big_index]
            first_big_index += 1
    arr[first_big_index], arr[end] = arr[end], arr[first_big_index]
    return first_big_index


if __name__ == '__main__':
    a1 = [3, 5, 6, 7, 8]
    a2 = [2, 2, 2, 2]
    a3 = [4, 3, 2, 1]
    a4 = [5, -1, 9, 3, 7, 8, 3, -2, 9]
    quick_sort(a1, len(a1))
    print(a1)
    quick_sort(a2, len(a2))
    print(a2)
    quick_sort(a3, len(a3))
    print(a3)
    quick_sort(a4, len(a4))
    print(a4)

谢谢

更多代码请移步我的个人 g i t h u b github github,会不定期更新。
本章代码见 c o d e code code
欢迎关注

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最快的排序算法_桶排序 最快的排序算法 [ 江南孤峰 发表于 2006-11-9 12:57:00 ] /****************************************************************\ 最快的排序算法:   桶 排 序 经分析通过比较的排序算法如,选择排序,插入排序,快速排序,堆排序 等最快为 n*log(n),这是比较排序算法的极限任何通过比较进行排序 的算法都不可能超过这个极限. 现在要介绍的 桶排序 可以超过它为 n ,当然 桶排序 的灵活性却拿不出手,必须要知道待排序数组中最大 的数.下面的程序,首先由用户输入数组的大小,程序随机产生最大数为 不超过 10000 的随机数组,最后输出原始数组,以及排序后的数组. ######################################### 独学而无友,则孤陋而寡闻 诚交天下程序员  ! Q 群: 28011342 ######################################### 编译器: VC ++ 6.0  Author : 江南孤峰   Time :2006--10--27 \****************************************************************/ #i nclude <stdio> #i nclude <malloc> #i nclude <memory> #i nclude <stdlib> #i nclude <ctype> int main(){ int order[10000],total,*array,i; while( 1){ memset(order,0,sizeof(int)*10000); printf("\nPlease input the size of the source array:"); scanf("%d",&total); array = (int *)malloc(sizeof(int)*total + 4); printf("The source array as follow:\n"); for(i = 0; i < total; i ++){ array[i] = rand() 000; printf("%d ",array[i]); order[array[i]] ++; // 这里就是排序,够简洁吧 ! } printf("\nThe array after by order as follow:\n"); for(i = 0; i < 10000; i ++){ while(order[i]){ printf("%d ",i); order[i] --; } } free(array); printf("\nContinue(y/n)? :"); getchar(); i = getchar(); if(isupper(i)) i = tolower(i); if(i == 'n') break; } return 0; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值