算法与数据结构(五)--排序

排序算法的稳定性

稳定排序算法会让原有相等键值的记录维持相对次序
例如:

(4,1) (3,1) (3,7) (5,6) 

排序后

(3,1) (3,7) (4,1) (5,6)-------稳定排序
(3,7) (3,1) (4,1) (5,6)------非稳定排序

冒泡排序

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。
算法实现:

def bubble_sort(alist):
    n = len(alist)
    for i in range(n-1):
        count = 0
        for j in range(n-1-i):
            if alist[j]>alist[j+1]:
                alist[j],alist[j+1] = alist[j+1],alist[j]
                count += 1
        if 0 == count:
            return

if __name__ == '__main__':
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    bubble_sort(li)
    print(li)
时间复杂度:

最坏时间复杂度:O(n^2)
最优时间复杂度:O(n)

稳定性:

-稳定

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。

def select_sort(alist):
    n = len(alist)
    for j in range(0, n-2):
        min_index = j
        for i in range(j+1,n):
            if alist[min_index] > alist[i]:
                min_index = i
        alist[j], alist[min_index] = alist[min_index], alist[j]

if __name__ == '__main__':
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    select_sort(li)
    print(li)
时间复杂度:

最坏时间复杂度:O(n^2)
最优时间复杂度:O(n^2)

稳定性

不稳定,举例([5,8,5,2,9])。即使比较的时候换成>=,也是不稳定的,举例([5,8,2,2,9])

插入排序

插入排序(Insertion sort)是一种简单直观且稳定的排序算法。插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。

def insert_sort(alist):
    n = len(alist)
    for j in range(1,n):
        i = j
        while i > 0:
            if alist[i] < alist[i-1]:
                alist[i], alist[i-1] = alist[i-1], alist[i]
                i -= 1
            else:
                break

if __name__ == '__main__':
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    insert_sort(li)
    print(li)
时间复杂度:

最坏时间复杂度:O(n^2)
最优时间复杂度:O(n)

稳定性:

稳定

希尔排序

希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

def shell_sort(alist):
    n = len(alist)
    gap = n // 2
    while gap >= 1:
        for j in range(gap,n):
            i = j
            while i > 0:
                if alist[i] < alist[i-gap]:
                    alist[i], alist[i-gap] = alist[i-gap], alist[i]
                    i -= gap
                else:
                    break
        gap //= 2
        
if __name__ == '__main__':
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    shell_sort(li)
    print(li)
时间复杂度:

最坏时间复杂度:O(n^2)
最优时间复杂度:视具体情况的步长而定

稳定性:

不稳定

快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

def quick_sort(alist, head, tail):
    if head >= tail:
        return
    mid_value = alist[head]
    low = head
    high = tail

    while low < high:
        while low < high and alist[high] >= mid_value:
            high -= 1
        alist[low] = alist[high]
        while low < high and alist[low] < mid_value:
            low += 1
        alist[high] = alist[low]
    alist[low] = mid_value
    quick_sort(alist, head, low-1)   #不能传入alist[:low-1],这样传入的是一个新列表
    quick_sort(alist, high+1, tail)

if __name__ == '__main__':
    li = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(li)
    n = len(li)
    quick_sort(li, 0, n-1)
    print(li)
时间复杂度:

最坏时间复杂度:O(n^2)
最优时间复杂度:O(nlogn)—每次拆分执行n次,拆分logn次

稳定性:

不稳定

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值