python数据结构排序和查找算法06

文章目录

  • 一、各种排序的时间复杂度
  • 二、排序
    • 一、冒泡排序
    • 二、插入排序
    • 三、选择排序
    • 四、shell排序
    • 五、快速排序
    • 六、归并排序
    • 七、计数排序
  • 三、二分查找


一、各种排序的时间复杂度

python数据结构排序和查找算法06_第1张图片
在观看本文章之前,推荐链接: 视觉算法
该辅助工具提供了对代码进行可视化的界面,帮助更能够理解
不仅仅只有排序,还有二叉树,递归,哈希表等的可视化。
python数据结构排序和查找算法06_第2张图片

二、排序

一、冒泡排序

冒泡排序比较简单,每一次都对相邻的两个数进行比较,前者大于后者就进行位置交换,是原地排序算法

def bubble_sort(alist):
    for i in range(len(alist)):
        for j in range(i+1,len(alist)-1):
            if alist[j] > alist[j+1]:
                alist[j],alist[j+1] = alist[j+1],alist[j]
    return alist

alist = [1,2,5,3,8,4]
print(bubble_sort(alist))

二、插入排序

插入排序更倾向于维护动态的数据有序,插入排序也是原地排序算法

def insert_sort(alist):
    for i in range(1,len(alist)):
        val = alist[i]
        j = i-1
        for j in range(i-1,0,-1):
            if alist[j] > val:
                alist[j+1] = alist[j]
            else:
                break
        alist[j+1] = val
    return alist

print(insert_sort(alist))

"方法2"
def insert_sort_2(alist):
    for i in range(1,len(alist)):
        val = alist[i]
        while i > 0 and alist[i-1] > val:
            alist[i] = alist[i-1]
            i = i-1
        alist[i] = val
    return alist
print(insert_sort_2(alist))


三、选择排序

选择排序是类似插入排序的,同样将一个数组分成两个部分,一个部分已经排序,另一个部分未排。其原理在于找到最小的数与第一个数交换,倒数第二小的数与第二个数交换,选择排序是一种不稳定算法。

def sel_sort(alist):
    for i in range(len(alist)-1):
        min_num = i
        for j in range(i,len(alist)):
            if alist[j]<alist[min_num]:
                min_num = j
        tem = alist[i]
        alist[i] = alist[min_num]
        alist[min_num] = tem
    return alist

print(sel_sort(alist))


四、shell排序

shell排序算法在最好的情况下其时间复杂度是O(n)的,其本身对数组进行间隔划分子列表,每个子列表都进行插入排序。
所有子列表的间隔一般都是n/2开始,到n/4,n/8一直到n。

def shell_sort(alist):
    mid = len(alist)//2
    while mid > 0:
        for i in range(mid):
            gap_insert_sort(alist,i,mid)

        mid = mid//2
    return alist
def gap_insert_sort(alist,start,gap):
    for i in range(start+gap,len(alist),gap):
        cur = alist[i]
        pos = i

        while i >= gap and alist[pos-gap] > cur:
            alist[pos] = alist[pos-gap]
            pos = pos-gap
        alist[pos] = cur
print('shell_sort排序',sel_sort(alist))

五、快速排序

快速排序利用了分治的思想,但它不同于归并排序算法的是,它任然是一种原地排序算法,解决了归并排序算法太耗费内存的问题。

def quick_sort(alist):
    return q_sort(alist,0,len(alist)-1)


def partition(alist,first,last):
    pivot = alist[first]
    left = first+1
    right = last

    done = False
    while not done:
        while left <= right and alist[left] <= pivot:
            left = left+1
        while alist[right] > pivot and right >= left:
            right = right-1

        if right < left:
            done = True
        else:
            tem = alist[left]
            alist[left] = alist[right]
            alist[right] = tem
    temp = alist[first]
    alist[first] = alist[right]
    alist[right] = temp
    return right


def q_sort(alist,first,last):
    if first < last:
        split = partition(alist,first,last)

        q_sort(alist,first,split-1)
        q_sort(alist,split+1,last)
    return alist

print('快速',quick_sort(alist))

六、归并排序

归并排序,其实就是分治思维和递归结合。
将一个数组不断的分解成小数组进行解决。
当然该排序方法时间复杂度为O(nlogn),也不是不需要付出代价的,它不是一个原地排序算法,它需要借助非常量级的额外储存空间,当然,内存大当我没说,哈哈哈哈

