码迷,mamicode.com
首页 > 编程语言 > 详细

算法导论—中位数与顺序统计量

时间:2015-07-08 00:34:54      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:算法导论   顺序统计量   快速排序   

一、选择最大值或者最小值的最优算法
对于长度为n的数组,已证找最大值或者最小值比较操作下界就是n-1。所以只需要让第一个值为初始最大值或者初始最小值,用所有的值与这个值比较,更新这个值即可。

def minimum(a):
    minNum=a[0]
    for i in range(1,len(a)):
        if minNum>a[i]:
            minNum=a[i]
    return minNum
print(minimum ([1,2,3,4,5,6,7,8,9]))

二、同时选择最大值和最小值的快速算法(成对比较)
首先设置一对初始的最大值最小值(总数个数是奇数,初始最大值最小值为第一个数,若是偶数就为前两个比较),然后剩下的数两两组对,对内比较大小,然后小的与当前最小的比,大的与当前最大的比。这样的话两个数需要比较三次。如果选择分别计算最大值最小值需要2(n-1)次比较,采用成对比较的话只需要3int(n/2)次

def minmax(a):
    k=len(a)
    if k%2==0:
        if a[0]<a[1]:
            minNum,maxNum=a[0],a[1]
        else:
            minNum,maxNum=a[1],a[0]
    else:
        minNum,maxNum=a[0],a[0]
    for i in range(2-k%2,k,2):
        if a[i]>a[i+1]:
            a[i+1],a[i]=a[i],a[i+1]
        if a[i]<minNum:
            minNum=a[i]
        if a[i+1]>maxNum:
            maxNum=a[i+1]
    return minNum,maxNum
print(minmax([1,2,3,4,5,6,7,8,9]))

三、期望时间为线性时间的选择算法—随机选择
回想一下,快速排序的时候,选择一个数(随机)为基准,左右交换将小于基准的分到左边,大于基准的分到右边的思想,然后得到这个数在数组中的位置,这样我们可以根据这个位置判断我们要的数所处的位置,逐步缩小搜索范围。

import random

def randomizedPartion(a,p,r):
    k=random.randint(p, r)
    a[k],a[r]=a[r],a[k]
    value=a[r]
    i=p-1
    for j in range(p,r):
        if a[j]<value:
            i+=1
            a[i],a[j]=a[j],a[i]
    i+=1
    a[i],a[r]=a[r],a[i]
    return i

def randomizedSelect(a,p,r,i):
    q=randomizedPartion(a,p,r)
    k=q-p+1
    if k==i:
        return a[q]
    else:
        if i<k:
            return randomizedSelect(a,p,q-1,i)
        else:
            return randomizedSelect(a,q+1,r,i-k)

lst=[2,6,3,1,5,0,7,8,4,9]
k=randomizedSelect(lst,0,len(lst)-1,10)
print(k)

四、最坏时间为线性时间的选择算法—中位数的中位数划分
基于快速排序的舍弃法,不考虑直接命中的情况的话一次平均舍弃一半的数。
select算法的思想为:首先对数组中所有的数分组,每个组的大小为奇数,然后计算每个组的中位数,然后计算所有组的中位数的中位数,获取这个中位数在数组的位置,然后比较舍弃。这样每次舍弃的下限就不是基于快速算法的0了。

def midNum(a):
    k=len(a)
    groupNum=5
    start=0
    while start<k:
        end=min(k-1,start+4)
        InsertSort(a,start,end)
        start+=5
    if k<5:
        return a[(k-1)//2]
    else:
        b=a[(groupNum//2)::groupNum]
        return midNum(b)

def InsertSort(a,start,end):
    for k in range(start+1,end+1):
        i=k
        while a[i-1]>a[i] and i>start:
            a[i-1],a[i]=a[i],a[i-1]
            i-=1
    return a

def PartionByValue(a,x):
    i=0
    j=0
    for k in range(0,len(a)):
        if a[k]<x:
            a[k],a[i]=a[i],a[k]
            i+=1
    for k in range(i,len(a)):
        if a[k]==x:
            j=k
    a[i],a[j]=a[j],a[i]
    return i

def select(a,i):
    mid=midNum(a)
    k=PartionByValue(a,mid)+1
    if i==k:
        return mid
    else:
        if i<k:
            return select(a[0:k-1],i)
        else:
            return select(a[k::],i-k)

lst=[2,6,3,1,5,0,7,8,4,9]
k=select(lst,10)
print(k)

版权声明:本文为博主原创文章,未经博主允许不得转载。

算法导论—中位数与顺序统计量

标签:算法导论   顺序统计量   快速排序   

原文地址:http://blog.csdn.net/zhangzhengyi03539/article/details/46795831

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!