数据结构07-选择排序及python实现

东阳的学习记录,坚持就是胜利!

选择排序的基本思想是:每一趟(如第i趟)在后面n-i+1(i = 1, 2, …, n-1)个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到第n-1趟做完,待排序元素只剩下1个,就不用再选了。堆排序是重点

简单排序算法

根据上面的简单排序思想,可以很直观地得出简单排序算法的思想。

def select_sort(alist):
    l = len(alist)
    for i in range(l-1):
        min_index = i
        j = i+1
        
        # 找出最小关键字的下标——min_index
        while j < l:
            if alist[j] < alist[min_index]: 
                min_index = j
            j += 1
        # 交换
        if (min_index != i):
            alist[i], alist[min_index] = alist[min_index], alist[i]

算法分析

  • 时间复杂度:都是O(n**2)
  • 空间复杂度:O(1)
  • 不稳定

堆排序

堆排序是一种树形选择排序方法,其特点是:在排序过程中,将L[1…n]视为一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大或最小的元素。

构造初始堆

堆的定义如下:n个关键字序列L[1…n]称为堆,当且仅当该序列满足。

  • L(i) < L(2i) 且 L(i) < L(2i+1) (小根堆)
  • L(i) > L(2i) 且 L(i) < L(2i+1) (大根堆)

对初始序列建堆,是一个反复筛选的过程。n个结点的完全二叉树,最后一个结点是第 n // 2个结点的孩子。从该结点开始筛选,如果根节点的关键字小于其孩子的关键字,则与之交换。对[n //2 ~ 1]执行同样的操作。

在这里插入图片描述

def build_max_heap(alist):
	"""构建初始堆"""
    l = len(alist)
    i = l // 2
    while i > 0:
        i -= 1
        adjust_down(alist,i,l)

def adjust_down(alist, k, l):
    """
    alist: 
    k: 当前正在调整的双亲结点的编号
    l: 
    """
    
    alist[0] = alist[k]
    i = 2 * k
    while i < l:
        if i < l - 1 and alist[i] < alist[i+1]:
            i += 1
        if alist[0] > alist[i]:
            break
        else:
            alist[k] = alist[i]
            k = i
        i *= 2
    alist[k] = alist[0]

向下调整的时间与树高有关,为O(h),即log(n)。建堆过程中每次向下调整时,大部分结点的高度都较小。因此,在元素个数为n的序列上建堆,其时间复杂度为O(n)。

对构建好的大根堆进行排序

应用堆这种数据结构进行排序的思路也很简单:首先将存放在L[1, n]中的各个元素简称初始堆,由于堆本身的特性,堆定元素就是最大值。输出堆定元素后,通常将堆底元素送入堆顶,此时大根堆的结构被迫环,需要重新执行一次向下调整。

def swap_param(L, i, j):
    L[i], L[j] = L[j], L[i]
    return L
    
def heap_sort(alist):
    alist.insert(0, 0)
    l = len(alist)
    build_max_heap(alist)
    i = l
    while i > 1:
        swap_param(alist, 1, i-1)
        adjust_down(alist, 1, i-1)
        i -= 1
    alist.pop(0)

堆的插入和删除

由于堆顶元素或为最大值或为最小值,删除堆顶元素时,先将堆的最后一个元素与堆顶元素交换,再进行向下调整。再对堆进行插入操作时,先将新结点放在堆的末端,再对这个新结点执行向上调整的操作。

def adjust_up(alist, k):
    """向上调整"""
    alist[0] = alist[k]
    i = k // 2
    while i > 0 and alist[i] < alist[0]:
        alist[k] = alist[i]  # 双亲结点下调
        k = i
        i = k // 2  # 继续向上比较
    alist[k] = alist[0]

插入操作示意图

算法分析

  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(1)
  • 不稳定
  • 适用于顺序存储和链式存储(线索二叉树??)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东阳z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值