常用的查找和简单排序算法(python版)

常用的查找

什么是查找?
在一些数据元素中,通过一定的方法找出与给定关键字相同的数据元素的过程

列表查找(线性表查找)
从列表中查找指定的元素
输入:列表,待查找的元素
输出:元素下标(未找到时返回None或-1)

顺序查找(linear_search)

def linear_search(li, val):
    for ind, v in enumerate(li):
        if v == val:
            return ind
        else:
            return None

二分查找(binary_search)

def binary_search(li, val):
    left, right = 0, len(li)-1

    while left <= right:  # 候选区有值
        mid = (left + right) // 2
        if li[mid] == val:
            return mid
        elif li[mid] > val:  # 查找的值在mid左侧
            right = mid - 1
        else:  # 查找的值在mid右侧
            left = mid + 1
    else:
        return None

------------------------------------------------------------华丽的分割线-----------------------------------------------------------

简单的排序算法

什么是排序?
将一组"无序"的记录序列调整为"有序"的记录序列.

常见的排序算法

  • LowB 三人组
    1,冒泡排序
    2.选择排序
    3,插入排序
  • NB三人组
    1,快速排序
    2.堆排序
    3.归并排序
  • 其他排序
    1.希尔排序
    2.计数排序
    3.基数排序

Low B三人组

1.冒泡排序

# 升序排序
def bubble_sort_up(li):
    for i in range(len(li) - 1):  # 第i趟
        flag = False  # 如果一趟循环里没有交换 证明列表已经有序
        for j in range(len(li) - i - 1):  # 键头
            if li[j] > li[j + 1]:
                li[j], li[j + 1] = li[j + 1], li[j]
                flag = True
        if not flag:
            return


# 降序排序
def bubble_sort_down(li):
    for i in range(len(li) - 1):  # 第i趟
        flag = False
        for j in range(len(li) - i - 1):
            if li[j] < li[j + 1]:
                li[j], li[j + 1] = li[j + 1], li[j]
                flag = True
        if not flag:
            return

2.选择排序

# 选择排序
def select_sort_simple(li):  # 简单 不推荐
    li_new = []
    for i in range(len(li)):
        min_val = min(li)
        li_new.append(min_val)
        li_new.remove(min_val)
    return li_new


def select_sort(li):
    for i in range(len(li) - 1):  # 第i趟
        min_loc = i  # 假设 无序区第i个位置是最小
        for j in range(i + 1, len(li)):
            if li[j] < li[min_loc]:
                min_loc = j
        li[i], li[min_loc] = li[min_loc], li[i]

3.插入排序

把拆入排序想象成打扑克牌时抓牌的过程,从小到大进行插入

# 插入排序
def insert_sort(li):
    for i in range(1, len(li)):  # 摸到的牌
        temp = li[i]
        j = i - 1  # 手里的牌的下标
        while j >= 0 and li[j] > temp:
            li[j + 1] = li[j]
            j -= 1
        li[j + 1] = temp

NB三人组

1.快速排序

# 快速排序

def partition(li, left, right):
    temp = li[left]
    while left < right:
        while left < right and li[right] >= temp:  # 从右边找比temp小的数
            right -= 1  # 右游标向左移动
        li[left] = li[right]
        while left < right and li[left] <= temp:  # 从左边找比temp小的数
            left += 1  # 左游标向右移动
        li[right] = li[left]
    li[left] = temp  # 把temp归位
    return left


def quick_sort(li, left, right):
    if left < right:  # 至少有两个元素
        mid = partition(li, left, right)
        quick_sort(li, left, mid - 1)
        quick_sort(li, mid + 1, right)

2.堆排序

# 堆排序

def sift(li, low, high):
    """
    :param li: 列表
    :param low: 根节点位置
    :param high:堆的最后一个元素位置
    :return:
    """

    i = low  # i指向最开始的根节点
    j = 2 * i + 1  # 左孩子位置
    temp = li[low]  # 把堆顶存起来
    while j <= high:  # j的位置有数
        if j + 1 < high and li[j] < li[j + 1]:  # 右孩子存在并且比较大
            j = j + 1  # 指向右孩子
        if li[j] > temp:
            li[i] = li[j]
            i = j  # 向下移动指针
            j = 2 * i + 1
        else:  # temp更大,放在i的位置
            li[i] = temp
            break
    else:
        li[i] = temp # 把temp放到叶子节点上