def merge_sort(alist):
    if len(alist) <= 1:
        return alist
    mid = len(alist)//2
    left = merge_sort(alist[:mid])
    right = merge_sort(alist[mid:])

    merge_list = []
    while left and right:
        if left[0] <= right[0]:
            merge_list.append(left.pop(0))
        else:
            merge_list.append(right.pop(0))
    merge_list.extend(right if right else left)
    return merge_list

print(merge_sort(alist))

'''
归并排序麻烦算法
'''
def merge_sort_diff(alist):
    if len(alist) > 1:
        mid = len(alist)//2
        left = alist[:mid]
        right = alist[mid:]
        #递归调用
        merge_sort_diff(left)
        merge_sort_diff(right)

        i = j = k = 0
        while i < len(left) and j <len(right):
            if left[i] < right[j]:
                alist[k] = left[i]
                i = i+1
            else:
                alist[k] = right[j]
                j = j+1
            k = k+1
        # 归并左
        while i < len(left):
            alist[k] = left[i]
            i = i+1
            k = k+1
        # 归并右
        while j < len(right):
            alist[k] = right[j]
            j = j+1
            k = k+1
        return alist

print(merge_sort_diff(alist))

七、计数排序

什么是计数排序呢?
其实计数排序是桶排序中的一种,特殊情况,当排序的数据量并不大时,直接将所有的数据分到不同的桶中,每个桶放一个数据,就节省了桶内排序的时间。
关于桶排序,我推荐的大佬的博客

def count_sort(alist):
    if len(alist) <= 1:
        return alist
    max = alist[0]
    for i in range(i,len(alist)):
        if max < alist[i]:
            max = alist[i]
    c = max+1
    for j in range(max+1):
        c[i] = 0

    for m in range(len(alist)):
        c[alist[m]] = c[alist[m]]+1
    for n in range(1,max+1):
        c[i] = c[i-1]+c[i]

    r = len(alist)
    for k in range(len(alist)-1,0,-1):
        index = c[alist[i]]-1
        r[index] = alist[i]
        c[alist[i]] = c[alist[i]]-1
    for l in range(len(alist)):
        alist[i] = r[i]
    return alist
print(alist)

三、二分查找

二分查找也叫折半查找,当你搜寻一个数时,你将排序完成的数组,进行取中值进行查询,比中值大就选右边,比中值小就选左边,同时丢弃令一边,举个例子:
当你的数据量有2的32次方那么大时,这个数据有多大呢,大约是40亿,你每次查找的数据都是上一次数据的二分之一,就是n,n/2,n/3,n/4…n/(2^k),一个等比数列,所以当n/(2 ^k)=1时,得到以2为底的对数k=log2(n),所以,即使数据量达到2 ^32次方那么大时,也只是需要32次就可以得到结果,其效率是超级高的。
但其缺点也相对比较明显,虽然时间复杂度是O(logn),但二分查找是通过下标进行查询的,所以相对而说,并不适合链表,同时当数据量太大时,数据通过列表的方式进行存储显然是不合理的。所以数据太大了,也不是很好处理。
python数据结构排序和查找算法06_第3张图片

'''
二分查找
'''
def binary_search(alist,val):
    first = 0
    last = len(alist)-1
    while first <= last:
        mid = first+(last-first)//2
        if alist[mid] == val:
            return mid
        else:
            if val < alist[mid]:
                last = mid-1
            else:
                first = mid+1
    return -1

alist = [1,2,5,3,8,4]
print(binary_search(alist,8))

'''
二分查找
递归
'''
def binary_search_2(alist,n,val):
    return binary_search_3(alist,0,n-1,val)

def binary_search_3(alist,first,last,val):
    if first >= last:
        return -1
    mid = (first+last)//2

    if alist[mid] < val:
        return binary_search_3(alist,mid+1,last,val)
    elif alist[mid] > val:
        return binary_search_3(alist,first,mid-1,val)
    else:
        return mid
print(binary_search_2(alist,len(alist),8))

python数据结构排序和查找算法06_第4张图片
python数据结构排序和查找算法06_第5张图片
搞定!!!

你可能感兴趣的:(数据结构,算法,快速排序,数据结构,python)