zoukankan      html  css  js  c++  java
  • 常用排序算法的Python实现

    引言

           排序算法稳定性的简单形式化定义为:如果Ai = Aj,排序前Ai在Aj之前,排序后Ai还在Aj之前,则称这种排序算法是稳定的。通俗地讲就是保证排序前后两个相等的数的相对顺序不变。

      对于不稳定的排序算法,只要举出一个实例,即可说明它的不稳定性;而对于稳定的排序算法,必须对算法进行分析从而得到稳定的特性。需要注意的是,排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种条件下也可以变为不稳定的算法。

    选择排序

            选择排序也是一种简单直观的排序算法。它的工作原理很容易理解:初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列;然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

    代码实现

    def swap(lyst, i, j):
        temp = lyst[i]
        lyst[i] = lyst[j]
        lyst[j] = temp
    # 选择排序
    def selectionSort(lyst):
        i = 0
        while i < len(lyst) - 1:
            minIndex = i
            j = i + 1
            while j < len(lyst):
                if lyst[j] < lyst[minIndex]:
                    minIndex = j
                j += 1
            if minIndex != i:
                swap(lyst, minIndex, i)
            i += 1

    冒泡排序

           冒泡排序它重复地走访过要排序的元素,依次比较相邻两个元素,如果他们的顺序错误就把他们调换过来,直到没有元素再需要交换,排序完成。这个算法的名字由来是因为越小(或越大)的元素会经由交换慢慢“浮”到数列的顶端。

      冒泡排序算法的运作如下:

    1. 比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。
    2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
    3. 针对所有的元素重复以上的步骤,除了最后一个。
    4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

    代码实现

    def swap(lyst, i, j):
        temp = lyst[i]
        lyst[i] = lyst[j]
        lyst[j] = temp
    # 冒泡排序
    def bubbleSort(lyst):
        n = len(lyst)
        while n > 1:
            i = 1
            while i < n:
                if lyst[i] < lyst[i - 1]:
                    swap(lyst, i, i - 1)
                i += 1
            n -= 1

    插入排序

    具体算法描述如下:

    1. 从第一个元素开始,该元素可以认为已经被排序
    2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
    3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
    4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
    5. 将新元素插入到该位置后
    6. 重复步骤2~5

    代码实现

    def insertSort(lyst):
        i=1
        while i<len(lyst):
            itemToInsert=lyst[i]
            j=i-1
            while j>=0:
                if itemToInsert<lyst[j]:
                    lyst[j+1]=lyst[j]
                    j-=1
                else:
                    break
            lyst[j+1]=itemToInsert
            i+=1

    快速排序

           快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序n个元素要O(nlogn)次比较。在最坏状况下则需要O(n^2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他O(nlogn)算法更快,因为它的内部循环可以在大部分的架构上很有效率地被实现出来。

      快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。步骤为:

    1. 从序列中挑出一个元素,作为"基准"(pivot).
    2. 把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作。
    3. 对每个分区递归地进行步骤1~2,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了。

    代码实现

    def quickSort(lyst):
        quickSortHelper(lyst,0,len(lyst)-1)
    def quickSortHelper(lyst,left,right):
        if left<right:
            pivotLocation=partition(lyst,left,right)
            quickSortHelper(lyst,left,pivotLocation-1)
            quickSortHelper(lyst,pivotLocation+1,right)
    def partition(lyst,left,right):
        middle=(left+right)//2
        pivot=lyst[middle]
        lyst[middle]=lyst[right]
        lyst[right]=pivot
        boundary=left
        for index in range(left,right):
            if lyst[index]<pivot:
                swap(lyst,index,boundary)
                boundary+=1
        swap(lyst,right,boundary)
        return boundary

    归并排序

           归并排序是创建在归并操作上的一种有效的排序算法,效率为O(nlogn),1945年由冯·诺伊曼首次提出。

      归并排序的实现分为递归实现非递归(迭代)实现。递归实现的归并排序是算法设计中分治策略的典型应用,我们将一个大问题分割成小问题分别解决,然后用所有小问题的答案来解决整个大问题。非递归(迭代)实现的归并排序首先进行是两两归并,然后四四归并,然后是八八归并,一直下去直到归并了整个数组。

      归并排序算法主要依赖归并(Merge)操作。归并操作指的是将两个已经排序的序列合并成一个序列的操作,归并操作步骤如下:

    1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
    2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
    3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
    4. 重复步骤3直到某一指针到达序列尾
    5. 将另一序列剩下的所有元素直接复制到合并序列尾

    代码实现

    def mergesort(seq):
        mid = len(seq) // 2
        lft, rgt = seq[:mid], seq[mid:]
        if len(lft) > 1: lft = mergesort(lft)
        if len(rgt) > 1: rgt = mergesort(rgt)
        res = []
        while lft and rgt:
            if lft[-1] >= rgt[-1]:
                res.append(lft.pop())
            else:
                res.append(rgt.pop())
        res.reverse()
        return (lft or rgt) + res

  • 相关阅读:
    集合模拟斗地主
    泛型
    Iterator迭代器
    嵌入式应用开发过程中用到的函数
    Keil ,source insight使用技巧等
    Socket应用demo 获取IP
    tftp安装、配置,ubuntu联网设置
    C++基础三——类、结构体、联合体
    C++基础二——清华
    STM32笔记
  • 原文地址:https://www.cnblogs.com/austinjoe/p/9388992.html
Copyright © 2011-2022 走看看