def heap_sort(li):
    n = len(li)
    for i in range((n - 2) // 2, -1, -1):
        # 将i指向最后一个位置
        sift(li, i, n - 1)
    # 建堆完成了
    for i in range(n - 1, -1, -1):
        li[0], li[i] = li[i], li[0]
        sift(li, 0, i - 1)  # i-1是新的high

3.归并排序

# 归并排序

# mid两边有序时使用
def merge(li, low, mid, high):
    i = low
    j = mid + 1
    ltemp = []
    while i <= mid and j <= high:  # 两边都有数
        if li[i] > li[j]:
            ltemp.append(li[j])
            j += 1
        else:  # li[j] > li[i]
            ltemp.append(li[i])
            i += 1
    while i <= mid:
        ltemp.append(li[i])
        i += 1
    while j <= high:
        ltemp.append(li[j])
        j += 1
    li[low:high + 1] = ltemp


def merge_sort(li, low, high):
    if low < high:  # 至少两个数
        mid = (low + high) // 2
        # 左边排序
        merge_sort(li, low, mid)
        # 右边排序
        merge_sort(li, mid + 1, high)
        merge(li, low, mid, high)

其它排序

1.希尔排序

# 希尔排序

def insert_sort_gap(li, gap):
    for i in range(gap, len(li)):
        temp = li[i]
        j = i - gap
        while j >= 0 and li[j] > temp:
            li[j + gap] = li[i]
            j -= gap
        li[j + gap] = temp


def shell_sort(li):
    d = len(li) // 2
    while d >= 1:
        insert_sort_gap(li, d)
        d // 2

2.计数排序

# 计数排序

def count_sort(li, max_count=100):
    count = [0 for _ in range(max_count + 1)]
    for val in li:
        count[val] += 1
    li.clear()
    for index, value in enumerate(count):
        for i in range(value):
            li.append(index)

3.桶排序

# 桶排序

def bucket_sort(li, n=100, max_num=10000):
    """
    :param li:
    :param n: 分成多少给桶
    :param max_num: 范围
    :return:
    """
    bucket = [[] for _ in range(n)]  # 创建n给桶
    for var in li:
        i = min(var // (max_num // n), n - 1)  # i表示 var放到几号桶里
        bucket[i].append(var)  # 把var加到桶里
        # 保持桶内顺序
        for j in range(bucket[i] - 1, 0, -1):
            if bucket[i][j] < bucket[i][j - 1]:
                bucket[i][j], bucket[i][j - 1] = bucket[i][j - 1], bucket[i][j]
            else:
                break
    sorted_li = []
    for buc in bucket:
        sorted_li.extend(buc)
    return sorted_li

4.基数排序

# 基数排序

def radix_sort(li):
    max_num = max(li)
    it = 0
    while 10 ** it <= max_num:
        buckets = [[] for _ in range(10)]
        for var in li:
            digit = (var // 10 ** it) % 10
            buckets[digit].append(var)
        # 分桶完成
        li.clear()
        for buc in buckets:
            li.extend(buc)  # 把数重新写回li

        it += 1

总结

1.LowB三人组

  • 三种算法的时间复杂度都是O(n2)
  • 在数据规模较小时,直接插入排序,简单选择排序差不多。
    当数据较大时,冒泡排序算法的时间代价最高。性能为O(n^2)的算法基
    本上是相邻元素进行比较,基本上都是稳定的。

2.NB三人组

  • .三种算法的时间复杂度都是O(nlogn)
  • 一般情况下就运行时间来说: 快速排序 < 归并排序 < 堆排序
  • 三种算法的缺点:
    - 快速排序: 极端情况下排序效率较低
    - 归并排序: 需要额外的内存开销
    - 堆排序: 在快的排序算法来说相对较慢

-----------------------------------------------------------------------------------------------------------------------------------
  稳定:冒泡排序、插入排序、归并排序和基数排序
 
  不稳定:选择排序、快速排序、希尔排序、堆排序

参考视频链接

#####] >原视频链接(清华大学博士讲解Python数据结构与算法(完整版)全套100节)

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值