数据结构与算法(一)之排序算法

排序算法

python自带排序

a = [7,3,4,1,6]
b = sorted(a)
print(b)
a.sort(reverse=True)
print(a)
[1, 3, 4, 6, 7]
[7, 6, 4, 3, 1]
d = {"2":5,"1":1,"2":3,"5":15,"4":10}
sorted(d.items(),key=lambda x:x[0])
[('1', 1), ('2', 3), ('4', 10), ('5', 15)]

冒泡排序

从头遍历所有样本,进行两两比较,如果是从小到大排序,每次比较大的样本在前都要进行交换,最终将最大值放到最后;每次遍历将当前最大值放到最后,对剩下未排序样本进行重复的遍历比较操作,最终得到排序好的序列。

def bubbling_sort(a):
    for i in range(len(a)-1,0,-1):
        for j in range(1,i+1):
            # 交换两个相邻的样本
            if a[j] < a[j-1]:
                a[j-1],a[j] = a[j],a[j-1]
    
if __name__ == "__main__":
    a = [7,3,4,1,6]
    bubbling_sort(a)
    print(a)
[1, 3, 4, 6, 7]

选择排序

如果是从小到大排序,每次选出最小的样本放到序列的最前面,然后在剩下的样本中选第二小的样本,放到前面,不断重复这个过程。

def select_sort(a):
    for i in range(len(a)-1):
        min_value = float("inf")
        index = -1
        for j in range(i,len(a)):
            if a[j]< min_value:
                index = j
                min_value = a[j]
        a[i],a[index] = a[index],a[i]

if __name__ == "__main__":
    a = [7,3,4,1,6]
    select_sort(a)
    print(a)
[1, 3, 4, 6, 7]

插入排序

从头开始遍历,对于遍历的每个元素i,其前i-1个元素为有序,将其第i个元素插入到前i-1个元素中正确的位置。

def insert_sort(a):
    n = len(a)
    for i in range(1,n):
        for j in range(i,0,-1):
            if a[j]<a[j-1]:
                a[j-1],a[j] = a[j],a[j-1]

if __name__ == "__main__":
    a = [7,3,4,1,6]
    insert_sort(a)
    print(a)
[1, 3, 4, 6, 7]

希尔排序

在插入排序的基础上做的一个升级。通过增量大小对序列分组,对每组分别进行插入排序,然后不断缩小增量。

def shell_sort(a):
    n = len(a)
    gap = n // 2
    while gap >= 1:
        for i in range(gap,n):
            j = i
            while j-gap>=0:
                if a[j]<a[j-gap]:
                    a[j-gap],a[j] = a[j],a[j-gap]
                    j = j-gap
                else:
                    break # 之前的已经排好序,不要再往前比较
        gap = gap // 2
        
if __name__ == "__main__":
    a = [7,3,4,1,6]
    shell_sort(a)
    print(a)                
[1, 3, 4, 6, 7]

快速排序

每次将一个基数放置到正确的位置,用两个指针left和right,分别从左边和右边进行遍历,将右边比基数小的值和左边比基数大的值进行交换,重复该过程,直到两个指针相遇,left指针位置即为基数应所处的位置。

def find_base(a,left,right):
    base = a[left]
    while left < right:
        while left < right and a[right] > base:
            right -= 1
        if left < right:
            a[left] = a[right]
        while left < right and a[left] < base:
            left += 1
        if left < right:
            a[right] = a[left]
        a[left] = base
    return left

def quick_sort(a,left,right):
    if left<right:
        base = find_base(a,left,right)
        quick_sort(a,left,base-1)
        quick_sort(a,base+1,right)
        
if __name__ == "__main__":
    a = [7,3,4,1,6]
    quick_sort(a,0,len(a)-1)
    print(a)  
[1, 3, 4, 6, 7]

归并排序

不断的将两个有序序列进行合并的过程。

def mergesort(a):
    if len(a) == 1:
        return a
    mid = len(a)//2
    return merge(mergesort(a[:mid]),mergesort(a[mid:]))

def merge(left,right):
    result = []
    while len(left) and len(right):
        if left[0] <= right[0]:
            result.append(left.pop(0))
        else:
            result.append(right.pop(0))
    while len(left):
        result.append(left.pop(0))
    while len(right):
        result.append(right.pop(0))
    return result

if __name__ == "__main__":
    a = [7,3,4,1,6]
    b = mergesort(a)
    print(b) 
[1, 3, 4, 6, 7]

堆排序

首先建立最大堆或者最小堆,然后将堆的最小值或者最大值放置数组最后,重新调整剩下的元素为最大堆或者最小堆,重复上述过程。

def heapfiy(a,i):
    left = 2*i
    right = 2*i+1
    largest = i
    if left < n and a[largest] < a[left]:
        largest = left
    if right < n and a[largest] < a[right]:
        largest = right
    if largest != i:
        a[i],a[largest] = a[largest],a[i]
        heapfiy(a,largest)

def build_maxheap(a):
    for i in range(n//2,-1,-1):
        heapfiy(a,i)

def heapsort(a):
    global n
    n = len(a)
    # 建立最大堆,为了升序排序
    build_maxheap(a)
    for i in range(n-1,0,-1):
        a[0],a[i] = a[i],a[0]
        n = n - 1
        heapfiy(a,0)
        
if __name__ == "__main__":
    a = [7,3,4,1,6]
    heapsort(a)
    print(a) 
[1, 3, 4, 6, 7]

应用

第k小(大)的元素

  • 第k小的元素即索引为k-1位置的元素,n为序列长度
  • 第k大的元素即索引为n-k位置的元素,n为序列长度
# 时间复杂度:O(n)
def find_base(a,left,right):
    base = a[left]
    while left < right:
        while left < right and a[right] > base:
            right -= 1
        if left < right:
            a[left] = a[right]
        while left < right and a[left] < base:
            left += 1
        if left < right:
            a[right] = a[left]
        a[left] = base
    return left

def quicksort(a,left,right,k):
    if left < right:
        base = find_base(a,left,right)
        if k == base:
            return a[base]
        elif k<base:
            return quicksort(a,left,base-1,k)
        else:
            return quicksort(a,base+1,right,k)

def findKthElement(a,k):
    n = len(a)
    k = k-1
    return quicksort(a,0,n-1,k)

if __name__ == "__main__":
    a = [7,3,4,1,6]
    print(findKthElement(a,2))
3
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值