数据结构与算法——冒泡、选择、插入、快速、希尔、归并、二分查找(python实现)

冒泡排序

def bubble_sort(l):
    n = len(l)
    for i in range(n-1):  #i表示比较趟数
        for j in range(n-1-i):
            if l[j]>l[j+1]:
                l[j],l[j+1] = l[j+1],l[j] #大数往上冒泡,交换位置
    return l
if __name__ == '__main__':
    s = [54,26,93,17,77,31,44,55,20]
    print(bubble_sort(s))

选择排序

def select_sort(l):
    n = len(l)
    for i in range(n-1):  #比较趟数,每比较完一趟,都能确定一个最小值
        min_index = i   #每趟将比较序列中的第一个数下标作为最小值的下标
        for j in range(i+1,n):  #比较其余数,找到实际最小值的下标
            if l[j]<l[min_index]:
                min_index = j   
        if min_index !=i:  #若与比较序列中第一个数的下标不等,则交换位置
            l[i],l[min_index] = l[min_index],l[i]
    return l 
if __name__ == '__main__':
    s = [54,26,93,17,77,31,44,55,20]
    print(select_sort(s))

插入排序

def insert_sort(l):  #类似于抓牌时,按顺序插入牌的位置,已插入的都是有序的
    n = len(l)
    for i in range(1,n): #比较趟数
        for j in range(i,0,-1):  #与已经有序的序列比较,插入合适的位置
            if l[j]<l[j-1]:
                l[j],l[j-1] = l[j-1],l[j]
            else:  #因为前面的序列已经有序,插入一个新数,一旦不比前一个数小,就不再往前比较
                break
    return l
if __name__ == '__main__':
    s = [54,26,93,17,77,31,44,55,20]
    print(insert_sort(s))

快速排序

#每次选比较序列中第一个数作为基准值,比它小的在左边,比它大的在右边
# 分别将左右两边作为新序列,递归排序,直到序列中只有一个数
def quick_sort(l,head,tail):
    pivot = l[head]
    if head >= tail:
        return
    left = head
    right = tail
    while left < right:  #先将右边的与基准值比较
        while l[right] > pivot:  #右边的大于基准值 right左移
            right = right -1
        l[left] = l[right]  #遇到小于基准值的,放到左边
        while l[left] < pivot:  #左边的小于基准值 left右移
            left = left +1
        l[right] = l[left]  #遇到大于基准值的,放到右边
        l[left] = pivot # 将基准值放到中间(left和right相等时)
    quick_sort(l,head,left-1)
    quick_sort(l,left+1,tail)
    return l
if __name__ == '__main__':
    s = [54,26,93,17,77,31,44,55,20]
    print(quick_sort(s,0,len(s)-1))

希尔排序

#递减增量排序。由相隔某个“增量”的元素组成的序列,分别进行直接插入排序
# 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,
# 待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。
def shell_sort(l):
    n = len(l)
    d = n //2
    while d >=1:
        for i in range(d,n): #相同增量间的值进行比较
            while i>=d and l[i] <l[i-d] :  # 相同增量可能存在多个数比较(插入排序,前面的数已经排好序,所
                # 以只有当后面的数比前面一个数小时,才交换位置,然后再与相同增量的前一个数比较)
                l[i],l[i-d] = l[i-d],l[i]
                i = i - d
        d = d // 2
    return  l
if __name__ == '__main__':
    s = [54,26,93,17,77,31,44,55,20]
    print(shell_sort(s))

归并排序

# 分治法:
# # 分割:递归地把当前序列平均分割成两半。
# # 集成:在保持元素顺序的同时将上一步得到的子序列集成到一起(归并)
def merge_sort(l):
    n = len(l)
    if 1==n:
        return l
    d = n // 2
    left_list = merge_sort(l[:d])  #左边
    right_list = merge_sort(l[d:]) #右边
    #合并两边  左序列与右序列比较,小数先存入另一个数组中
    left = right = 0
    left_len = len(left_list)
    right_len = len(right_list)
    merged_l = []
    while left <left_len and right< right_len:
        if left_list[left] <= right_list[right]:
            merged_l.append(left_list[left])
            left = left +1
        else:
            merged_l.append(right_list[right])
            right = right +1
    #若两边比较完后,某一边还剩数字没加入数组中,则全部加入数组中
    merged_l +=left_list[left:]
    merged_l +=right_list[right:]
    return merged_l
if __name__ == '__main__':
    s =[54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(merge_sort(s))

堆排序

def heap_sort(lst):
    #最大堆调整
    def sift_down(start,end):
        print('调整数字:',lst[start:end+1])
        root = start
        while True:
            child = 2*root +1  #左孩子
            if child>end:  #孩子索引大于数组最大长度
                break
            if child +1<=end and lst[child]<lst[child+1]: #左孩子小于右孩子,则最大值节点在右孩子,否则不变,依旧是左孩子
                child = child+1
            if lst[root]<lst[child]:  #根节点与当前子节点最大值比较
                lst[root],lst[child] = lst[child],lst[root]
                print(root, child)
                print(lst[root], lst[child])
                root = child
            else:
                break
    #创建最大堆
    for start in range((len(lst)-2)//2,-1,-1):
        #(len(lst)-2)//2 为最后一个有子节点的位置
        sift_down(start,len(lst)-1)
        print('lst', lst)
    #堆排序
    for end in range(len(lst)-1,0,-1):
        print('堆排序',lst[:end+1])
        lst[0],lst[end]=lst[end],lst[0]#首尾交换,数组中最后为最大,前面的数重新堆排序
        sift_down(0,end-1)
        print('一趟排序后',lst)
    return lst
alist =[70,22,12,30,40,20,10]
print(heap_sort(alist))

二分查找

递归查找

# 针对已经有序的序列,进行二分查找,可以递归实现也可以非递归
# 递归查找
def binary_search(l,num):
    n = len(l)
    if 0 == n:
        return False
    mid = n // 2
    if l[mid] == num:
        return True,mid
    elif num < l[mid]:
        return binary_search(l[:mid],num)
    else:
        return binary_search(l[mid+1:],num)
if __name__ == '__main__':
    s = [0, 1, 2, 8, 13, 17, 19, 32, 42]
    print(binary_search(s,13))

非递归查找

def binary_search(l,num):
    n = len(l)
    start = 0
    end = n-1
    while start<=end: 
        mid = (start + end)//2
        if l[mid] == num:
            return True,mid
        elif num <l[mid]:  #要找的数在左边,end指向左边最后,去左边找
            end = mid -1
        else:    #要找的数在右边,start指向右边第一个,去右边找
            start = mid + 1
    return False
if __name__ == '__main__':
    s = [0, 1, 2, 8, 13, 17, 19, 32, 42]
    print(binary_search(s,13))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值