Java教程

数据结构与算法Day6

本文主要是介绍数据结构与算法Day6,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

快速排序

将两部分数据分别进行拍讯,整个排序过程可以用递归进行,以达到整个数据变成有序序列
操作步骤为:
1.先从序列中挑出一个元素,以这个元素为基准值。
2.将剩下数列中的元素分别以基准值为中心,比基准大的排在基准的右侧,比基准小的排在基准的左侧,操作完后形成以基准值为中心的新序列。
3.递归地,将以基准值两边的序列看成两个子序列继续操作。
在Python中实现

def quick_sort(alist,first,last):
    '''快速排序 递归嵌套'''
    if first >= last: #严格小于才执行程序
        return
    mid_value = alist[first]
    low = first
    high = last
    while low < high:
         #若两边都有一个与mid相等的值 放在一边 不放在两边
         #带low<high是因为进入上一个while后下列操作会移动low与high的指针
        while low < high and alist[high] >= mid_value: 
            high -= 1 #满足条件继续遍历右端值
        alist[low] = alist[high] #不满足条件则将右端位置换到基准值左端
        # low游标右移
        while low < high and alist[low] < mid_value:
            low += 1 #满足条件继续遍历左端值
        alist[high] = alist[low] #不满足条件则将左端位置换到基准值右端
    alist[high] = mid_value #当low>=high时 意味着两个指针重叠 将基准值赋值于指针指向位置
    quick_sort(alist,first,low-1) #左子序列递归
    quick_sort(alist,low+1,last) #右子序列递归

快速排序的时间复杂度以及稳定性
每次都会对两端子序列进行排序,对子序列排序时,操作是同时进行的,对时间复杂度进行累加,而每次对两端子序列进行排序时,所需要的时间复杂度是O(n) (因为222…=n个数,需要分log2(n)次数),因此最终时间复杂度为O(nlog2(n))。但在最坏情况下,每次找的数都是在数列的第一个数,每次都需要对所有数进行排序,时间复杂度为O(n^2)。
稳定性为不稳定

归并排序

和快速排序类似,也是分成子序列进行排序,但归并排序直接将所需序列都拆成单个序列,单个序列在组成成对序列,这样依次成倍的合并。
在Python中实现

def merge_sort(alist):
    '''归并排序'''
    n = len(alist)
    if n<=1:
        return alist
    mid = n//2
    # left 采用归并排序后形成有序的新的列表 right同理
    left_li = merge_sort(alist[:mid]) #不断递归 直至n<=1
    right_li = merge_sort(alist[mid:])
    #将两个有序子序列合并为一个整体
    # merge_sort(left_li,right_li)
    left_pointer,right_pointer = 0,0
    result = []
    while left_pointer < len(left_li) and right_pointer < len(right_li):
        if left_li[left_pointer] <= right_li[right_pointer]:
            result.append(left_li[left_pointer]) #传入数据
            left_pointer += 1 #移动指针
        else:
            result.append(right_li[right_pointer])
            right_pointer += 1
    #左右指针但凡有一个不满足条件则退出循环,result列表直接加上之前排序好的序列
    result += left_li[left_pointer:] 
    result += right_li[right_pointer:]
    return result

归并排序的时间复杂度以及稳定性
子序列的操作是同时的,时间复杂度累加记,每次排序时间复杂度为O(n),但总共需要排序log2(n)次(因为总共有222…=n个数),因此最终的时间复杂度为O(nlog2(n)),稳定性为稳定。

常见排序算法的时间复杂度以及稳定性比较

在这里插入图片描述

二分查找

二分查找又称为折半查找,优点是查找次数少,查找速度快,平均性能好,但要求带查表为有序表,且插入删除困难。
折半查找的步骤为(假设表中元素为升序排列):
1.将表中中间位置的数值与输入item数值进行比较,若表中中间位置数值大于item则在中间位置的右端子序列寻找item数值,否则在左端子序列寻找item数值。
2.递归地,像查找第一次数值那样在某一段子序列查找是否有和输入item一样的数。
在Python中的操作
递归的二分查找

def binary_search(alist,item):
    '''二分查找'''
    n = len(alist)
    mid = n//2 #找到中间值位置
    if n >= 1:#进入循环的条件:要求序列长度至少为1
        if alist[mid] == item: #中间值直接找到则返回True
            return True
        elif item < alist[mid]: #如果比中间值小则找递归找右端子序列
            return binary_search(alist[:mid],item)
        else:#如果item比中间值大或等于则找递归找左端子序列
            return binary_search(alist[mid+1:],item)
    return False #循环内没找到则返回False

非递归的二分查找

def binary_search_2(alist,item):
    '''二分查找,非递归'''
    n = len(alist)
    first = 0 #设置指针
    last = n-1
    while first <= last:#循环条件带上等于 有可能两个指针相邻但却没找到值(与item相等的值被last或者first指针指着)
        mid = (first + last) // 2 #找到中间值
        if alist[mid] == item:
            return True
        elif item < alist[mid]:#没找到item移动指针
            last = mid - 1
        else:
            first = mid + 1
    return False #在循环内没找到item
这篇关于数据结构与算法Day6的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!