搜索是在一个项目集合中找到一个特定项目的算法过程。搜索通常的答案是真的或假的,因为该项目是否存在。 搜索的几种常见方法:顺序查找、二分法查找、二叉树查找、哈希查找

线性查找
线性查找就是从头找到尾,直到符合条件了就返回。比如在一个 list 中找到一个等于 5 的元素并返回下标:

number_list = [0, 1, 2, 3, 4, 5, 6, 7]

def linear_search(value, iterable):
for index, val in enumerate(iterable):
if val == value:
return index
return -1 assert linear_search(5, number_list) == 5

是不是 so easy。当然我们需要来一点花样,比如传一个谓词进去,你要知道,在 python 里一切皆对象,所以我们可以把函数当成一个参数传给另一个函数。

def linear_search_v2(predicate, iterable):
for index, val in enumerate(iterable):
if predicate(val):
return index
return -1
assert linear_search_v2(lambda x: x == 5, number_list) == 5

效果是一样的,但是传入一个谓词函数进去更灵活一些,比如我们可以找到第一个大于或者小于 5 的,从而控制函数的行为。 还能玩出什么花样呢?前面我们刚学习了递归,能不能发挥自虐精神没事找事用递归来实现呢?

def linear_search_recusive(array, value):
if len(array) == 0:
return -1
index = len(array)-1
if array[index] == value:
return index return linear_search_recusive(array[0:index], value)

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

二分法查找实现
(非递归实现)

def binary_search(alist, item):
first = 0
last = len(alist)-1
while first<=last:
midpoint = (first + last)/2
if alist[midpoint] == item:
return True
elif item < alist[midpoint]:
last = midpoint-1
else:
first = midpoint+1
return False testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13)) (递归实现)
def binary_search(alist, item):
if len(alist) == 0:
return False
else:
midpoint = len(alist)//2
if alist[midpoint]==item:
return True
else:
if item<alist[midpoint]:
return binary_search(alist[:midpoint],item)
else:
return binary_search(alist[midpoint+1:],item) testlist = [0, 1, 2, 8, 13, 17, 19, 32, 42,]
print(binary_search(testlist, 3))
print(binary_search(testlist, 13))er

时间复杂度

最优时间复杂度:O(1)
最坏时间复杂度:O(logn)

二叉树
二叉树的基本概念

二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)

二叉树的性质(特性)

性质1: 在二叉树的第i层上至多有2^(i-1)个结点(i>0)
性质2: 深度为k的二叉树至多有2^k - 1个结点(k>0)
性质3: 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
性质4:具有n个结点的完全二叉树的深度必为 log2(n+1)
性质5:对完全二叉树,若从上至下、从左至右编号,则编号为i 的结点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i=1 时为根,除外)

