最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的基本實(shí)現(xiàn)及迭代器實(shí)例詳解

 更新時(shí)間:2017年12月12日 11:55:39   作者:hanahimi  
這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的基本實(shí)現(xiàn)及迭代器,結(jié)合實(shí)例形式詳細(xì)分析了數(shù)據(jù)結(jié)構(gòu)與算法中圖的實(shí)現(xiàn)及迭代器相關(guān)算法原理與操作技巧,需要的朋友可以參考下

本文實(shí)例講述了Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的基本實(shí)現(xiàn)及迭代器。分享給大家供大家參考,具體如下:

這篇文章參考自《復(fù)雜性思考》一書(shū)的第二章,并給出這一章節(jié)里我的習(xí)題解答。

(這書(shū)不到120頁(yè)紙,要賣50塊??!,一開(kāi)始以為很厚的樣子,拿回來(lái)一看,尼瑪。。。。。代碼很少,給點(diǎn)提示,然后讓讀者自己思考怎么實(shí)現(xiàn))

先定義頂點(diǎn)和邊

class Vertex(object):
 def __init__(self, label=''):
  self.label = label
 def __repr__(self):
  return 'Vertex(%s)' % repr(self.label)
 # __repr__返回表達(dá)式, __str__返回可閱讀信息
 __str__=__repr__ # 使其指向同一個(gè)函數(shù)
class Edge(tuple):
 # 繼承自建tuple類型并重寫(xiě)new方法
 def __new__(cls, e1, e2):
  return tuple.__new__(cls, (e1,e2))
 def __repr__(self):
  return "Edge(%s, %s)" % (repr(self[0]), repr(self[1]))
 __str__ = __repr__

創(chuàng)建頂點(diǎn)和邊的方法如下

if __name__=="__main__":
 # 創(chuàng)建兩個(gè)頂點(diǎn)一條邊
 v = Vertex('v')
 w = Vertex('w')
 e = Edge(v,w)
#  print e
 # 將頂點(diǎn)和邊放入圖中
 g = Graph([v,w],[e])
#  print g

創(chuàng)建一個(gè)基本的圖類:

# 通過(guò)字典的字典實(shí)現(xiàn)圖的結(jié)構(gòu)
class Graph(dict):
 def __init__(self, vs=[], es=[]):
  """ 建立一個(gè)新的圖,(vs)為頂點(diǎn)vertices列表,(es)為邊緣edges列表 """
  for v in vs:
   self.add_vertex(v)
  for e in es:
   self.add_edge(e)
 def add_vertex(self,v):
  """ 添加頂點(diǎn) v: 使用字典結(jié)構(gòu)"""
  self[v] = {}
 def add_edge(self, e):
  """ 添加邊緣 e: e 為一個(gè)元組(v,w) 
   在兩個(gè)頂點(diǎn) w 和 v 之間添加成員e ,如果兩個(gè)頂點(diǎn)之間已有邊緣,則替換之 """
  v, w = e
  # 由于一條邊會(huì)產(chǎn)生兩個(gè)項(xiàng)目,因此該實(shí)現(xiàn)代表了一個(gè)無(wú)向圖
  self[v][w] = e
  self[w][v] = e

練習(xí)2-2解答:圖的一些基本操作

def get_edge(self,v1, v2):
  """ 接收兩個(gè)頂點(diǎn),若這兩個(gè)頂點(diǎn)之間右邊則返回這條邊,否則返回None """
  try:
   return self[v1][v2]
  except:
   return None
 def remove_edge(self,e):
  """ 接受一條邊,并且刪除圖中該邊的所有引用 """
  v, w = e
  self[v].pop(w)
  self[w].pop(v)
 def vertices(self):
  """ 返回圖中所有頂點(diǎn)的列表 """
  return self.keys()
 def edges(self):
  """ 返回圖中邊的列表 """
  es = set()    # 為了避免返回重復(fù)的邊,設(shè)為集合
  for v1 in self.vertices():
   for v2 in self.vertices():
    es.add(self.get_edge(v2, v1))
  es.discard(None)  # 若集合中存在None元素,則刪除 
  return list(es)
  """ 利用圖的字典結(jié)構(gòu)獲得所有邊
  es = []
  for v in self.vertices():
   es.extend(self[v].values())
  es = list(set(es))
  return es
  """
 def out_vertices(self,v):
  """ 接受一個(gè)Vertex并返回鄰近頂點(diǎn)(通過(guò)一條邊連接到給定節(jié)點(diǎn)的節(jié)點(diǎn))的列表 """
  return self[v].keys()
 def out_edges(self,v):
  """ 接受一個(gè)Vertex并返回連接到給定節(jié)點(diǎn)的邊的列表 """
  return self[v].values()
 def add_all_edges(self,vs=None):
  """ 從一個(gè)無(wú)邊的圖開(kāi)始,通過(guò)在各個(gè)頂點(diǎn)間添加邊來(lái)生成一個(gè)完全圖
   輸入為目標(biāo)頂點(diǎn)的列表,如果為None,則對(duì)所有的點(diǎn)進(jìn)行全聯(lián)結(jié) """
  if vs == None:
   vs = self.vertices()
  for v1 in vs:
   for v2 in vs:
    if v1 is v2 : continue  # 假設(shè)不存在單頂點(diǎn)連通
    self.add_edge(Edge(v1,v2))

