博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分治算法(一)二分搜索技术
阅读量:4092 次
发布时间:2019-05-25

本文共 2626 字,大约阅读时间需要 8 分钟。

分治算法的本质就是将一个大规模的问题分解为若干个小规模的相同子问题,分而治之。

1.分治算法简述
1.1分治算法也有它的适用条件,满足以下3个条件,才能使用分治法来解决:

(1)原问题可分解为若干个规模较小的相同子问题

(2)子问题相互独立
(3)子问题的解可以合并为原问题的解

1.2使用分治法解题的步骤:

(1)分解:将要解决的问题分解为若干个规模较小、相互独立、与原问题形式相同的子问题。

(2)治理:对子问题进行求解。
(3)合并:按原问题的要求,将子问题的解逐层合并构成原问题的解。

2.用二分搜索技术玩猜数字游戏

2.1问题描述
假如你女朋友想跟你玩一个游戏,说:“亲爱的,猜一下我心里想的是哪个数字?这个数字在1~10范围内。”你可能会猜1,女朋友说:“小了。”接着你猜2,女朋友说:“小了。”接着你又猜3,女朋友还是说:“小了。”这时候女朋友会很无奈地说:“天呐,你怎么可以这么笨!”这样每次加1的方法来猜,如果给定的数字是1,那么很幸运,一次就能猜中;但是如果给定的是10,用这种方法就需要猜10次。
推广开来,如果是n个数,使用这种方法最坏的情况要猜n次才能成功。如何能够用最少次数猜中给定的数字?我们的二分查找(也叫折半查找)可以很好地解决这个问题。就拿上面问题为例,因为这些数字(1到10)是有序(升序)的,使用二分查找每次和中间元素比较,如果提示说猜的数字比给定的数字小了,即给定数字比中间元素大,则在后半部分查找;如果提示说猜的数字比给定的数字大了,即给定数字比中间元素小,则在前半部分查找。这样每次查找,问题都会缩小为上次问题规模的一半,所以也被称为折半查找。
2.2算法设计
用列表num[]存储该有序序列(假定为升序),设变量low表示查找范围的下界,high表示查找范围的上界,middle表示查找范围的中间位置,x为特定的查找元素。
(1)初始化。令low=0,即指向有序列表num[]的第一个元素(列表元素下标从0开始);high=n-1,即指向有序列表num[]的最后一个元素,n表示列表长度,也就是列表元素的个数。
(2)middle=(low+high)/ 2,即指向查找范围的中间元素。(low+high)为奇数的话,除以2并不能得到整数,但是列表中元素的下标都是整数,这里实际上是向下取整,比如:3.5向下取整为3。
(3)判定 low<=high 是否成立,如果成立,转第4步,否则,说明该列表中没有指定元素,算法结束。
(4)判断 x 与 num[middle] 的关系。如果 x=num[middle],搜索成功,算法结束;如果 x>num[middle],令 low=middle+1;如果 x<num[middle],令 high=middle-1,转为第2步。

2.3算法实现

(1)非递归实现

numList = []#定义一个计数变量,统计查找次数count = 1 def BinarySearch(numList,x):    low = 0    high = len(numList) - 1    global count    while(low <= high):        #地板除向下取整        middle = (low + high) // 2        if x == numList[middle]:            #指定元素等于中间元素,查找成功,返回元素下标            return middle        elif x < numList[middle]:            #指定元素小于中间元素,到前半部分查找            high = middle - 1            count = count + 1        else:            #指定元素大于中间元素,到后半部分查找            low = middle + 1            count = count + 1    return Nonen = int(input('请输入数列中的元素个数n为:'))for i in range(n):    number = int(input('请依次输入数列中的元素:'))    numList.append(number)# 列表的sort函数,默认为升序numList.sort()print('升序排序后的列表为:',numList)x = int(input('请输入要查找的元素:'))index = BinarySearch(numList,x)print('共查找了',count,'次!')if index == None:    print('该列表中没有要查找的元素!')else:    print('要查找的元素:',x,',在列表中的位置为:',index+1)

测试:

请输入数列中的元素个数n为:7请依次输入数列中的元素:16请依次输入数列中的元素:30请依次输入数列中的元素:22请依次输入数列中的元素:31请依次输入数列中的元素:63请依次输入数列中的元素:12请依次输入数列中的元素:56升序排序后的列表为: [12, 16, 22, 30, 31, 56, 63]请输入要查找的元素:16共查找了 2 次!要查找的元素: 16 ,在列表中的位置为: 2

(2)递归实现

def recusionBS(numList,x,low,high):    if low > high:        return None    middle = (low + high) // 2    if x == numList[middle]:        return middle    elif x < numList[middle]:        return recusionBS(numList,x,low,middle-1)    else:        return recusionBS(numList,x,middle+1,high)index = recusionBS([1,2,3,4,5],2,0,4)print('要查找的元素下标是:',index)

测试:

要查找的元素下标是: 1

转载地址:http://qncii.baihongyu.com/

你可能感兴趣的文章
DirectX11 三种光照组成对比
查看>>
DirectX11 指定材质
查看>>
DirectX11 平行光
查看>>
DirectX11 点光
查看>>
DirectX11 聚光灯
查看>>
DirectX11 HLSL打包(packing)格式和“pad”变量的必要性
查看>>
DirectX11 光照演示示例Demo
查看>>
漫谈一下前端的可视化技术
查看>>
VUe+webpack构建单页router应用(一)
查看>>
Vue+webpack构建单页router应用(二)
查看>>
从头开始讲Node.js——异步与事件驱动
查看>>
Node.js-模块和包
查看>>
Node.js核心模块
查看>>
express的应用
查看>>
NodeJS开发指南——mongoDB、Session
查看>>
Express: Can’t set headers after they are sent.
查看>>
2017年,这一次我们不聊技术
查看>>
实现接口创建线程
查看>>
Java对象序列化与反序列化(1)
查看>>
HTML5的表单验证实例
查看>>