(1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。

(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。

二叉树的节点表示以及树的创建
通过使用Node类中定义三个属性,分别为elem本身的值,还有lchild左孩子和rchild右孩子

class Node(object):
"""节点类"""
def __init__(self, elem=-1, lchild=None, rchild=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild
#树的创建,创建一个树的类,并给一个root根节点,一开始为空,随后添加节点 class Tree(object):
"""树类"""
def __init__(self, root=None):
self.root = root def add(self, elem):
"""为树添加节点"""
node = Node(elem)
#如果树是空的,则对根节点赋值
if self.root == None:
self.root = node
else:
queue = []
queue.append(self.root)
#对已有的节点进行层次遍历
while queue:
#弹出队列的第一个元素
cur = queue.pop(0)
if cur.lchild == None:
cur.lchild = node
return
elif cur.rchild == None:
cur.rchild = node
return
else:
#如果左右子树都不为空,加入队列继续判断
queue.append(cur.lchild)
queue.append(cur.rchild)

二叉树的遍历
树的遍历是树的一种重要的运算。所谓遍历是指对树中所有结点的信息的访问,即依次对树中每个结点访问一次且仅访问一次,我们把这种对所有节点的访问称为遍历(traversal)。那么树的两种重要的遍历模式是深度优先遍历和广度优先遍历,深度优先一般用递归,广度优先一般用队列。一般情况下能用递归实现的算法大部分也能用堆栈来实现。

深度优先遍历

对于一颗二叉树,深度优先搜索(Depth First Search)是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
那么深度遍历有重要的三种方法。这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。这三种遍历分别叫做先序遍历(preorder),中序遍历(inorder)和后序遍历(postorder)。我们来给出它们的详细定义,然后举例看看它们的应用。

先序遍历 在先序遍历中,我们先访问根节点,然后递归使用先序遍历访问左子树,再递归使用先序遍历访问右子树
根节点->左子树->右子树

def preorder(self, root):
"""递归实现先序遍历"""
if root == None:
return
print root.elem
self.preorder(root.lchild)
self.preorder(root.rchild)
中序遍历 在中序遍历中,我们递归使用中序遍历访问左子树,然后访问根节点,最后再递归使用中序遍历访问右子树
左子树->根节点->右子树 def inorder(self, root):
"""递归实现中序遍历"""
if root == None:
return
self.inorder(root.lchild)
print root.elem
self.inorder(root.rchild)
后序遍历 在后序遍历中,我们先递归使用后序遍历访问左子树和右子树,最后访问根节点
左子树->右子树->根节点 def postorder(self, root):
"""递归实现后续遍历"""
if root == None:
return
self.postorder(root.lchild)
self.postorder(root.rchild)
print root.elem 广度优先遍历(层次遍历)
从树的root开始,从上到下从从左到右遍历整个树的节点 def breadth_travel(self, root):
"""利用队列实现树的层次遍历"""
if root == None:
return
queue = []
queue.append(root)
while queue:
node = queue.pop(0)
print node.elem,
if node.lchild != None:
queue.append(node.lchild)
if node.rchild != None:
queue.append(node.rchild)

python实现查找算法的更多相关文章

  1. 两种方法实现Python二分查找算法

    两种方法实现Python二分查找算法   一. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 arr=[1,3,6,9,10,20,30] def findnumber( ...

  2. Python二分查找算法

    Python 二分查找算法: 什么是二分查找,二分查找的解释: 二分查找又叫折半查找,二分查找应该属于减值技术的应用,所谓减值法,就是将原问题分成若干个子问题后,利用了规模为n的原问题的解与较小规模( ...

  3. python实现查找算法:二分查找法

    二分查找算法也称折半查找,基本思想就是折半,和平时猜数字游戏一样,比如猜的数字时67,猜测范围是0-100,则会先猜测中间值50,结果小了,所以就会从50-100猜测,中间值为75,结果大了,又从50 ...

  4. python数组查找算法---bisect二分查找插入

    1 实例 这个模块只有几个函数, 一旦决定使用二分搜索时,立马要想到使用这个模块 [python] view plaincopyprint? import bisect L = [1,3,3,6,8, ...

  5. python有序查找算法:二分法

    二分法是一种快速查找的方法,时间复杂度低,逻辑简单易懂,总的来说就是不断的除以2除以2... 例如需要查找有序数组arr里面的某个关键字key的位置,那么首先确认arr的中位数或者中点center,下 ...

  6. python --- 二分查找算法

    二分查找法:在我的理解中这个查找方法为什么会叫二分呢,我认为是将要查询的一个列表分成了两份,然后在利用某个值来进行比较,在一个不断循环的过程中来找出我们要找的某一个值. 废话不多说,先上代码: def ...

  7. python——二分查找算法

    从有序列表的候选区data[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半   二分查找: 在一段数字内,找到中间值,判断要找的值和中间值大小的比较. 如果中间值大一些,则在 ...

  8. python实现折半查找算法&&归并排序算法

    今天依旧是学算法,前几天在搞bbs项目,界面也很丑,评论功能好像也有BUG.现在不搞了,得学下算法和数据结构,笔试过不了,连面试的机会都没有…… 今天学了折半查找算法,折半查找是蛮简单的,但是归并排序 ...

  9. python函数(4):递归函数及二分查找算法

    人理解循环,神理解递归!  一.递归的定义 def story(): s = """ 从前有个山,山里有座庙,庙里老和尚讲故事, 讲的什么呢? ""& ...

随机推荐

  1. 【ARTS】01_41_左耳听风-201900819~201900825

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  2. beego框架(golang)学习过滤器(实现restful请求)

    过滤器 在用beego做restful路由的时候,遇到了除了GTE.POST之外的HTTP请求,比如 PUT.PATCH.delete请求无法通过路由认证,报错误:405 METHOD NOT ALL ...

  3. RF之条件判断、初始化清除-4

    条件判断:        rf中用run keyword if 关键字做条件判断,以此来达到类似在python中if ...else...条件判断的功能. 注意:ELSE IF一定都是大写的,不然运行 ...

  4. 以Redis为例介绍YCSB的使用

    环境 首先确保安装了jdk和maven,我个人使用的是openjdk11和maven3,由于本人非常建议使用python版本的ycsb,建议安装python.ubuntu 18.04下可以使用apt安 ...

  5. 【GStreamer开发】GStreamer播放教程03——pipeline的快捷访问

    目的 <GStreamer08--pipeline的快捷访问>展示了一个应用如何用appsrc和appsink这两个特殊的element在pipeline中手动输入/提取数据.playbi ...

  6. 洛谷 题解 P1550 【[USACO08OCT]打井Watering Hole】

    本题看似很难,实际上思路非常简单--如果你想通了. 首先有一个问题:图中有几个点?大部分的人会回答\(n\)个点.错了,有\(n+1\)个. 多出来的那个点在哪?关键在于你要理解每一个决策的意义.实际 ...

  7. Jenkins+maven+gitlab自动化部署之docker发布sprint boot项目(七)

    Jenkins发布docker应用与发布java应用配置基本一致,需要配置Dockerfile及构建的步骤,步骤如下: 1.jenkins主机构建应用为jar包 2.jenkins主机把生产的jar包 ...

  8. java当中JDBC当中请给出一个SQLServer DataSource and SingleTon例子

    [学习笔记] 5.SQLServer DataSource and SingleTon: import net.sourceforge.jtds.jdbcx.*;import java.sql.*;i ...

  9. Zuul【限流】

    在项目中,大部分都会使用到hyrtrix做熔断机制,通过某个预定的阈值来对异常流量进行降级处理,除了做服务降级以外,还可以对服务进行限流,分流,排队等. 当然,zuul也能做到限流策略,最简单的方式就 ...

  10. python 之 前端开发(HTTP协议、head标签、img标签、a标签、列表标签)

    第十一章前端开发 11.1 HTTP 1.1引入了许多关键性能优化:keepalive连接,请求流水线,chunked编码传输,字节范围请求等 1.keepalive连接: 1.长连接允许HTTP设备 ...