習(xí)題2-3 生成正則圖

正則圖是指圖中每個(gè)頂點(diǎn)的度相同,生成正則圖需要頂點(diǎn)數(shù)和度數(shù)滿足一定條件,具體算法見(jiàn)注釋:

def add_regular_edges(self,k):
  """ 從一個(gè)無(wú)邊的圖開(kāi)始不斷添加邊,使得每個(gè)頂點(diǎn)都有相同的度k
   一個(gè)節(jié)點(diǎn)的度指的是連接到它的邊的數(shù)量 """
  n = len(self.vertices())
  assert n > 1
  if k==1:
   vs = self.vertices()
   for i in range(n-1):
    self.add_edge(Edge(vs[i],vs[i+1]))
   return True
  if n < k+1:
   print "Cannot create regular graph"
   return False
  if n == k+1:
   self.add_all_edges()
   return True
  """
   設(shè)度數(shù)為k,圖的階數(shù)(頂點(diǎn)個(gè)數(shù))為n
   利用歸納方法生成邊的個(gè)數(shù)
   偶數(shù)度 當(dāng)k=2m,m>=1時(shí)
   遞歸過(guò)程:
   0. 假設(shè)n>k+1,因?yàn)楫?dāng)n=k+1時(shí),只要生成全連接即可,當(dāng)n<k+1,則不能生成正則圖
   1. 當(dāng)n>k+1時(shí):先從原圖中前k+1個(gè)頂點(diǎn)(v1,v2,...,v2m-1,v2m, v2m+1)生成完全圖
    此時(shí),該k+1個(gè)頂點(diǎn)的度數(shù)均為k
   2. 現(xiàn)添加一個(gè)頂點(diǎn)vx,x=2m+2該頂點(diǎn)的度為0
   3. 刪除m條不相連的邊,如(v1,v2),(v3,v4),(v5,v6),...,(v2m-1,v2m),這時(shí)頂點(diǎn)v1,v2,...v2m的度為k-1
    記錄下這m條邊的頂點(diǎn)
   4. 聯(lián)結(jié) (v1,vx),(v2,vx),...,(v2m-1,vx),(v2m,vx),使得v1,v2,...,v2m,v2m+2的度=k
   5. 對(duì)新加入的點(diǎn),重復(fù)3,4
   奇數(shù)度 當(dāng)k=2m+1,m>=1時(shí)
   遞歸過(guò)程:
   設(shè)圖G是有n個(gè)頂點(diǎn)的k正則圖,且k=2m+1,m>=1,按照下面法則生成新圖G1
   0. 假設(shè)n>k+1,因?yàn)楫?dāng)n=k+1時(shí),只要生成全連接即可,當(dāng)n<k+1,則不能生成正則圖
   1. 在圖G中任取m條頂點(diǎn)不同的邊(x1,x2),(x3,x4),(x5,x6),...,(x2m-1,x2m) 記為組es1
    再另取m條頂點(diǎn)不同的邊 (y1,y2),(y3,y4),(y5,y6),...,(y2m-1,y2m) 記為組es2
    其中xi和yj可以存在相同,但是兩組中的所有邊都不相同
    此時(shí),該k+1個(gè)頂點(diǎn)的度數(shù)均為k
   2. 在圖G中去掉m條邊(x1,x2),(x3,x4),(x5,x6),...,(x2m-1,x2m),增加新的頂點(diǎn)v1,并增加2m條新邊
    (v1,x1),(v1,x2),...,(v1,x2m-1),(v1,x2m)
   3. 在圖G中去掉m條邊(y1,y2),(y3,y4),(y5,y6),...,(y2m-1,y2m),增加新的頂點(diǎn)v2,并增加2m條新邊
    (v2,y1),(v2,y2),...,(v2,y2m-1),(v2,y2m)
   4. 增加新邊 (v1,v2)
   5. 對(duì)新的點(diǎn)v3,v4,重復(fù)1,2,3,4
   增加的頂點(diǎn)和邊保證了v1,v2和x1,x2,...,x2m,y1,y2,...,y2m的度數(shù)為2m+1其余頂點(diǎn)度數(shù)不變
  """
  if k%2==0:
   # 選取前k+1個(gè)點(diǎn),先構(gòu)造完全圖
   vs = self.vertices()
   self.add_all_edges(vs[:k+1])
   for i in range(k+1,n):   # 對(duì)之后的點(diǎn)進(jìn)行遍歷 
    vsdel = []     # 記錄刪除過(guò)邊的頂點(diǎn)
    for e in self.edges():      
     # 獲得邊的兩個(gè)頂點(diǎn)
     v1,v2 = e[0],e[1]  
     if v1 not in vsdel and v2 not in vsdel:
      vsdel.append(v1)
      vsdel.append(v2)
      # 刪除不相連的邊
      self.remove_edge(e)
     # 當(dāng)已刪除的邊數(shù)為k/2,即共k個(gè)非鄰近點(diǎn)時(shí),退出循環(huán)
     if len(vsdel)==k:
      break 
    # 將新的點(diǎn)與記錄的點(diǎn)進(jìn)行連接
    for v in vsdel:
     self.add_edge(Edge(v,vs[i]))
  else:
   if n%2==0 and n>k+1: # 由上述法則可知,n必須為偶數(shù)
    # 選取前k+1個(gè)偶數(shù)點(diǎn),先構(gòu)造完全圖
    vs = self.vertices()
    self.add_all_edges(vs[:k+1])
    for i in range(k+1,n,2): # 之后的點(diǎn)進(jìn)行兩兩遍歷
     vsdel1 = []    # 記錄第1組刪除的點(diǎn)
     edel1 = []    # 記錄第1組刪除的邊
     for e in self.edges():      
      # 獲得邊的兩個(gè)頂點(diǎn)
      v1,v2 = e[0],e[1]  
      if v1 not in vsdel1 and v2 not in vsdel1:
       vsdel1.append(v1)
       vsdel1.append(v2)
       # 刪除不相連的邊
       edel1.append(e)
       self.remove_edge(e)
      # 當(dāng)已刪除的邊數(shù)為m,即共k-1個(gè)非鄰近點(diǎn)時(shí),退出循環(huán)
      if len(vsdel1)==k-1:
       break
     vsdel2 = []    # 記錄第2組刪除的點(diǎn)
     edel2 = []    # 記錄第2組刪除的邊
     for e in self.edges():      
      # 獲得邊的兩個(gè)頂點(diǎn)
      v1,v2 = e[0],e[1]  
      # 點(diǎn)可以和第一組相同,但邊不可以
      if v1 not in vsdel2 and v2 not in vsdel2 and e not in edel1:
       vsdel2.append(v1)
       vsdel2.append(v2)
       # 刪除不相連的邊
       edel2.append(e)
       self.remove_edge(e)
      # 當(dāng)已刪除的邊數(shù)為m,即共k-1個(gè)非鄰近點(diǎn)時(shí),退出循環(huán)
      if len(vsdel2)==k-1:
       break
     # 分別連接兩組邊
     for v in vsdel1:
      self.add_edge(Edge(v,vs[i]))
     for v in vsdel2:
      self.add_edge(Edge(v,vs[i+1]))
     self.add_edge(Edge(vs[i],vs[i+1]))
   else:
    print "Cannot create regular graph"
    return False
  return True

習(xí)題2-4:判斷一個(gè)圖是否連通,可以用BFS實(shí)現(xiàn):

def is_connect(self):
  """ 判斷一個(gè)圖是否連通的
   從任意頂點(diǎn)開(kāi)始進(jìn)行一次BFS,將所有到達(dá)的節(jié)點(diǎn)都標(biāo)記上,然后檢查是否所有的節(jié)點(diǎn)都被標(biāo)記上 """
  pass
  vs = self.vertices() # 獲得所有頂點(diǎn)
  q, s = [], set()  # 搜索隊(duì)列,標(biāo)記集合
  q.append(vs[0])   # 從第1個(gè)頂點(diǎn)開(kāi)始搜索
  while q:    # 當(dāng)隊(duì)列非空
   v = q.pop(0)  # 從隊(duì)列中刪除移一個(gè)頂點(diǎn)
   s.add(v)   # 并標(biāo)記當(dāng)前頂點(diǎn)
   # 搜索當(dāng)前頂點(diǎn)的連接點(diǎn),如果這些連接點(diǎn)沒(méi)有被標(biāo)記
   # 則將其添加到隊(duì)列中
   for w in self.out_vertices(v):
    if w not in s:
     q.append(w)
  # 當(dāng)隊(duì)列為空時(shí)完成搜索,檢查標(biāo)記過(guò)的頂點(diǎn)是否等于圖的頂點(diǎn)數(shù)
  if len(s)==len(vs):
   return True
  else:
   return False

