淺談深度優先和廣度優先(scrapy-redis)


首先先談談深度優先和廣度優先的定義

深度優先搜索算法英語:Depth-First-Search,DFS)是一種用於遍歷或搜索算法。沿着樹的深度遍歷樹的節點,盡可能深的搜索樹的分支。當節點v的所在邊都己被探尋過,搜索將回溯到發現節點v的那條邊的起始節點。這一過程一直進行到已發現從源節點可達的所有節點為止。如果還存在未被發現的節點,則選擇其中一個作為源節點並重復以上過程,整個進程反復進行直到所有節點都被訪問為止。屬於盲目搜索。

 

深度優先搜索
節點搜索的順序
節點進行深度優先搜索的順序
概況
類別: 搜索算法
數據結構:
時間復雜度: {\displaystyle O(b^{m})}O(b^m)
空間復雜度: {\displaystyle O(bm)}O(bm)
最佳解:
完全性:
其他: b - 分支系數
m - 圖的最大深度

 

廣度優先搜索算法英語:Breadth-First-Search,縮寫為BFS),又譯作寬度優先搜索,或橫向優先搜索,是一種圖形搜索算法。簡單的說,BFS是從根節點開始,沿着樹的寬度遍歷樹的節點。如果所有節點均被訪問,則算法中止。廣度優先搜索的實現一般采用open-closed表。

廣度優先搜索
節點搜索的順序
節點進行廣度優先搜索的順序
概況
類別: 搜索算法
數據結構:
時間復雜度: {\displaystyle O(|V|+|E|)=O(b^{d})}O(|V|+|E|) = O(b^d)
空間復雜度: {\displaystyle O(|V|+|E|)=O(b^{d})}O(|V|+|E|) = O(b^d)
最佳解:
完全性:

 

 

通俗的講:

深度優先:一個一個節點往下找,不找兄弟節點,每一個深度一個節點,先進去的后出來

廣度優先:橫向取值,一個節點有關聯其他的節點,一同被取出來,一個深度多個節點,先進去的先出來

在settings里面的配置:

from scrapy_redis.queue import PriorityQueue,FifoQueue,LifoQueue
先進先出:廣度優先
SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.FifoQueue'
后進先出:深度優先
SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.LifoQueue'
優先級隊列:
SCHEDULER_QUEUE_CLASS='scrapy_redis.queue.PriorityQueue'
優先級隊列里面也有深度優先和廣度優先:

requets.priority=1   廣度優先
requets.priority=1   深度優先

 

實現原理:

from scrapy_redis import queue

prio=1

depth = response.meta['depth'] + 1

requets.priority-=depth*self.prio

每一次循環,depth加1
同一個深度可以找到很多url(兄弟節點)

如果是1的話,廣度優先

廣度優先:
depth 優先級
1 -1
1 -1
1 -1
2 -2

從深度為1的開始往下找,優先級也越大
重點:深度越小,優先級越小

def push(self, request):
"""Push a request"""
data = self._encode_request(request)
score = -request.priority##取反,注意

......

優先級隊列:
放進隊列里面:
反一下
1 1
1 1
1 1
2 2
......

print('這里優先級是',score)
print(request.meta.get('depth'))
# We don't use zadd method as the order of arguments change depending on
# whether the class is Redis or StrictRedis, and the option of using
# kwargs only accepts strings, not bytes.
self.server.execute_command('ZADD', self.key, score, data)
#按照分值來看


def pop(self, timeout=0):
"""
Pop a request
timeout not support in this queue class
"""
# use atomic range/remove using multi/exec
##開啟事物
pipe = self.server.pipeline()
pipe.multi()
##取第一個值出來,拿出一個刪除一個
pipe.zrange(self.key, 0, 0).zremrangebyrank(self.key, 0, 0)
results, count = pipe.execute()
if results:
return self._decode_request(results[0])

最終pop是按照這個優先級來取值的,優先級越小的越先被取出來,優先級從小多大取值
總結:就是深度越小,優先級越小,越先被取出來>>廣度優先(先進先出,橫向取值)

 

深度優先:
先進后出:一個一個節點的往下面執行

深度越大,優先級越小,越先被pop出來

深度優先類似,就不多說了

....................

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM