排序与查找——数据结构与算法(python)

学习笔记(数据结构与算法)

1.顺序查找__O(N)

直接按顺序遍历列表的下标,最好的情况“对比”一次就找到,最差的情况“对比”N次。因此时间复杂度为O(N)

def sequantialSearch(alist,item):
    found = False  # 控制查找结束
    pos = 0
    while pos < len(alist) and not found:
        if alist[pos] == item:
            found = True
        else:
            pos += 1
    return found

2.二分查找__O(logN) (仅针对有序表有效)
def binarySearch(alist,item):
    found = False
    first = 0
    last = len(alist)-1
    while first <= last and not found:
        midpoint = (first+last)//2
        if alist[midpoint] == item:
            found = True
        else:
            if alist[midpoint] > item:
                last = midpoint - 1
            else:
                first = midpoint + 1
    return found

#递归  采用了切片会更复杂
def binarySearch(alist,item):
    if len(alist) == 0:
        return False
    else:
        midpoint = len(alist)//2
        if alist[midpoint] == item:
            return True
        else:
            if alist[midpoint] > item:
                return binarySearch(alist[:midpoint],item)
            else:
                return binarySearch(alist[midpoint+1:],item)  
3.冒泡排序__O(n²)

长度为n的列表,第一次遍历,从第一项开始,如果和下一项是逆序,则交换位置,经过n-1次对比后,第n项即是最大项。第二次遍历又从头开始,和下一项逆序则交换位置,经过n-2次对比,第n-1项即是第二大项,一次类推…

def bubbleSort(alist):
    exchange = True  #如果某趟对比没有发生交换,表示已经排好序,提前结束循环。
    passnum = len(alist)-1
    while passnum>0 and exchange:
        for i in range(passnum):
            exchange = False
            if alist[i] > alist[i+1]:
                exchange = True
                alist[i], alist[i+1] = alist[i+1], alist[i]
        passnum = passnum - 1
4.选择排序__O(n²)

与冒泡排序类似,不同的是,冒泡排序是对比一次,有逆序就立刻交换位置。选择排序是记录最大值的位置,最后与再最右端的数据交换位置。

def selectSort(alist):
    for passnum in range(len(alist)-1,0,-1):
        posOfMax = 0 # 记录最大值位置
        for i in range(1,passnum+1):
            if alist[i] > alist[posOfMax]:
                posOfMax = i
        alist[passnum], alist[posOfMax] = alist[posOfMax], alist[passnum]  #每一趟结束交换位置
5.插入排序__O(n²)

对每一个数据进行寻找插入位置的操作。比如:从第二个数据项开始currentPos=1,如果比前一项小,就将第一个数据项右移;如果当前为第三个数据currentValue,比第二个数据项小,就将第二个数据项右移,当前位置变为第二,再与前一个数据,也就是第一个数据比,如果第一个数据更大,则将第一个数据右移,当前位置变为第一,此时,while循环结束。将alist[currentPos]=currentValue

def insertSort(alist):
    for i in range(1,len(alist)):
        currentPos = i
        currentValue = alist[i]
        while currentPos > 0 and alist[currentPos-1] > currentValue:
            alist[currentPos] = alist[currentPos-1]
            currentPos = currentPos - 1
        alist[currentPos] = currentValue

6.谢尔排序__O(n)~O(n²)

是在对无序表进行间隔划分,比如将有n个数据项的列表每隔n/2个数据划分,得到n/2个子列表,对每个子列表进行插入排序,然后再缩小划分间隔,变成n/4,再对每个子列表进行插入排序…直到间隔为1,即是标准的插入排序,由于之前进行的子列表排序,此时的列表已接近有序,只需要稍微调整几个位置即可,对比的次数很少。

def shellSort(alist):
    space = len(alist) // 2
    while space >= 1:
        for start in range(space):
            gapInsertSort(alist,start,space)

        space = space //2

def gapInsertSort(alist,start,gap):
    for i in range(start+gap,len(alist),gap):
        currentValue = alist[i]
        currentPos = i
        while currentPos > 0 and alist[currentPos-gap] > currentValue:
            alist[currentPos] = alist[currentPos-gap]
            currentPos -= gap
        alist[currentPos] = currentValue

7.归并排序__O(nlogn)

先递归:将列表分为两半,分别对两半进行排序。基本结束条件是当列表被分到不能再分的时候即里面不足2个数。
再创建一个空列表进行归并。

def mergeSort(alist):
    if len(alist) <= 1:
        return alist
    else:
        mid = len(alist) // 2
        left = mergeSort(alist[:mid])
        right = mergeSort(alist[mid:])
        merge = []
        while left and right:   #当左右都不是空列表
            if left[0] < right[0]: # 若左边最小的大于右边最小的
                merge.append(left.pop(0))  #加入mergt,并且在left中删除
            else:
                merge.append(right.pop(0))
        merge.extend(right if right else left) #当某一边列表有剩余时,直接加入merge末尾

    return merge
8.快速排序__O(nlogn)~O(n²)

依据一个“中值”,将列表分为:大于“中值”的子列表和小于“中值”的子列表。每个子列表再选“中值”继续分…将此过程递归。
为了方便一遍都直接选取列表的第一项为“中值”,这种方法的时间复杂度受选取的“中值”影响很大,若选取的“中值”刚好将整个列表分为数量相等的两个子列表,则时间复杂度为O(nlogn)。若不幸,选取的“中值”分成的左右两列表数量差距很大,甚至其中一边几乎没有数据,那么复杂度为O(n²)。

def quickSortHelp(alist):
    quickSort(alist,0,len(alist)-1)
    
def quickSort(alist,first,last):
    if first < last:  #基本结束条件
        mid = partition(alist,first,last)
        quickSort(alist,first,mid-1)  #调用自身
        quickSort(alist,mid+1,last)

def partition(alist,first,last):
    pivotValue = alist[first]
    leftmark = first+1
    rightmark = last
    stop = False
    while not stop:
        while leftmark <= rightmark and alist[leftmark]<=pivotValue:
            leftmark += 1
        while rightmark >= leftmark and alist[rightmark] >= pivotValue:
            rightmark -= 1
        if leftmark > rightmark:
            stop = True
        else:
            temp = alist[leftmark]
            alist[leftmark] = alist[rightmark]
            alist[rightmark] = temp

    temp = alist[rightmark]
    alist[rightmark] = pivotValue
    alist[first] = temp
    return rightmark
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值