測(cè)試代碼:需要用到作者書(shū)中網(wǎng)頁(yè)提供的GraphWorld.py實(shí)現(xiàn)可視化功能

from GraphWorld import CircleLayout,GraphWorld
from Graph import Graph,Vertex,Edge
import string
def test(n,k):
 # create n Vertices
 labels = string.ascii_lowercase + string.ascii_uppercase
 vs = [Vertex(c) for c in labels[:n]]
 # create a graph and a layout
 g = Graph(vs)
 g.add_regular_edges(k)
 layout = CircleLayout(g)
 # draw the graph
 gw = GraphWorld()
 gw.show_graph(g, layout)
 gw.mainloop()
if __name__ == '__main__':
 test(n=10,k=3)

以下為生成10個(gè)結(jié)點(diǎn),度為3的正則圖:

生成隨機(jī)圖,繼承上面的Graph類:

from Graph import Graph,Vertex,Edge
from random import randint
class RandomGraph(Graph):
 """ 隨即圖 """
 def add_random_edges(self,p):
  """ 從一個(gè)·無(wú)邊圖開(kāi)始隨機(jī)生成邊
   使得任意兩個(gè)節(jié)點(diǎn)間存在邊的概率為p (0<=p<=1) """
  for v1 in self.vertices():
   for v2 in self.vertices():
    if v1 is v2: continue
    if randint(0,100) < p*100 :
     self.add_edge(Edge(v1,v2))

測(cè)試一下:

from GraphWorld import CircleLayout,GraphWorld
import string
def test(n,p):
 # create n Vertices
 labels = string.ascii_lowercase + string.ascii_uppercase
 vs = [Vertex(c) for c in labels[:n]]
 # create a graph and a layout
 g = RandomGraph(vs)
 g.add_random_edges(p)
 print "connect?:",g.is_connect()
 layout = CircleLayout(g)
 # draw the graph
 gw = GraphWorld()
 gw.show_graph(g, layout)
 gw.mainloop()
if __name__ == '__main__':
 test(p=0.2,n=5)

迭代器部分代碼:

# 迭代器
class AllTrue(object):
 def next(self):
  return True
 def __iter__(self):
  return self
# 使用AllTrue之類的迭代器可以表現(xiàn)無(wú)限序列
print zip('abc',AllTrue())
# 通過(guò)編寫(xiě)生成器函數(shù)創(chuàng)建一個(gè)迭代器
def generate_letters():
 for letter in 'abc':
  yield letter
iter = generate_letters()
import string
# 帶有無(wú)限循環(huán)的生成器會(huì)返回一個(gè)不會(huì)終止的迭代器
def alphabet_cycle():
 while True:
  for i in range(1,10):
   for c in string.lowercase:
    yield c+str(i)
iter_ac = alphabet_cycle()
print iter_ac.next()

