Python实现常见排序算法下

一、快速排序

  快速排序(Quick Sort),又称为划分交换排序(Partition-exchange Sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要笑,然后在按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

  

  1、快速排序过程:

    ① 从数列中选出一个元素,称为“基准”(pivot)。

    ② 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准大的摆在基准的后面(相同的数,可以放到任意一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

    ③ 递归(recursive)把小于基准值元素子数列和大于基准值元素的子数列排序。

    递归的的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。

 

    

     

  

  2、python实现过程:

    这里提供两种快速排序的方式,基本思想一样,第一种是在原有列表进行操作(通过游标进行),第二种则是新建左右子列表进行存储。

# coding=utf-8


def quick_sort1(ls, start, end):
    """
        快速排序-1
        low 和 high 分别指向序列的头和尾
        low += 1, high -= 1
        在low自增过程中,直到找到大于 mid_val 的下标
        在high自增减过程中,直到找到小于 mid_val 的小标
        然后将这两个值交换
    """

    # 递归退出条件
    if start >= end:
        return

    low = start
    high = end
    mid_val = ls[low]

    while low < high:
        while low < high and ls[high] > mid_val:
            high -= 1
        ls[low] = ls[high]

        while low < high and ls[low] < mid_val:
            low += 1
        ls[high] = ls[low]

    ls[low] = mid_val

    print("mid:", mid_val, ls)

    quick_sort1(ls, start, low - 1)  # 左边的子序列
    quick_sort1(ls, low + 1, end)    # 右边的子序列

    return ls


def quick_sort2(ls):
    """快速排序-2"""

    # 递归退出条件
    if len(ls) <= 1:
        return ls

    left_ls, right_ls = [],[]
    mid_val = ls[0]
    for i in range(1, len(ls)):
        if ls[i] < mid_val:
            left_ls.append(ls[i])
        else:
            right_ls.append(ls[i])

    print(left_ls, mid_val, right_ls)

    # 递归调用,左右子列表
    left_res = quick_sort2(left_ls)
    right_res = quick_sort2(right_ls)

    return left_res + [mid_val] + right_res



if __name__ == "__main__":
    ls1 = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    ls2 = [54, 26, 93, 17, 77, 31, 44, 55, 20]

    print("before:", ls1)
    res1 = quick_sort1(ls1, 0, len(ls1) - 1)
    print("quick sort1: ", res1)

    print("-"*50)
    print("before: ", ls2)
    res2 = quick_sort2(ls2)
    print("quick sort2:", res2)

执行结果:

      

    

  3、时间复杂度:

    最优时间复杂度:O(nlogn)

    最坏时间复杂度:O(n2)

    稳定性:不稳定

二、归并排序

  归并排序是采用分治法的一种非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。

  将数组分解最小之后,然后合并两个有序数组,基本思路:比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直到一个数组为空,最后把另外一个数组的剩余部分复制过来即可。

 

  1、归并排序过程,图示:

    

分而治之

   可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n。

   

再来看看阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。

 

  2、python实现过程:

    先把序列拆分成 left_ls 和 right_ls ,然后再合并成一个res。

# coding=utf-8


def merge_sort(ls):
    """归并排序"""
    n = len(ls)

    # 递归退出条件
    if n <= 1:
        return ls

    mid = n // 2

    # 1、拆分子序列
    left_ls = merge_sort(ls[:mid])
    right_ls = merge_sort(ls[mid:])

    # 2、合并子序列:left_ls 和 right_ls
    left_point, right_point = 0, 0
    res = []

    # 当left_ls或者right_ls 结束,就会退出 while,而另外一个则可能未结束,所有后面需要 res +=
    while left_point < len(left_ls) and right_point < len(right_ls):
        # 比较两个子序列,小的先加入到 res[]
        if left_ls[left_point] < right_ls[right_point]:
            res.append(left_ls[left_point])
            left_point += 1
        else:
            res.append(right_ls[right_point])
            right_point += 1
    print("res:", res)

    res += left_ls[left_point:]
    res += right_ls[right_point:]

    return res


if __name__ == "__main__":
    ls = [54, 26, 93, 17, 77, 31, 44, 55, 20]

    print("before: ", ls)
    res = merge_sort(ls)
    print("merge sort: ", res)

执行结果:

      

 

  3、时间复杂度:

    最优时间复杂度:O(nlogn)

    最坏时间复杂度:O(nlogn)

    稳定性:稳定

 

 

三、二分查找

  二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好,其缺点是要求待查找表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

  基本思想:假设表中元素是按升序排序,将表中间位置记录关键字与查找关键字比较,如果两者相等,则查找成功,否则利用中间位置记录分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一个子表。重复以上过程,知道找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

  

  1、二分查找过程,图示(图片来源网络):

    

 

 

  2、python实现过程:

    这里主要两种实现方式,一种递归,另一种非递归。

# coding=utf-8


def binary_search_recursion(ls, item):
    """二分查找---递归"""
    n = len(ls)
    if n < 1:
        return False

    mid = n // 2

    # 与中间值比较
    if item == ls[mid]:
        return True

    # 去左边子序列查找
    elif item < ls[mid]:
        return binary_search_recursion(ls[:mid], item)

    # 去右边子序列查找
    else:
        return binary_search_recursion(ls[mid + 1:], item)


def binary_search(ls, item):
    """二分查找---非递归"""
    n = len(ls)
    start = 0
    end = n - 1

    while start <= end:
        mid = (start + end) // 2

        if item == ls[mid]:
            return True
        elif item < ls[mid]:
            end = mid - 1
        else:
            start = mid + 1
    return False


if __name__ == "__main__":
    ls = [17, 20, 26, 31, 44, 54, 55, 77, 93]

    num = int(input("请输入一个整数:"))
    res = binary_search(ls, num)
    print("查找结果:", res)

3、时间复杂度:

    最优时间复杂度:O(nlogn)

    最坏时间复杂度:O(n2)

    稳定性:稳定


http://www.niftyadmin.cn/n/853179.html

相关文章

ASP.Net网站开发的单元测试方案

用vs2005的团队开发版应该可以&#xff0c;但是&#xff0c;我的几个机子的环境都是vs2005专业版&#xff0c;要全部换过来&#xff0c;实在是感觉很头痛。其它的解决方案&#xff0c;NUnit&#xff0c;在2003时我记得还是可以的&#xff0c;现在的代码都搞到App_Code下去了&am…

机器学习之推荐系统的基础知识

本文转载至博客园的小编周旭龙&#xff1a;初探机器学习之推荐系统的基础知识 一、推荐系统是神马 维基百科这样解释道&#xff1a;推荐系统属于资讯过滤的一种应用。推荐系统能够将可能受喜好的资讯或实物&#xff08;例如&#xff1a;电影、电视节目、音乐、书籍、新闻、图…

WEB页的局部打印

关于WEB页的局部打印问题&#xff1a; JScript code ----------------------------------------<script language"javascript"><!--functionPrintNote() { varPrintWinwindow.open(about:blank,Print); PrintWin.document.write(<object id"WebBrow…

基于用户的协同过滤推荐算法原理和实现分析

本文转载自nieson 基于用户的协同过滤推荐算法原理和实现 在推荐系统众多方法中&#xff0c;基于用户的协同过滤推荐算法是最早诞生的&#xff0c;原理也较为简单。该算法1992年提出并用于邮件过滤系统&#xff0c;两年后1994年被 GroupLens 用于新闻过滤。一直到2000年&…

centos---centos用户组权限添加删除用户问题总结

2019独角兽企业重金招聘Python工程师标准>>> 1.Linux操作系统是多用户多任务操作系统&#xff0c;包括用户账户和组账户两种 细分用户账户&#xff08;普通用户账户&#xff0c;超级用户账户&#xff09;除了用户账户以为还有组账户所谓组账户就是用户账户的集合&am…

HDU 2066 一个人的旅行【dijkstra】

Problem Description虽然草儿是个路痴&#xff08;就是在杭电待了一年多&#xff0c;居然还会在校园里迷路的人&#xff0c;汗~),但是草儿仍然很喜欢旅行&#xff0c;因为在旅途中 会遇见很多人&#xff08;白马王子&#xff0c;^0^&#xff09;&#xff0c;很多事&#xff0c;…

centos 编译 安装 protobuf

link&#xff1a;http://dbua.iteye.com/blog/1633079 yum -y install gcc gcc-c yum -y install make 下载protobuf-2.4.1.tar.gz&#xff1a;http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.gz安装&#xff1a;tar zxvf protobuf-2.4.1.tar.gzcd protobuf-2.4.1./…

SQL 排名函数面试宝典

本文转载自 sql 四大排名函数---&#xff08;ROW_NUMBER、RANK、DENSE_RANK、NTILE&#xff09;简介 1.ROW_NUMBER() 定义&#xff1a;ROW_NUMBER()函数作用就是将select查询到的数据进行排序&#xff0c;每一条数据加一个序号&#xff0c;他不能用做于学生成绩的排名&#x…