交换排序:冒泡排序和快速排序

       交换,指的是根据序列中的两个元素关键字的比较结果来对换这两个元素在序列中的位置。在众多的排序算法中,冒泡和快排属于交换排序。

一、冒泡排序

1、基本思想:

类似于水中冒泡,较小的浮上来,较大的沉下去。将两个数进行比较,较大的数往后移动,较小的数往前移动。

2、算法描述:

将序列最后一个元素与前一个元素进行两两比较,如果为逆序,那么交换元素位置;

按照的上面的做法往前进行两两比较,直到第一个元素,那么第一个元素将为最小值,且为最终位置;

对剩余序列按照上述两个步骤进行比较,直到排序完成。

3、编码实现:

def swap(s, a, b):
    temp = s[a]
    s[a] = s[b]
    s[b] = temp


def bubblesort(instr):
    n = len(instr)
    for i in range(n-1):
        for j in range(i,n)[::-1]:
            if instr[j-1] > instr[j]:
                swap(instr, j-1, j)


if __name__ == '__main__':
    instr = input().split()
    bubblesort(instr)
    print(''.join(instr))

以上代码便是冒泡法实现排序,比较的次数与序列的初始状态无关,始终是n*(n-1)/2,因此时间复杂度为O(n^2)。使用常数个辅助单元,因此空间复杂度为O(1)。

但是如果在初始序列有序的情况下,这样进行比较,无疑浪费资源和时间。为了提高效率,可以设置了一个变量flag,如果flag为0那么说明该组序列为有序序列,不需要再进行冒泡排序比较,直接退出循环即可。这样,最好情况下,移动次数为0,比较次数为n-1次,时间复杂度为O(n)。编码如下:

def swap(s, a, b):
    temp = s[a]
    s[a] = s[b]
    s[b] = temp


def bubblesort(instr):
    n = len(instr)
    for i in range(n-1):
        flag = 0
        for j in range(i,n)[::-1]:
            if instr[j-1] > instr[j]:
                swap(instr, j-1, j)
                flag = 1
        if flag == 0:
            return


if __name__ == '__main__':
    instr = input().split()
    bubblesort(instr)
    print(''.join(instr))

4、示例:

对初始序列:5,4,3,2,1 进行从小到大排序

第一趟排序过程:比较4次

第二趟排序过程:比较3次

第三趟排序过程:比较2次

第四趟排序过程:比较1次

5、算法分析:

每趟排序进行n-1次比较,每趟比较后都有一个元素放在最终位置,剩余排序个数为n-1。一共需要n-1趟比较。最好的情况下,比较次数为n,移动次数为0,时间复杂度为O(n);最坏情况下,比较次数为n*(n-1)/2,移动次数为3*n*(n-1)/2,时间复杂度为O(n^2)。由于元素相等时,不会进行交换操作,所以冒泡排序是一种稳定的排序算法。

二、快速排序

1、基本思想:基于分治法,通过一趟排序将待排序的序列分为两部分,一部分序列中的元素都比基准元素小,另一部分序列中的元素都比基准元素大,然后分别对这两部分序列进行排序,直到整个序列有序。

2、算法描述:

从序列中选择一个基准元素;

对序列进行排序,所有比基准元素小的放在前面,所有比基准元素大的放在后面,并返回基准元素的最终位置;

根据基准元素的位置将序列分为两个子序列;

对每部分的序列进行上述三个步骤操作,直到序列有序。

3、编码实现:

def partition(instr, low, high):
    p = instr[low]
    while low < high:
        while low < high and instr[high] >= p:
            high = high-1
        instr[low] = instr[high]
        while low < high and instr[low] <= p:
            low = low+1
        instr[high] = instr[low]
    instr[low] = p
    return low


def quickSort(instr, low, high):
    if low < high:
        p = partition(instr,low,high)
        quickSort(instr,low,p-1)
        quickSort(instr,p+1,high)


if __name__ == '__main__':
    instr = input().split()
    quickSort(instr,0,len(instr)-1)
    print(''.join(instr))

4、示例:

       对初始序列:3,5,1,6,2,7,4,9进行从小到大排序,以第1个元素为基准

第一次分区:分为两部分

  、

以3为基准分为两部分,然后对3前面和后面的两个序列进行如上分区,直到序列有序。

5、算法分析:

      每次排序后,基准元素都将被放到在序列中的最终位置上。在最好的情况下,空间容量与递归调用的最大深度一致,为log2(n+1),最坏情况下,要进行n-1次递归调用,栈的深度为n-1,因此,最坏情况下空间复杂度为O(n),平均情况下为O(log2 n)。在最好的情况下,时间复杂度为O(n log2 n),最坏情况下,时间复杂度为O(n^2)。如果在排序过程中,有两个元素均小于基准元素,那么都将被移动,原本次序发生变化,可能导致最终次序与原来次序不一致,因此快速排序是一种不稳定的排序方法。

猜你喜欢

转载自blog.csdn.net/VinWqx/article/details/104858424