更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python加密解密算法與技巧總結(jié)》、《Python編碼操作技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門(mén)與進(jìn)階經(jīng)典教程

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Python Django給admin添加Action的方法實(shí)例詳解

    Python Django給admin添加Action的方法實(shí)例詳解

    這篇文章主要介紹了Django給admin添加Action的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-04-04
  • 利用python繪制動(dòng)態(tài)圣誕下雪圖

    利用python繪制動(dòng)態(tài)圣誕下雪圖

    圣誕節(jié)快到了,給你最愛(ài)的人送上一顆python動(dòng)態(tài)圣誕下雪圖吧,所以今天小編給大家介紹了如何利用python繪制動(dòng)態(tài)圣誕下雪圖,文中有詳細(xì)的代碼示例,需要的朋友可以參考下
    2023-12-12
  • python django下載大的csv文件實(shí)現(xiàn)方法分析

    python django下載大的csv文件實(shí)現(xiàn)方法分析

    這篇文章主要介紹了python django下載大的csv文件實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了Django框架下載csv大文件的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2019-07-07
  • Python+ChatGPT制作一個(gè)AI實(shí)用百寶箱

    Python+ChatGPT制作一個(gè)AI實(shí)用百寶箱

    ChatGPT最近在互聯(lián)網(wǎng)掀起了一陣熱潮,其高度智能化的功能能夠給我們現(xiàn)實(shí)生活帶來(lái)諸多的便利。本文就來(lái)用Python和ChatGPT制作一個(gè)AI實(shí)用百寶箱吧
    2023-02-02
  • Python開(kāi)發(fā)文字版密室逃脫游戲的實(shí)例(含代碼)

    Python開(kāi)發(fā)文字版密室逃脫游戲的實(shí)例(含代碼)

    密室逃脫游戲是一種頗受歡迎的解謎類游戲,玩家通常需要通過(guò)觀察、推理、合作等方式解決一系列難題,以逃脫困境,在這篇博文中,我們將使用Python開(kāi)發(fā)一個(gè)文字版密室逃脫游戲,旨在通過(guò)簡(jiǎn)單的文本交互來(lái)呈現(xiàn)游戲的趣味性與挑戰(zhàn)性
    2025-04-04
  • Python使用openpyxl實(shí)現(xiàn)Excel超鏈接批量化設(shè)置

    Python使用openpyxl實(shí)現(xiàn)Excel超鏈接批量化設(shè)置

    在Excel中,超鏈接是一種非常有用的功能,本文我們將介紹如何使用Python來(lái)處理Excel中的超鏈接,以及如何將超鏈接與對(duì)應(yīng)的工作表鏈接起來(lái),需要的可以參考一下
    2023-07-07
  • Python jieba結(jié)巴分詞原理及用法解析

    Python jieba結(jié)巴分詞原理及用法解析

    這篇文章主要介紹了Python jieba結(jié)巴分詞原理及用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • pandas實(shí)現(xiàn)數(shù)據(jù)可視化的示例代碼

    pandas實(shí)現(xiàn)數(shù)據(jù)可視化的示例代碼

    本文主要介紹了pandas實(shí)現(xiàn)數(shù)據(jù)可視化的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Python繪制趨勢(shì)線的示例代碼

    Python繪制趨勢(shì)線的示例代碼

    趨勢(shì)線是用來(lái)顯示數(shù)據(jù)趨勢(shì)或者預(yù)測(cè)未來(lái)發(fā)展方向的一種圖形表示方法,這篇文章主要為大家詳細(xì)介紹了如何使用Python繪制趨勢(shì)線,需要的可以了解下
    2024-03-03
  • Python網(wǎng)絡(luò)編程之ZeroMQ知識(shí)總結(jié)

    Python網(wǎng)絡(luò)編程之ZeroMQ知識(shí)總結(jié)

    這篇文章主要介紹了Python網(wǎng)絡(luò)編程之ZeroMQ知識(shí)總結(jié),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)python的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04

最新評(píng)論

宁晋县| 怀远县| 江门市| 乌海市| 常山县| 登封市| 富源县| 漠河县| 绥滨县| 维西| 宣化县| 苗栗市| 宾川县| 罗甸县| 宝丰县| 湖口县| 大田县| 中西区| 麦盖提县| 铜川市| 山东省| 新竹县| 长汀县| 五家渠市| 墨竹工卡县| 焦作市| 外汇| 济南市| 同德县| 咸丰县| 塔城市| 蛟河市| 三门峡市| 荃湾区| 普陀区| 丰都县| 乌鲁木齐市| 长汀县| 阳西县| 黄龙县| 昭苏县|