python实现八大排序算法

明早去面试,今天复习了一下八大排序,把总结以及代码实现记录一下~~~
希望明天面试顺利!!

结合本科的数据结构课件。

可以参考链接[https://www.cnblogs.com/wuxinyan/p/8615127.html]
python实现八大排序算法_第1张图片

插入排序

1. 【直接插入排序】

原理
依次遍历数组中的每个元素,当插入到第 i 个位置时,前边的所有元素V[0] V[1]··· V[i-1]都已经排序完毕。此时将V[i] 与前边的所有元素比较,找到插入位置,插入V[i] ,原来位置上的元素向后顺移。

def InsertSort(lis):
    length = len(lis)
    for i in range(length):
        key = lis[i]
        j = i-1
        while j >= 0:
            if lis[j] > key:
                lis[j+1] = lis[j]
                lis[j] = key
            j -= 1
    return lis
    

平均时间复杂度: $O(n^{2})$

2【折半插入排序】

原理
就是在上述插入排序算法中,插入元素V[i]时,在前i-1个有序数组中采用二分搜索的方法。

def BinaryInsertSort(lis):
    for i in range(len(lis)):
        low = 0
        high = i-1
        tmp = lis[i]
        while high >= low:
            middle = int((high+low)/2)
            if lis[middle] > tmp:
                high = middle - 1
            else:
                low = middle + 1
        j = i-1
# 成块后移
        while j >= low:
            lis[j+1] = lis[j]
            j -= 1
        lis[j+1] = tmp
    return lis
BinaryInsertSort(a)

平均时间复杂度:$O(nlogn)$

3【希尔排序】

原理

缩小增量。就是对于插入排序的一种改进,因为插入排序对于已经排序好的数组效率较高;但是对于一般的数组,每次只移动一位,效率较低。

希尔排序是想先大叔组分成几个小的数组进行插入排序,然后拼成一个基本有序的大数组在进行排序。

def shellSort(lis):
    length = len(lis)
    gap = length
    while gap > 1:
        gap //= 2 
        for i in range(gap,length):
            for j in range(i%gap, i, gap):
                if lis[i] < lis[j]:
                    lis[i], lis[j] = lis[j], lis[i]
    return lis
shellSort(a)

不稳定的排序。
希尔排序的时间复杂度为:O(n^(3/2))

4【冒泡排序】

原理
数组长度为n,比较第i个元素时,从后往前(n-1,n-2····)依次比较

def bubbleSort(lis):
    if lis == []:
        return lis
    for i in range(len(lis)):
        for j in range(i+1, len(lis)):
            if lis[i] > lis[j]:
                lis[i],lis[j] = lis[j], lis[i]
    return lis

5【快速排序】

原理
定一个基准pivot,将数组分成两个大的部分。基准左边的都小于基准,基准右边的都大于基准。

然后对左右两个数组重复上述方法。

def quickSort2(lis,left = None,right = None):
    left = 0 if not isinstance(left,(int, float)) else left
    right = len(lis)-1 if not isinstance(right,(int, float)) else right
    if left < right:
        partitionIndex = partition(lis,left,right)
        quickSort(lis, left, partitionIndex-1)
        quickSort(lis, partitionIndex+1, right)
    return lis

def partition(lis,left,right):
    pivot = left
    index = pivot + 1
    i = index
    while i <= right :
        if lis[i] < lis[pivot]:
            swap(lis, i, index)
            index += 1
        i += 1
    swap(lis, pivot, index-1)
    return index -1

def swap(lis,m,n):
    lis[m], lis[n] = lis[n], lis[m]   
def QuickSort(lists, left, right):
    if left > right :
        return lists
    key = lists[left]
    low = left
    high = right
    while left < right:
        while left < right and lists[right] >= key:
            right -= 1
        lists[left] = lists[right]
        while left <right and lists[left] <= key:
            left += 1
        lists[right] = lists[left]
    lists[right] = key
    QuickSort(lists, low, left-1) #执行左侧
    QuickSort(lists, left+1, high) #执行右侧
    return lists

当数组长度较小时,不适用。
适用于较大数组。
不稳定的排序。

平均时间复杂度:
最好:O(nlogn)
最坏:O(n^2)

6【直接选择排序】

原理
选择最小的元素,如果不在数组首位,与首位交换。

剔除刚刚最小的,重复此步骤。

def selectSort2(lis):
    for i in range(len(lis)):
        min_index = i
        for j in range(i+1, len(lis)):
            if lis[min_index] > lis[j]:
                min_index = j
 # 与首位交换
        lis[min_index], lis[i] = lis[i], lis[min_index]
    return lis

平均复杂度 O(n^2)
空间复杂度:O(1)

7【堆排序】

原理
每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最大堆,依次类推,最终得到排序的序列。

步骤 :
1、建立最大堆

2、堆顶元素与堆底元素交换,然后从堆底外的元素进行shift_down,目的是想把新的堆顶元素调整到相应位置

3、重复步骤2,直至堆长度为1

def build_heap(lis,size):
    for i in range(size//2,-1,-1):
        shift_down(lis,i,size)
        
def shift_down(lis,i,size):
    left = 2 * i + 1
    right = 2 * i + 2
    max_index = i
    if left < size and lis[left] > lis[max_index]:
        max_index = left
    if right < size and lis[right] > lis[max_index]:
        max_index = right
    if i!= max_index:
        lis[i], lis[max_index] = lis[max_index], lis[i]
        shift_down(lis,max_index, size)
        
def heapSort(lis):
    size = len(lis)
    build_heap(lis,size)
    for i in range(size,-1,-1):
        lis[i],lis[0] = lis[0],lis[i]
        shift_down(lis,0,i)
        return lis

shift_dowm:O(nlogn)

建立初始最大堆的时间复杂度也就是shift_down的时间复杂度O(nlogn)

然后排序是使用n-1次shift_down,也是:O(nlogn)

空间复杂度:O(1)

8【归并排序】

原理
设初始元素序列有 n 个元素,首先把它看成是 n 个长度为 1 的有序子序列(归并项),做两两归并,得到 n/2 个长度为 2 的归并项(最后一个归并项的长度为1);
再做两两归并,得到 n/4 个长度为 4 的归并项(最后一个归并项长度可以短些)…,如此重复,最后得到一个长度为 n 的有序序列

def merge(left,right):
    i,j = 0,0
    res = []
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            res.append(left[i])
            i += 1
        else:
            res.append(right[j])
            j += 1
    
    res += (left[i:])
    res += (right[j:])
    return res

def mergeSort(lis):
    if len(lis) <= 1:
        return lis
    middle = len(lis)//2
    left = mergeSort(lis[:middle])
    right = mergeSort(lis[middle:])
    return merge(left, right)

时间复杂度:O(nlogn)

你可能感兴趣的:(python,数据结构,剑指offer)