我们常见的排序算法(通过Python实现)

 


冒泡算法

冒泡排序。O(n2)通常认为冒泡是比较差的,可以加些改进,比如在一趟中无数据的交换,则结束等措施。 

在数据已基本有序时,冒泡是一个较好的方法;在数据量较少时(15个左右)可以用冒泡算法。

def BubbleSort(ls):

    n=len(ls)

    if n<=1:

        return ls

    for i in range (0,n):

        for j in range(0,n-i-1):

            if ls[j]>ls[j+1]:

                (ls[j],ls[j+1])=(ls[j+1],ls[j])

 

快速排序

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序的数组。

def QuickSort(arr, firstIndex, lastIndex):

    if firstIndex < lastIndex:

        divIndex = Partiotion(arr, firstIndex, lastIndex)

        QuickSort(arr, firstIndex, divIndex)

        QuickSort(ar, divIndex + 1, lastIndex)

    else:

        return



def Partition(arr, firstIndex, lastIndex):

    i = firstIndex - 1

    for j in range(firstIndex, latIndex):

        if arr[j] <= arr[lastIndex]:

            i = i + 1

            arr[i], arr[j] = arr[j], arr[i]

        arr[i + 1], arr[lastIndex] = arr[lastIndex], arr[i + 1]

        return i + 1

 

选择排序

简单选择排序同样对数据操作n-1轮,每轮找出一个最大(小)值。操作指选择,即未排序数逐个比较交换,争夺最值位置,每轮将一个未排序位置上的数交换成已排序数,即每轮选一个最值。每轮操作O(n)次,共O(n)轮,时间复杂度O(n^2)。额外空间开销出在交换数据时那一个过渡空间,空间复杂度O(1)。

def SelectionSort (lists):

    for i in range(0, len(lists)):

        min_number = i

        for j in range(i + 1, len(lists)):

            if lists[j] < lists[min_number]:

                min_number = j

        lists[i], lists[min_number] = lists[min_number], lists[i]

 

归并排序

归并排序运用分治递归思想:将大问题分为较小的子问题,分而治之;递归调用同样的方法解决子问题。最终将序列的排序问题分治为一个数的排序问题,关键在于如何将子问题答案合并为问题答案。

两个有序序列合并为一个有序序列,借助一个暂存数组(列表),两个序列元素依次比较填入暂存列表,形成一个有序序列。归并排序划分子问题采用二分法,共需O(logn)次划分,当然需要相当次合并;每次合并遍历比较O(n)。时间复杂度O(nlogn)。额外空间开销出在合并过程中的一个暂存数组,空间复杂度O(n)。

def MergeSort (lists):

    if len(lists) <= 1:

        return lists

    num = int( len(lists)/2 )

    return Merge(MergeSort(lists[:num]),

                 MergeSort(lists[num:]))



def Merge (left, right):

    r, l = 0, 0

    result = []

    while l < len(left) and  r < len(right):

        if left[l] < right[r]:

            result.append(left[l])

            l += 1

        else:

            result.append(right[r])

            r += 1

    result += right[r:]

    result += left[l:]

    return  result

 

插入排序

插入排序,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序;首先将第一个作为已经排好序的,然后每次从后的取出插入到前面并排序。

def insert_sort(ilist):

    for i in range(len(ilist)):

        for j in range(i):

            if ilist[i] < ilist[j]:

                ilist.insert(j, ilist.pop(i))

                break

    return ilist

 

希尔排序

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

def shell_sort(slist):

    gap = len(slist)

    while gap > 1:

        gap = gap // 2

        for i in range(gap, len(slist)):

            for j in range(i % gap, i, gap):

                if slist[i] < slist[j]:

                    slist[i], slist[j] = slist[j], slist[i]

    return slist

 

堆排序

堆排序实际上是利用堆的性质来进行排序的,要知道堆排序的原理我们首先一定要知道什么是堆。堆实际上是一棵完全二叉树。

堆的分类:

1、最大堆(大顶堆):堆的每个父节点都大于其孩子节点;

2、最小堆(小顶堆):堆的每个父节点都小于其孩子节点;

堆的性质:

1、堆的每一个父节点都大于(或小于)其子节点;

2、堆的每个左子树和右子树也是一个堆。

堆的存储:

一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。

堆排序步骤:

1、建堆(升序建大堆,降序建小堆);

2、交换数据;

3、向下调整。

由上面的介绍我们可以看出堆的第一个元素要么是最大值(大顶堆),要么是最小值(小顶堆),这样在排序的时候(假设共n个节点),直接将第一个元素和最后一个元素进行交换,然后从第一个元素开始进行向下调整至第n-1个元素。所以,如果需要升序,就建一个大堆,需要降序,就建一个小堆。

def HeapSort(lists):

    BuildMaxHeap(lists)

    for i in range(len(lists) - 1, 0, -1):

        lists[0], lists[i] = lists[i], lists[0]

        MaxHeapify(lists, 0, i)



def BuildMaxHeap(lists):

    for i in range((int)(len(lists) / 2) - 1, -1, -1):

        MaxHeapify(lists, i, len(lists))



def MaxHeapify(lists, i, heap_size):

    if 2 * i + 1 < heap_size and lists[2 * i + 1] > lists[i]:

        largest = 2 * i + 1

    else:

        largest = i

    if 2 * i + 2 < heap_size and lists[2 * i + 2] > lists[largest]:

        largest = 2 * i + 2

    if largest != i:

        lists[i], lists[largest] = lists[largest], lists[i]

        MaxHeapify(lists, largest, heap_size)

 

以上内容如有错误,欢迎指出。谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值