八大排序、时间复杂度空间复杂度

1、复杂度

1.1 时间复杂度

语句总的执行次数:T( n ) = O( f( n ) )
f(n) 是问题规模n的某个函数。

表示随着问题规模n的增大,算法执行时间的增长率和f( n )的增长率相同。
我们一般只关心随着问题规模n趋于无穷时函数中对函数结果影响最大的项,也就是最高次项

常数阶O(1)

int i = 1;
int j = 2;
++i;
j++;
int m = i + j;

上述代码在执行的时候,它消耗的时候并不随着某个变量的增长而增长,那么无论这类代码有多长,即使有几万几十万行,都可以用O(1)来表示它的时间复杂度。

线性阶O(n)

for(i=1; i<=n; ++i){
   j = i;
   j++;
}

for循环里面的代码会执行n遍,因此它消耗的时间是随着n的变化而变化的,因此这类代码都可以用O(n)来表示它的时间复杂度。

对数阶O(logN)

int i = 1;
while(i<n){
    i = i * 2;
}

当循环 log2^n 次以后,这个代码就结束了。

线性对数阶O(nlogN)

for(m=1; m<n; m++){
    i = 1;
    while(i<n)    {
        i = i * 2;
    }
}

将时间复杂度为O(logn)的代码循环N遍的话,那么它的时间复杂度就是 n * O(logN),也就是了O(nlogN)。

平方阶O(n2)

for(x=1; i<=n; x++){
   for(i=1; i<=n; i++)    {
       j = i;
       j++;
    }
}

如果将其中一层循环的n改成m,那它的时间复杂度就变成了 O(m*n)。

常用的时间复杂度所耗费的时间从大到小依次是:
O(1)< O(log n)< O(n)< O(nlog n)< O(n^2)< O(n^3)< O(2^n)< O(n!)< O(n^n)

1.2 空间复杂度

S(n)=O(f(n))算法所耗费的存储空间。空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势
f(n)为语句关于n所占存储空间的函数

空间复杂度O(1)

如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)

空间复杂度O(n)

int[] m = new int[n]
for(i=1; i<=n; ++i){
   j = i;
   j++;
}

第一行new了一个数组出来,这个数据占用的大小为n,其他行虽然有循环,但没有再分配新的空间,因此,这段代码的空间复杂度主要看第一行即可,即 S(n) = O(n)

2、八大排序算法

2.1 快速排序

基本思想: 通过一趟排序将排序的数据分隔成独立的俩部分,其中一部分的所有数据都比另外一部分的所有数据要小,然后再按照此办法对俩部分数据分别进行快速排序。

def quicksort(lst):
    if len(lst) < 2:
        return lst
    else:
        temp = lst[0]  #以第一个数为基准
        less = [i for i in lst if i < temp] # 比基准小的放在less列表中
        more = [i for i in lst if i > temp]# 比基准大的放在more列表中
        return quicksort(less) + [temp] + quicksort(more) # 返回三个列表拼接后的列表

testArr = [11, 23, 45, 23, 55, 99, 22]
print(quicksort(testArr))

2.2 冒泡排序

基本思想:重复地走访过要排序的数列,一次比较俩个元素,按左小右大排序,直到没有需要交换的元素时,该数列排序完成。
越大的元素会经由交换慢慢“浮”到数列的顶端,故名“冒泡排序”。

def bubblesort(lst):
    for i in range(len(lst) - 1): # 倒数第二个肯定是和最后一个比较大小,那么第len(lst)次就不需要了,最后一个数没有谁可以和它比了
        flag = 0
        for j in range(len(lst) - 1 - i):  # 第i个数肯定是和i后面的的数比较,比较 len(lst) - 1 - i次
            if lst[j] > lst[j + 1]:
                lst[j], lst[j + 1] = lst[j + 1], lst[j]
                flag = 1
        if flag == 0:  #判断一轮下来是否有顺序改变,没有的话直接退出了不用再排序
            break
        print(lst)

testArr = [1, 12, 32, 24, 5, 8, 7]
bubblesort(testArr)

运行结果:

[1, 12, 24, 5, 8, 7, 32]
[1, 12, 5, 8, 7, 24, 32]
[1, 5, 8, 7, 12, 24, 32]
[1, 5, 7, 8, 12, 24, 32]

2.3 插入排序

基本思想:第一部分包含了这个数组的所有元素(最后一个除外),将最后一个元素(即待插入元素)插入到前面合适的位置。

def insertionSort(arr):
    for i in range(len(arr)):
        print(i)
        preIndex = i - 1  # 记录有序序列最后一个元素的下标
        current = arr[i]  # 待插入的元素
        while preIndex >= 0 and arr[preIndex] > current:  # 最后一个元素大于待插入的元素的时候
            arr[preIndex + 1] = arr[preIndex]      # 将最后一个元素往后挪一个下标
            preIndex -= 1     # 下标逐渐往前推,进入下一轮比较,直到元素小于待插入元素的时候退出
        arr[preIndex + 1] = current   # 将待插入元素放到比它小的元素后面
    return arr


testArr = [12, 234, 22, 123, 33, 78, 95, 30]
print(insertionSort(testArr))

2.4 希尔排序

基本思想:对数组执行 多次的 间隔的 插入排序
先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的。

import math
def shellSort(arr):  
    gap=1  
    while(gap < len(arr)/3):
        gap = gap*3+1
    while gap > 0:
        for i in range(gap,len(arr)):
            temp = arr[i]
            j = i-gap
            while j >=0 and arr[j] > temp:
                arr[j+gap]=arr[j]
                j-=gap
            arr[j+gap] = temp
        gap = math.floor(gap/3)
    return arr

2.5 选择排序

基本思想:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

def selectionSort(arr):
    for i in range(len(arr) - 1):
        # 记录最小数的索引
        minIndex = i
        for j in range(i + 1, len(arr)):
            if arr[j] < arr[minIndex]:
                minIndex = j
        # i 不是最小数时,将 i 和最小数进行交换
        if i != minIndex:
            arr[i], arr[minIndex] = arr[minIndex], arr[i]
    return arr


testArr = [12, 54, 77, 46, 33, 41, 29, 75]
print(selectionSort(testArr))

2.6 堆排序

堆排序

2.7 归并排序

归并排序

2.8 基数排序

基数排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这个手刹不太灵儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值