快排、堆排和归并排序的Python实现

本文介绍了快速排序、堆排序和归并排序的算法实现,并通过实例进行了比较分析。

快速排序:

#! /usr/bin/env python
#coding=utf-8

import random,copy

def partition(lst,left,right):
    pivot = lst[left]
    pivot_index = left
    left = left + 1
    while True:
        # when pivot as lst[left] start from left
        while left <= right and lst[left] <= pivot:
            left = left + 1
        while left <= right and lst[right] >= pivot:
            right = right - 1
        if left <= right:
            lst[left],lst[right] = lst[right],lst[left]
        else:
            break
    lst[pivot_index],lst[right] = lst[right],lst[pivot_index]
    return right

def quick_sort_helper(lst,start,end):
    if (start < end):
        split_position = partition(lst,start,end)
        quick_sort_helper(lst,start,split_position-1)
        quick_sort_helper(lst,split_position+1,end)

def quick_sort(lst):
    quick_sort_helper(lst,0,len(lst)-1)
    

def quick_sort_helper2(lst,left,right):
    if left < right:
        pivot_index = right
        pivot = lst[pivot_index]
        i = left
        k = left
        while i < right:
            if lst[i] <= pivot:
                lst[k],lst[i] = lst[i],lst[k]
                k = k + 1
            i = i + 1
        lst[k],lst[pivot_index] = lst[pivot_index],lst[k]
        quick_sort_helper2(lst,left,k-1)
        quick_sort_helper2(lst,k+1,right)
        

def quick_sort2(lst):
    quick_sort_helper2(lst,0,len(lst)-1)
        

if  __name__ == '__main__':
    lst = [random.randint(0,20) for i in range(10)]
    lst2 = copy.deepcopy(lst)
    lst2.sort()
    print(lst)
    print(lst2)
    quick_sort2(lst)
    print(lst)

    

堆排序:

#! /usr/bin/env python
#coding=utf-8

import random,copy

def heap_sort_helper(lst,left,right):
    # max heapify
    current_value = lst[left]
    child = 2 * left + 1
    while (child <= right):
        if (child < right and lst[child] < lst[child+1]):
            child  = child + 1
        if (current_value > lst[child]):
            break
        else:
            lst[(child-1)>>1] = lst[child]
            child = 2 * child + 1
    lst[(child-1)>>1] = current_value
    
def heap_sort(lst):
    # build heap
    for i in range((len(lst)-1)>>1,-1,-1):
        heap_sort_helper(lst,i,len(lst)-1)
    for i in range(len(lst)-1,0,-1):
        lst[i],lst[0] = lst[0],lst[i]
        heap_sort_helper(lst,0,i-1)

if  __name__ == "__main__":
    lst = [random.randint(0,20) for i in range(10)]
    lst2 = copy.deepcopy(lst)
    lst2.sort()
    print(lst)
    print(lst2)
    heap_sort(lst)
    print(lst)
    
    
    

归并排序:

#! /usr/bin/env python
#coding=utf-8
import random

def mergesort(seq):
    mid = len(seq) // 2
    lft,rht = seq[:mid],seq[mid:]
    if len(lft) > 1: 
        lft = mergesort(lft)
    if len(rht) > 1:
        rht = mergesort(rht)
    res = []
    while lft and rht:
        #using pop to reduce data movements
        if lft[-1] >= rht[-1]:
            res.append(lft.pop())
        else:
            res.append(rht.pop())
    res.reverse()
    return (lft or rht) + res

def main():
    seq = [random.randint(0,20) for i in range(10)]
    print(seq)
    seq = mergesort(seq)
    print(seq)
    
if __name__ == "__main__":
    main()
    

    




### 不同序算法的实现特点 #### 选择序 选择序是一种简单直观的比较类内部序算法。其基本思想是在未序部分找到最小(大)元素,将其放到已序序列的一端。 ```cpp void SelectionSort(int arr[], int n) { for (int i = 0; i < n - 1; ++i) { int minIndex = i; for (int j = i + 1; j < n; ++j) { if (arr[j] < arr[minIndex]) { minIndex = j; } } std::swap(arr[i], arr[minIndex]); } } ``` 该方法稳定性时间复杂度表现一般,平均情况下需要 O(n²) 的时间来完成序过程[^1]。 #### 插入序 插入序通过构建有序序列,对于未序数据,在已序序列中从后向前扫描,找到相应位置并插入。适用于少量数据的序场景。 ```cpp void InsertionSort(int arr[], int n) { for (int i = 1; i < n; ++i) { int key = arr[i]; int j = i - 1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; --j; } arr[j + 1] = key; } } ``` 此算法同样具有 O(n²) 时间复杂度但在几乎已经好序的数据集上性能较好。 #### 快速序 快速序采用分治策略来进行序工作。它选取一个基准值pivot,使得数组中小于等于它的放在左边,大于它的放右边;再分别对左右两部分递归处理直到全部元素都有序为止。 ```python def quick_sort(arr): if len(arr) <= 1: return arr else: pivot = arr[len(arr) // 2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return quick_sort(left) + middle + quick_sort(right) ``` 这种高效的方法通常能在实践中达到接近线性的速度即 O(n log n)[^1]。 #### 希尔序 希尔序是对直接插入序的一种改进形式。它按照一定步长将原始列表分割成若干子表,并依次执行插入序;随着迭代次数增加逐步减少步长直至最终变为常规插入序。 ```cpp void ShellSort(int* a, int n) { int gap = n; while (gap > 1) { gap = gap / 3 + 1; for (int i = gap; i < n; ++i) { if (a[i] < a[i - gap]) { int tmp = a[i]; int j; for (j = i - gap; j >= 0 && a[j] > tmp; j -= gap){ a[j + gap] = a[j]; } a[j + gap] = tmp; } } } } ``` 这种方法可以显著降低最坏情况下的运行时间至 O(n^(3/2)) 或更好取决于具体增量序列的选择[^4]。 #### 归并排序 归并排序也是一种基于分而治之原则的经典序技术。首先把原问题分解为两个规模更小相同类型的子问题——即将输入分成前后半部各自独立地进行序;接着合并这两个经过序后的片段使之成为一个整体上的有序集合。 ```cpp void MergeSort(int arr[], int l, int r) { if(l >= r)return ; int mid = (l+r)/2; MergeSort(arr,l,mid); MergeSort(arr,mid+1,r); static int temp[N]; int k=l,i=l,j=mid+1; while(i<=mid&&j<=r) if(arr[i]<=arr[j]) temp[k++]=arr[i++]; else temp[k++]=arr[j++]; while(i<=mid)temp[k++] = arr[i++]; while(j<=r)temp[k++] = arr[j++]; for(k=l;k<=r;++k) arr[k]=temp[k]; } ``` 由于每次都将当前区间均匀切分为二份因此理论上能够保证稳定的 O(nlogn) 复杂度。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值