美文网首页
查找与排序总结

查找与排序总结

作者: 小八是怪兽 | 来源:发表于2019-09-29 12:42 被阅读0次

查找

  1. 线性查找
def seq_search(target,alist):
   found = False
   pos = 0
   count = 0
   while not found and pos < len(alist):
       count = count + 1
       if alist[pos] == target:
           found = True
       else:
           pos = pos + 1
   return found,count

时间复杂度
情况1: item is present:

  • best : O(1)
  • worst : O(n)
  • avg : O(n/2)

情况2 : item is not present:

  • best : O(n)
  • worst : O(n)
  • avg : O(n)

优化: 当要查找的列表是有序列表时,可以加入一个提前结束判断来优化时间复杂度。

def seq_search_ordered(target,alist):
    found = False
    pos = 0
    stop = False
    count = 0
    while not found and pos < len(alist) and not stop:
        count = count + 1
        if alist[pos] == target:
            found = True
        
        if alist[pos] > target:
            stop = True #如果当前元素大于目标元素,则停止查找
        
        pos = pos + 1
    return found,count
  1. 二分查找
def binary_search(target,alist):
    low = 0
    high = len(alist) - 1
    found = False
    while not found and low <= high:
        mid = (high+low)//2
        if alist[mid] == target:
            found = True
        else:
            if alist[mid] > target:
                high = mid - 1 
                
            else:
                low = mid + 1
                
                
    return found

时间复杂度:

  • worst : O(n) 逆序的
  • best : O(1) 本身排好序的
  • avg : O(logn)
  1. 哈希查找
  • 键(key):要存储在槽中的数据或数据的一部分。
  • 槽(slot):哈希表中用于保存数据的一个单元,也就是数据真正存放的容器。
  • 哈希函数(hash function):将键(key)映射(map)到数据应该存放的槽(slot)所在位置的函数。
    base: remainder
    扩展:
    1. 折叠法
      将数据均分成相等的长度(最后一个部分可能不等),然后相加取余。
      For example, if our item was the phone number 436-555- 4601, we would take the digits and divide them into groups of 2 (43, 65, 55, 46, 01). After the addition, 43 + 65 + 55 + 46 + 01, we get 210.
      假设slot总数为11,则hash_num = 210 % 11 = 10
    2. 平方取中法
      数据取平方然后取中间的数。
      44^2 = 1936 hash_num = 93 % 11 = 5
    3. 对字符串来说
      ‘cat’ 99 + 97 + 116 = 312 hash_num = 312%11 = 4
  • 哈希冲突(hash collision):哈希函数将两个不同的键映射到同一个索引的情况。
    解决方案:
    1. 开放地址法。open addressing
      如果slot不为空,则继续寻找直到找到下一个空槽。
    • 线性探查 (linear probing)
      线性探查,如果T(n)不为空,则T(n+1)...直到T(n-1)
      问题: 产生聚集
      再哈希法
      当产生冲突时,再hash一遍来跳过n个槽
    • 平方探测 (线性探测的变种)
      每次跳过1,3,5,7,..个slot而不是常数个。
      如果第一个哈希值时h, 则h+1,h+4,h+9,h+16
    1. 链地址法
      这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。
  1. 分块/索引查找
  • 块间有序,块内无序
  • 先使用二分查找搜索索引表,找到具体块,然后在块内用线性查找。
  • 索引表包含两个元素:该快的起始元素的位置;该块中的最大值(或最小值)
  • ASL 平均搜索长度: 索引表二分查找平均搜索长度+ 块内线性查找平均搜索长度
    假设共有s个元素,分为m块,每块中有n个元素, (1+2+...+m)/m + (1+2+...+n)/n = (m+n)/2 + 1

搜索总结

  • 由于binary search要求列表有序,所以对于排序一次可搜索多次的小列表来说较好
  • 对于大列表来说,线性搜索而不是先排序再使用二分搜索可能更高效。

排序

  1. 冒泡排序
def bubble_sort(alist):
    for i in range(len(alist)-1):
        exchange = False # exchange flag
        for j in range(len(alist)-i-1):
            if alist[j] > alist[j+1]:
                alist[j],alist[j+1] = alist[j+1],alist[j]
                exchange = True
        if not exchange : #优化算法,如果一次遍历中没有交换,则已排好序
            return alist
    return alist

时间复杂度:

  • worst : O(n^2) 如列表本身为逆序时
  • best : O(n) 如列表本身排好序的
  1. 快速排序
def quick_sort(alist):
    if len(alist) == 0:
        return alist
    pivot = alist[0]
    left = [each for each in alist if each < pivot]
    right = [each for each in alist if each > pivot]
    return quick_sort(left) + [pivot] + quick_sort(right)

时间复杂度:

  • worst : O(n^2) 如pivot无法很好的分割,或者列表本身逆序
  • avg : O(nlogn)

扩展
上述方法可以直接用于数组去重
若数组可重复,则将上述left\right任一判断方式改为<=或>=即可。

  1. 选择排序
    每次选取当前最大的数并放在合适的位置。
def selection_sort(alist):
    for pos in range(len(alist)-1, 0, -1):
        max_pos = 0
        for i in range(0,pos+1):
            if alist[max_pos] < alist[i]:
                max_pos = i
        alist[max_pos], alist[pos] = alist[pos],alist[max_pos]
    return alist

T(n) = n + (n-1) + (n-2) + ... + 1 = (n^2 + n)/2
时间复杂度为O(n^2). 但是由于更少的交换次数,还是比冒泡排序法要优化。

相关文章

  • 排序+查找总结

    排序总结 查找总结

  • 查找与排序总结

    查找 线性查找 时间复杂度情况1: item is present: best : O(1) worst : O(...

  • java (查找和排序)

    1.查找 递归形式: 二分查找: 2.排序方式 下面这个表格总结了各种排序算法的复杂度与稳定性: 冒泡排序 特点:...

  • 18-04-27  python3 算法笔记 003查找与排序

    查找: 顺序查找 二分查找 hash查找 排序: 冒泡排序 选择排序 插入排序希尔排序 归并排序 快速...

  • 排序算法的基本操作:两两交换数组中元素

    查找 vs 排序 比较查找与排序算法 说起来查找算法和排序算法从功能到使用目的都大有不同,但其实我们将要学习的(比...

  • 基础查找算法分析

    在之前学习了一些排序算法,得出了基础排序算法的总结。之后学习了一些查找算法,今天来对于基础的一些查找算法进行总结。...

  • 排序与查找

    参考:程序员必知8大排序3大查找(一)程序员必知8大排序3大查找(二)程序员必知8大排序3大查找(三)图解排序算法...

  • 排序与查找

    1、顺序查找的思想: 将待查找的关键字为key的元素从头到尾与表中元素进行比较,如果中间存在关键字为key的元素,...

  • 2.4.2 查找和排序

    排序 复习1:冒泡排序 复习2:快速排序 查找 1)顺序查找2)二分查找 3)哈希表查找4)二叉排序树查找

  • 面试知识点

    排序冒泡排序快速排序选择排序插入排序二路归并 查找二分查找 排序和查找的java实现 java语言Java字符串字...

网友评论

      本文标题:查找与排序总结

      本文链接:https://www.haomeiwen.com/subject/wkfuectx.html