精华内容
下载资源
问答
  • ACM常用搜索算法详解

    2009-06-28 09:42:21
    ACM常用搜索算法详解ACM常用搜索算法详解ACM常用搜索算法详解ACM常用搜索算法详解
  • 常用搜索算法—盲目搜索和启发式搜索

    万次阅读 多人点赞 2019-05-25 00:51:39
    搜索算法 本文主要以一些概念对较为常见的搜索作简单介绍: 一、盲目搜索 对一个图进行搜索意味着按照某种特定的顺序依次访问其顶点。在所有搜索方式中,广度优先算法和深度优先搜索算法都十分重要,因为它们提供了...

    搜索算法

    本文主要以一些概念对较为常见的搜索作简单介绍:

    一、盲目搜索

    对一个图进行搜索意味着按照某种特定的顺序依次访问其顶点。在所有搜索方式中,广度优先算法和深度优先搜索算法都十分重要,因为它们提供了一套系统地访问图数据结构的方法。我们着重讲解广度优先搜索算法。

    1.深度优先搜索
    深度优先搜索算法(简称DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点的所在边都己被探寻过,搜索将回溯到发现节点的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。由于深度优先搜索不是接下来最短路径算法的基础,因此这里不做拓展。
    2.广度优先搜索
    广度优先搜索算法(简称BFS)又称为宽度优先搜索从起点开始,首先遍历起点周围邻近的点,然后再遍历已经遍历过的点邻近的点,逐步的向外扩散,直到找到终点。
    在执行算法的过程中,每个点需要记录达到该点的前一个点的位置 —父节点。这样做之后,一旦到达终点,便可以从终点开始,反过来顺着父节点的顺序找到起点,由此就构成了一条路径。
    以上两种算法的不同搜索策略可以通过下面网页查看动图,这是两种相邻节点之间的移动代价相等时用到的算法,图中的边不设权值。
    https://cs.stanford.edu/people/abisee/tutorial/bfsdfs.html
    3.Dijkstra算法
    Dijkstra算法是由计算机科学家Edsger W.Dijkstra在1956年提出的。
    考虑这样一种场景,在一些情况下,图形中相邻节点之间的移动代价并不相等。例如,游戏中的一幅图,既有平地也有山脉,那么游戏中的角色在平地和山脉中移动的速度通常是不相等的。在Dijkstra算法中,需要计算每一个节点距离起点的总移动代价。同时,还需要一个优先队列结构。对于所有待遍历的节点,放入优先队列中会按照代价进行排序。在算法运行的过程中,每次都从优先队列中选出代价最小的作为下一个遍历的节点。直到到达终点为止。
    对比了不考虑节点移动代价差异的广度优先搜索与考虑移动代价的Dijkstra算法,又如下动图所示:
    在这里的无法插入图片描述
    可以看出当图形为网格图,并且每个节点之间的移动代价是相等的,那么Dijkstra算法将和广度优先算法变得一样。以下网址链接可以自行设置绿色网格的位置。

    Dijkstra算法(可自行设置障碍物)

    二、启发式搜索算法

    1.贪婪最佳优先
    在Dijkstra算法中,我已经发现了其最终要的缺陷,搜索存在盲目性。在这里,我们只针对这个痛点,采用贪婪最佳优先搜索来解决。如何解决?我们只需稍微改变下观念即可,在Dijkstra算法中,优先队列采用的是,每个顶点到起始顶点的预估值来进行排序。在贪婪最佳优先搜索采用的是,每个顶点到目标顶点的预估值来进行排序。
    两者的搜索过程对比如下动图所示:
    在这里插入图片描述
    明显看到右边的算法(贪婪最佳优先搜索 )寻找速度要快于左侧,虽然它的路径不是最优和最短的,但障碍物最少的时候,他的速度却足够的快。这就是贪心算法的优势,基于目标去搜索,而不是完全搜索。
    贪婪最佳优先搜索动态图(可自行设置障碍物)

    2.A star算法
    我们找到了最短路径和搜索顶点最少数量的两种方案,Dijkstra 算法和贪婪最佳优先搜索。接下来能否汲取两者的有点选择既速度快又能得到最优解的算法?.
    A star算法正是这么做了,它吸取了Dijkstra 算法中的当前代价,为每个边长设置权值,不停的计算每个顶点到起始顶点的距离,以获得最短路线,同时也汲取贪婪最佳优先搜索算法中不断向目标前进优势,并持续计算每个顶点到目标顶点的距离,以引导搜索队列不断想目标逼近,从而搜索更少的顶点,保持寻路的最优解。A star算法在运算过程中,每次从优先队列中选取f(n)值最小(优先级最高)的节点作为下一个待遍历的节点。A star算法使用两个集合来表示待遍历的节点,与已经遍历过的节点,这通常称之为open_set和close_set。
    A star算法优先队列排序方式基于估价值,估价值由顶点到起始顶点的距离(代价)加上顶点到目标顶点的距离(启发函数)之和构成。
    A star算法、贪婪最佳优先、Dijkstra算法三者的静态效果图如下:
    在这里插入图片描述
    三者动态效果图对比(可自行设置障碍物)

    三、启发函数

    f(n)=g(n)+h(n)f(n)=g(n)+h(n)
    f(n)是节点n的综合优先级。当我们选择下一个要遍历的节点时,我们总会选取综合优先级最高(值最小)的节点。g(n) 是节点n距离起点的代价。h(n)是节点n距离终点的预计代价,这也就是A star算法的启发函数。
    上面已经提到,启发函数会影响A star算法的行为。
    在极端情况下,当启发函数h(n)始终为0,则将由g(n)决定节点的优先级,此时算法就退化成了Dijkstra算法。
    如果h(n)始终小于等于节点n到终点的代价,则A star算法保证一定能够找到最短路径。但是当h(n)的值越小,算法将遍历越多的节点,也就导致算法越慢。
    如果h(n)完全等于节点n到终点的代价,则A star算法将找到最佳路径,并且速度很快。可惜的是,并非所有场景下都能做到这一点。因为在没有达到终点之前,我们很难确切算出距离终点还有多远。
    如果h(n)的值比节点n到终点的代价要大,则A star算法不能保证找到最短路径,不过此时会很快。在另外一个极端情况下,如果h(n)相较于g(n)大很多,则此时只有h(n)产生效果,这也就变成了贪婪最佳优先搜索。
    由上面这些信息我们可以知道,通过调节启发函数我们可以控制算法的速度和精确度。因为在一些情况,我们可能未必需要最短路径,而是希望能够尽快找到一个路径即可。这也是A star算法比较灵活的地方。对于网格形式的图,有以下这些启发函数可以使用:
    如果图形中只允许朝上下左右四个方向移动,则可以使用曼哈顿距离。
    如果图形中允许朝八个方向移动,则可以使用对角距离。
    如果图形中允许朝任何方向移动,则可以使用欧几里得距离。

    总结

    以下网页是五种不同搜索算法的搜索过程对比:

    五种搜索算法(可进行添加多种障碍物)

    下面对在有权图(紫)和无权图(黄)上利用搜索算法的特点做一个总结:

    本文相关PDF文件:
    Graph Search Algorithms

    本文参考文章链接:

    http://frankorz.com/2017/12/16/greedy-best-find-search/
    https://cs.stanford.edu/people/abisee/tutorial/customize.html
    https://zhuanlan.zhihu.com/p/54510444?utm_source=com.tencent.tim&utm_medium=social&utm_oi=774664375033163776
    https://www.gameres.com/777251.html

    展开全文
  • 六种常用搜索算法

    2020-10-20 18:45:51
    搜索算法顺序搜索快速搜索二分搜索插值搜索跳跃搜索hash搜索 顺序搜索 O(n) int order_search(vector<int>& data, int target) { int n = (int)data.size(); for(int i = 0; i < n; ++i) { if...

    顺序搜索

    • O(n)
    int order_search(vector<int>& data, int target) {
    	int n = (int)data.size();
    	for(int i = 0; i < n; ++i) {
    		if(target == data[i])
    			return i;
    	}
    }
    

    快速搜索

    • 平均O(n), 最坏O(n^2), 序列不需要有序
    • 获取第k+1大的元素(下标k-1)
    int quick_search(vector<int>& data, int l, int r, int key) {
    	int i = l;
    	int j = r;
    	int temp = data[l];
    	while(i < j) {
    		while(i < j && data[j] >= temp) --j;
    		data[i] = data[j];
    		while(i < j && data[i] <= temp) ++i;
    		data[j] = data[i];
    	}
    	data[i] = temp;
    	if(i < key) quick_search(data, i+1, r, key);
    	else if (i > key) quick_search(data, l, i-1, key);
    	else return data[i];
    }
    

    二分搜索

    • 序列需要有序, 时间复杂度O(logn)
    int binary_search(vector<int>& data, int target) {
    	int l = 0;
    	int r = (int)data.size()-1;
    	while(l <= r) {
    		int mid = l + (r-l)/2;
    		if(data[mid] < target) l = mid + 1;
    		else if (data[mid] > target) r = mid - 1;
    		else return l;
    	}
    	return -1;
    }
    

    插值搜索

    • 序列需要有序, 时间复杂度O(loglogn)
    int intelpolation_search(vector<int>& data, int target) {
    	int l = 0;
    	int r = (int)data.size()-1;
    	while(l <= r) {
    		int pos = l + (target - data[l])/(data[r] - data[l]) * (r-l);
    		if(data[mid] < target) l = mid + 1;
    		else if (data[mid] > target) r = mid - 1;
    		else return l;
    	}	
    	return -1;
    }
    

    跳跃搜索

    • 在n个元素排序元素中, 以n/m的步伐搜索, 0, n/m, 2n/m… 当找到第一个大于target时, 遍历m-1次
    • 时间复杂度O(根号n), n/m + m -1 当m=sqrt(n)时取最小值
    int jump_search(vector<int>& data, int target) {
        int n = (int)data.size();
        int step = (int)sqrt(n);
        int i = step;
        while(i < n) {
            if(data[i] > target)
                break;
            i += step;
        }
        
        i = min(i, n);
        for(int j = i-1; i >= i - step; --i) {
            if(data[j] == target)
                return j;
        }
        return -1;
    }
    

    hash搜索

    • 无序没有重复元素, 时间复杂度O(1)
    int hash_search(vector<int>& v, int target) {
        map<int, int> mp;
        for(int i = 0; i < v.size(); ++i) {
            mp.insert(pair<int, int>(v[i], i));
        }
        if(mp.find(target) != mp.end())
            return mp[target];
        else
            return -1;
    }
    
    展开全文
  • 常用搜索算法c++描述

    2010-11-22 19:08:51
    8数码游戏,A star算法类的实现,黑白棋
  • 二分查找又称折半查找,它是一种效率较高的查找方法,但使用二分查找要满足以下要求: 1.必须采用顺序存储结构 2.待查找的序列为按关键字大小有序排列的序列。代码实现:public class BinarySearch { ...

    二分查找又称折半查找,它是一种效率较高的查找方法,但使用二分查找要满足以下要求:
    1.必须采用顺序存储结构
    2.待查找的序列为按关键字大小有序排列的序列。

    代码实现:

    public class BinarySearch {
        public static int binarySearch(int[] nums,int num){
            if(nums==null || nums.length<1){
                System.out.print("待查找数组为空");
                return -1;
            }
            int low = 0;
            int high = nums.length-1;
            while (low<=high){
                int middle = (low+high)/2;
                if(nums[middle]==num){
                    return middle;
                }
                else if(nums[middle]>num){
                    high=middle-1;
                }
                else {
                    low=middle+1;
                }
            }
            return -1;
        }
    
        public static void main(String[] args){
            int[] nums={1,2,3,4,5,6,7,8,9};
            int num=4;
            int index = BinarySearch.binarySearch(nums,num);
            System.out.print(index);
    
        }
    }
    展开全文
  • 主要介绍了JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法,结合实例形式详细分析了针对迷宫游戏路径搜索算法的普里姆算法相关原理、实现方法及操作注意事项,需要的朋友可以参考下
  • 主要介绍了JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法,结合完整实例形式分析了A*寻路算法的具体实现技巧,代码备有详尽的注释便于理解,需要的朋友可以参考下
  • 介绍了常用搜索算法,结合实际问题进行剖析
  • python实现搜索算法(一) 顺序搜索 顺序搜索也称为线性搜索,属于无序查找算法。 算法原理 思路: 从数据结构线性表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值 k 相比较, 若相等则表示查找成功; ...

    python实现搜索算法(一)


    顺序搜索

    顺序搜索也称为线性搜索,属于无序查找算法。

    算法原理

    思路:
    从数据结构线性表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值 k 相比较,
    若相等则表示查找成功;
    若扫描结束仍没有找到关键字等于 k 的结点,表示查找失败。

    适用性:顺序搜索适合于存储结构为顺序存储链接存储线性表

    复杂度分析

    • 最坏复杂度: 从一个线性表依次查找对应项,需要做 n 次查找,在最后一项才查找到对应项或者查找失败(仍然未查找到对应项),时间复杂度为 O(n)。

    • 最好复杂度: 从一个线性表依次查找对应项,第一项就查找到对应项,时间复杂度为 O(1)。

    • 平均复杂度: 假设每个数据元素的概率相等(1/n),1/n(1+2+3+…+n)=(n+1)/2,所以时间复杂度为 O(n)。

    算法实现

    
    """
    思路:从顺序表的头部依次遍历元素,判断是否匹配,
    若匹配则查找成功,若不匹配则遍历下一个元素。
    """
    def sequence_search(sequence,target):
        for i in range(len(sequence)):
            if target==sequence[i]:
                return i
        return None
    if __name__ == '__main__':
        sequence=[99,12,33,74,521,13,14]
        target=521
        print(sequence_search(sequence,target))
    

    二分搜索

    二分搜索也称折半搜索(Binary Search),它是一种效率较高的搜索方法。但是,二分搜索要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

    基本思想:

    • 用给定值 k 先与中间结点的关键字比较,中间结点把线性表分成两个子表,
    • 若相等则查找成功;
    • 若不相等,再根据 k 与该中间结点关键字的比较结果确定下一步查找哪个子表,
    • 这样递归进行,直到查找到或查找结束发现表中没有这样的结点。

    复杂度分析

    总共有 n 个元素。

    第 1 次折半:还剩 n/2 个元素

    第 2 次折半:还剩 n/4 个元素

    第 3 次折半:还剩 n/8 个元素

    ……

    第 k 次折半:还剩 n/2^k 个元素

    最坏的情况下,最后还剩 1 个元素,令 n/2^k = 1,得 k=logn,时间复杂度 O(logn)。

    • 最坏复杂度:上述分析可以得到时间复杂度为 O(logn)。

    • 最好复杂度:第一次折半就查找到中间元素,时间复杂度为 O(1)。

    • 平均复杂度:时间复杂度为 O(logn), 证明如下:
      在这里插入图片描述

    算法实现

    def binary_search(sorted_sequence,target):
        left=0
        right=len(sorted_sequence)-1
        """
        思路:每次查询查找范围内的"中间位置"的结点,
        若该节点不是所需,则缩小查找范围为前半部分或后半部分。
        """
        while(left<=right):
            midpoint=(left+right)//2
            current_item=sorted_sequence[midpoint]
            if current_item==target:
                return midpoint
            elif target<current_item:
                right=midpoint-1
            else:
                left=midpoint+1
        return None
    if __name__ == '__main__':
        sorted_sequence = [i for i in range(1, 999, 2)]
        print(binary_search(sorted_sequence, target=521))
    
    拓展

    三分搜索:就是在二分搜索的基础上,将区间分为三个区间做判断,因此存在 5 个条件判断。

    def ternary_search(sorted_sequence, target):
        left = 0
        right = len(sorted_sequence)-1
        while(left <= right):
            Third1 = (right-left)//3+left
            Third2 = 2*(right-left)//3+left
            if(sorted_sequence[Third1] == target):
                return Third1
            elif(sorted_sequence[Third2] == target):
                return Third2
            elif(target < sorted_sequence[Third1]):
                right = Third1-1
            elif(target > sorted_sequence[Third2]):
                left = Third2+1
            else:
                left = Third1+1
                right = Third2-1
        return None
    

    插值搜索

    锲子

    在介绍插值查找之前,首先考虑一个新问题,为什么上述算法一定要是折半,而不是折四分之一或者折更多呢?打个比方,在英文字典里面查“apple”,你下意识翻开字典是翻前面的书页还是后面的书页呢?如果再让你查“zoo”,你又怎么查?很显然,这里你绝对不会是从中间开始查起,而是有一定目的的往前或往后翻。同样的,比如要在取值范围 1 ~ 10000 之间 100 个元素从小到大均匀分布的数组中查找 5,我们自然会考虑从数组下标较小的开始查找。经过以上分析,折半查找这种查找方式,不是自适应的(也就是说是傻瓜式的)。二分查找中查找点计算如下:mid=(left+right)/2, 即 mid=left+1/2*(right-left)

    通过类比,我们可以将查找的点改进为如下: mid=left+(key-a[left])/(a[right]-a[left])*(right-left),也就是将上述的比例参数 1/2 改进为自适应的,根据关键字在整个有序表中所处的位置,让 mid 值的变化更靠近关键字 key,这样也就间接地减少了比较次数。

    算法原理

    适用性: 对于表长较大,而关键字分布又比较均匀的查找表来说,插值搜索算法的平均性能比折半搜索要好的多。反之,数组中如果分布非常不均匀,那么插值搜索未必是很合适的选择。

    基本思想: 基于二分搜索算法只是在取"中点"的时候把比例参数 1/2 修改为自适应参数,可以提高搜索效率。当然,差值搜索也属于有序搜索。

    复杂度分析

    • 最坏复杂度:时间复杂度为 O(logn),最坏的情况就是二分搜索的情况,时间复杂度和二分搜索的时间复杂度相同。

    • 最好复杂度:时间复杂度为 O(1)。

    • 平均复杂度:时间复杂度为 O(loglogn)

    算法实现

    def insert_search(sorted_sequence, target):
        left = 0
        #右侧取序列最大值-1
        right = len(sorted_sequence)-1
        while(left <= right):
            #自适应中点值=左+((目标值-最小值)*数组长度)//(最大值-最小值)
            midpoint = left + ((target-sorted_sequence[left])*(right-left))//(
                sorted_sequence[right]-sorted_sequence[left])  # 比例参数修改
            #中点值小于0或者大于等于最大长度界限,不存在,返回空
            if midpoint < 0 or midpoint >= len(sorted_sequence):
                return None
            current_item = sorted_sequence[midpoint]
            #当前值等于目标值,返回中点值
            if current_item == target:
                return midpoint
            #目标值小于当前值,中点值-1为新的右边界
            elif target < current_item:
                right = midpoint-1
            else:#否则大于当前值,左侧+1为新的左边界
                left = midpoint+1
        return None
    

    展开全文
  • python实现搜索算法(二) 跳跃搜索 跳跃搜索(Jump search),按照固定步长,从有序表的首项步进,直到匹配到符合目标元素的区间,然后在该区间使用线性搜索,找到目标元素的确切位置。 跳跃搜索的思路如下:给定...
  • 常用搜索算法

    2010-06-28 17:10:00
    //状态空间盲目搜索 //对具体问题可以加入限制和设置边界条件,对搜索状态空间剪枝 //广度优先搜索:总是先搜索一个深度上的所有结点,之后再搜索下一个深度的结点 bfs() 1 初始化列表N...
  • 常用算法-路径搜索算法(图算法)20.1 BFS与DFS 最大流最小割定理,最大流问题,最小生成树问题,Prim算法,Dijkstra算法是典型的单源最短路径算法。Floyd-Warshall算法是解决任意两点间的最短路径的一种算法,可以...
  • python实现搜索算法(一)顺序搜索顺序搜索也称为线性搜索,属于无序查找算法。算法原理思路:从数据结构线性表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值 k 相比较,若相等则表示查找成功;若扫描结束...
  • 常用STL算法示例

    2020-08-16 08:28:32
    搜索算法:Search() 搜索算法:Search_n() 搜索算法:Find_first_of()函数 搜索算法:Adjacent_find() 比较算法:Equal() 比较算法:equal_range() 比较算法:mismatch() 比较算法:Lexicographical_compare...
  • 路径搜索算法在游戏中非常常见,特别是在 RPG、SLG 中经常用到。在这些游戏中,通过鼠标指定行走目的地,人物或者NPC就会自动行走到目标地点,这就是通过路径搜索或者称为寻路算法来实现的。通俗地说,就是在...
  •  通常情况下,迷宫寻路算法可以使用深度优先或者广度优先算法,但是由于效率的原因,不会直接使用这些算法,在路径搜索算法中最常见的就是A*寻路算法。使用A*算法的魅力之处在于它不仅能找到...
  • C++常用经典算法源码

    2018-12-01 15:00:42
    C++常用经典算法源码,包括高精度计算、数据排序、递推算法、递归算法搜索与回溯算法、贪心算法、分治算法、广度优先搜索、动态规划等
  • 常用算法——广度优先搜索.htm,希望对学数据结构与算法的人能有所帮助!

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,253
精华内容 1,301
关键字:

常用搜索算法