Python算法之排序与二分法

可你觉得孤独又能怎么样啊?你觉得孤独也不过是心情更差而已嘛。以前没什么人跟你说话,你觉得孤独,也还是没人跟你说话啊。

排序算法之插入排序

插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。

算法步骤

1.将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

2.从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

代码实现

arr = [random.randint(1,20)for _ in range(20)]
def insertionSort(arr):
    for i in range(len(arr)):
        preIndex = i-1
        current = arr[i]
        while preIndex >= 0 and arr[preIndex] > current:
            arr[preIndex+1] = arr[preIndex]
            preIndex-=1
        arr[preIndex+1] = current
    return arr
for x in insertionSort(arr):print x

运行结果:

1
2
4
4
4
6
7
7
8
9
9
11
12
13
14
15
15
16
17
20

bisect实现顺序插入和二分法

Python 有一个 bisect 模块,用于维护有序列表。bisect 模块实现了一个算法用于插入元素到有序列表。在一些情况下,这比反复排序列表或构造一个大的列表再排序的效率更高。Bisect 是二分法的意思,这里使用二分法来排序,它会将一个元素插入到一个有序列表的合适位置,这使得不需要每次调用 sort 的方式维护有序列表。

使用bisect实现排序后插入数据

Bisect模块提供的函数有:

bisect.bisect_left(a,x, lo=0, hi=len(a)) :
查找在有序列表 a 中插入 x 的index。lo 和 hi 用于指定列表的区间,默认是使用整个列表。如果 x 已经存在,在其左边插入。返回值为 index。

bisect.bisect_right(a,x, lo=0, hi=len(a))
bisect.bisect(a, x,lo=0, hi=len(a)) :
这2个函数和 bisect_left 类似,但如果 x 已经存在,在其右边插入。

bisect.insort_left(a,x, lo=0, hi=len(a)) :
在有序列表 a 中插入 x。和 a.insert(bisect.bisect_left(a,x, lo, hi), x) 的效果相同。

bisect.insort_right(a,x, lo=0, hi=len(a))
bisect.insort(a, x,lo=0, hi=len(a)) :
和 insort_left 类似,但如果 x 已经存在,在其右边插入。

bisect.bisect()与bisect.insert()不同在于第一个并不会真的插入数据进去,第二个插入数据进去。

代码实例

arr = [random.randint(1,20)for _ in range(20)]
x=10
ret=bisect.bisect(arr,x)
## 打印x在列表中排第几,如果用insert的话,会把x插入进arr列表中
print ret

运行结果:

8

使用bisect实现二分法

二分查找的对象是:有序数组。这点特别需要注意。

常规方法实现二分法

下面有两种实现方法,一种是用递归,另一种是是用while循环控制。

def binarySearch1(lst,value,low,high):  
    if high < low:  
        return -1  
    mid = (low+high)/2  
    if lst[mid]>value:  
        return binarySearch1(lst,value,low,mid-1)  
    elif lst[mid]<value:  
        return binarySearch1(lst,value,mid+1,high)  
    else:  
        return mid  
def binarySearch2(lst,value):  
    low,high = 0,len(lst)-1  
    while low<=high:  
        mid = (low+high)/2  
        if lst[mid]<value:  
            low = mid + 1  
        elif value<lst[mid]:  
            high = mid - 1  
        else:  
            return mid  
    return -1  

if __name__ == '__main__':  
    l = range(50)  
    print binarySearch1(l,10,0,49)  
    print binarySearch2(l,10)  

bisect实现二分法

import bisect
arr = [random.randint(1,20)for _ in range(20)]
x=10
def binarySearch3(lst,x):
    i = bisect.bisect_left(lst,x)
    if i != len(lst) and lst[i] == x:
        return i
    raise ValueError
print binarySearch3(arr,x)

运行结果:

7

bisect常用与计算排序的地方,比如你得到一批数据,这批数据是一个一个获取的,你想维护这批数据的顺序,那么使用bisect.insert()逐个插入排序即可。

代码实现二分法查找数值

比如有一组有序数列,我要查找某个数值在这个数列的位置,使用二分法实现。

# -*- coding: utf-8 -*-
# @Time    : 2018/7/3 0003 14:23
# @Author  : Langzi
# @Blog    : www.langzi.fun
# @File    : 二分法.py
# @Software: PyCharm
import sys
import random
reload(sys)
sys.setdefaultencoding('utf-8')
def fun1(list_1,num):
    low,hight = 0,len(list_1)-1
    while low <= hight:
        mid = (low+hight)/2
        guess = list_1[mid]
        if guess == num:
            return mid
        if guess > num:
            hight = mid - 1
        else:
            low = mid + 1
    return None
list_1 = sorted([random.randint(1,20) for _ in range(10)])
print list_1
num = 5
print fun1(list_1,num)
坚持原创技术分享,您的支持将鼓励我继续创作!
------ 本文结束 ------

版权声明

LangZi_Blog's by Jy Xie is licensed under a Creative Commons BY-NC-ND 4.0 International License
由浪子LangZi创作并维护的Langzi_Blog's博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Langzi_Blog's 博客( http://langzi.fun ),版权所有,侵权必究。

0%