设为首页 收藏本站
查看: 1412|回复: 0

[经验分享] 算法抽象及用Python实现具体算法

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-5-30 17:37:00 | 显示全部楼层 |阅读模式
一、算法抽象

    它们一般是在具体算法的基础上总结、提炼、分析出来的,再反过来用于指导解决其它问题。它们适用于某一类问题的解决,用辩

证法的观点看,抽象的算法和具体的算法就是抽象与具体、普遍性与特殊性、共性和个性的关系。马是白马的抽象,无论是白马还是红

马,都是马,我们用马的唯一本质属性——染色体来决定一种动物是否是马,这个本质属性就是马的抽象。

(1)分治法

    分治法的基本思想是先分割原问题,将原问题分割成一个或多个简单的子问题,这些子问题的解经过一定组合得到原问题的解,而求

解这些子问题时,常常会再次分解,组合,即迭代上面的过程。再进一步总结可以得到分治法的步骤:分解、求解子问题、组合。而至

于怎么分解、组合,分治法没有抽象出规律。自己想怎么做就怎么做,比如归并排序和快速排序,都是用的分治法,但分解和组合过程

不一样。分治法适用于解决易分解为子问题的问题。

    我们可以给出分治法的伪代码框架,针对某个具体的问题,需进行适当的修改,比如参数个数等,由于数学功底不是很牛B,我没有办

法证明该框架适用于所有的递归函数和所有基于分治法的算法,但我还没有发现不适用的情况。还有,如果子结节是直接在原问题对象上进

行的操作,那有时子结节就不需要返回值(返回None就行)给父结点了,父结点也不会用这些结点的返回值,因为所有结点操作的是同

一个共享资源,这点见快速排序;另外,对于像二分查找,对于任意一次查找的过程,它其实只是走的某个结点到根结点的路径而已,它

每次分解后只用到其中一个结点,这样它也就没有merge()可言了。

    看了下面代码,是不是感觉跟MapReduce的思想有些相似,是的,MapReduce其实是就是基于分治法思想的。MapReduce中的Map

就对应下面的map()方法,而Reduce其实是merge()方法的一种特例而已,因为merge()是根据具体问题而定的,不一定就是迭代函数。

因为MapReduce是基于分治法的,所以适用场景与只能是分治法适用场景的一个子集。


def handler(obj):
    end_ret = is_end(obj)
    if end_ret[0]== True: #递归结束点
        return end_ret[1]   
    else:                 #非结束点,递归调用
       subnode_tuple = separate(obj) #该节点分割,分割为一个或多个子节点
       subnode_rettuple = map(handler, subnode_tuple) #求解每个子节点的解,递归调用
       node_ret = merge(subnode_rettuple,obj) #将子节点的解组合,组合时有时也会用到节点的某些数据
       return node_ret  



   

二、 具体算法

(1)快速排序

    快速排序其实是用的分治法的思想,归并排序也是用的分治法,同样都是分治法,但策略不同。我们在“分治法”中提到分治法分为三

个步骤:分解、求解子问题、组合。快速排序和归并排序的不同体现在分解上,分解不同,后面的组合也常常不同。快速排序在分解时

会有一定的排序,也就是边分解边求解,它们是在原对象上直接进行的操作,操作完也不需要组合。归并的主要工作在组合上,分解过

程非常简单,归并的过程也完全可以在原对象(原序列)上进行。

    快速排序一次分割会把序列中的某一个元素(任意选择一个即可)确定好位置,并把序列以该元素为界分为两部分,一部分大于等于

该元素,另一部分小于等于该元素,然后再递归分解这两部分(确定好位置的那个元素无需再排序,不用放在这两部分中),直到分割

的部分只有一个元素或为空。递归就是树的分解过程,子节点可以直接操作原问题对象(原序列),操作完之后,相当于原序列的某个

部分就是有序的了。这样子结节无需再返回值让父节点用了。下面是快速排序代码,第一个没用分治法框架,第二个用了。子结点和叶

节点其实不需用返回值,但为了更好的用分治法框架理解,还是让他们返回值好了。


#-*- coding=utf-8 -*-
def qsort(s,start_index,end_index):
    if start_index>=end_index:
        if start_index == end_index:
            return [s[start_index]]
        else:
            return []
else:
        i = separate(s,start_index,end_index)
        #不用考虑索引为i的元素,它已经排好序了
        left_ret = qsort(s,start_index,i-1)
        right_ret = qsort(s,i+1,end_index)
        node_ret = left_ret + [s[i]] + right_ret
        return node_ret


#分治,排好start_index的位置,并将序列分为两部分
def separate(s,start_index,end_index):
    key = s[start_index]
    empty_index = start_index #空位指针
    track_index = end_index #跟踪指针
    while empty_index != track_index:
        if track_index > empty_index:
            if s[track_index] < key:
                s[empty_index] = s[track_index]
                track_index,empty_index = empty_index,track_index
                track_index +=1
            else:
                track_index -=1
        else:
            if s[track_index] > key:
                s[empty_index] = s[track_index]
                track_index,empty_index = empty_index,track_index
                track_index -=1
            else:
                track_index +=1
    s[empty_index] = key
    return empty_index

a = [12,3,9,10,87,25,8,9,47,11,1,100,85,47,59,81,60,33]
b = qsort(a,0,len(a)-1)
print a
print b




使用分治法框架,与不使用的代码相比,只是微小的重构而已。


# -*- coding=utf-8 -*-
def qsort(obj):
    s = obj[0]
    start_index = obj[1]
    end_index = obj[2]
    end_ret = is_end(obj)
    if end_ret[0]== True:
        return end_ret[1]
    else:
        i = separate(obj)
        #不用考虑索引为i的元素,它的位置已经确定了
        subnode1 = (s,start_index,i-1)
        subnode2 = (s,i+1,end_index)
        subnode_tuple = (subnode1,subnode2)
        subnode_rettuple = map(qsort,subnode_tuple)
        node_ret = merge(subnode_rettuple,obj[0][i])
        return node_ret

def is_end(obj):
    s = obj[0]
    start_index = obj[1]
    end_index = obj[2]
    if start_index>=end_index:
        if start_index == end_index:
            return (True,[s[start_index]])
        else:
            return (True,[])
    else:
        return (False,None)

#分治,排好start_index的位置,并将序列分割成两部分
def separate(obj):
    s = obj[0]
    start_index = obj[1]
    end_index = obj[2]
    key = s[start_index]
    empty_index = start_index #空位指针
    track_index = end_index #跟踪指针
    while empty_index != track_index:
        if track_index > empty_index:
            if s[track_index] < key:
                s[empty_index] = s[track_index]
                track_index,empty_index = empty_index,track_index
                track_index +=1
            else:
                track_index -=1
        else:
            if s[track_index] > key:
                s[empty_index] = s[track_index]
                track_index,empty_index = empty_index,track_index
                track_index -=1
            else:
                track_index +=1
    s[empty_index] = key
    return empty_index

def merge(subnode_rettuple,obj):
    return subnode_rettuple[0] + [obj] + subnode_rettuple[1]



a = [12,3,9,10,87,25,8,9,47,11,1,100,85,47,59,81,60,33]
obj = (a,0,len(a)-1)
b = qsort(obj)
print a
print b







运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-19950-1-1.html 上篇帖子: python 批量下载图片 下篇帖子: linux系统服务rsync启动脚本
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表