詞梯字梯問題算法的代碼實現(使用Python實現).md


問題描述

  待完善.
詞梯文件下載:待完善.

代碼




# 測試代碼可運行. 時間: 20200328
import sys
import os
import unittest


'''
閱讀此代碼需要把圖的構成結構給跑通. 
    參見:
使用廣度優先遍歷進行標記詞梯問題.

讀取文件:參見.需要下載單詞文件.

參見課程:

'''
                
class Vertex: # 添加頂點
    def __init__(self,num):

        self.id = num # 頂點名稱
        self.connectedTo = {} # 鄰接表

        self.color = 'white' # 顏色.(用於廣度優先)
        self.pred = None # 前驅節點(用於廣度優先)
        self.disc = 0 # 設置距離(用於廣度優先)

        self.dist = sys.maxsize # sys.naxsize 表示最大值
        self.fin = 0

    # def __lt__(self,o):
    #     return self.id < o.id
    
    def addNeighbor(self,nbr,weight=0): # 設置權重
        self.connectedTo[nbr] = weight
        
    def setColor(self,color): # 顏色(尚未發現=> 白色 / 已經發現 => 灰色 / 完成探索 => 黑色)
        self.color = color
        
    def setDistance(self,d): # 設置距離
        self.dist = d

    def setPred(self,p): # 前驅頂點
        self.pred = p

    def setDiscovery(self,dtime): # 沒有用到
        self.disc = dtime
        
    def setFinish(self,ftime):# 沒有用到
        self.fin = ftime
        
    def getFinish(self):# 沒有用到
        return self.fin
        
    def getDiscovery(self):# 沒有用到
        return self.disc
        
    def getPred(self): # 獲得上一個節點
        return self.pred
        
    def getDistance(self): # 獲取距離
        return self.dist
        
    def getColor(self):
        return self.color
    
    def getConnections(self):
        return self.connectedTo.keys()
        
    def getWeight(self,nbr):# 獲取邊的權重.(無向圖的權重為0)
        return self.connectedTo[nbr]
                
    def __str__(self): # 沒用用到.
        return str(self.id) + ":color " + self.color + ":disc " + str(self.disc) + ":fin " + str(self.fin) + ":dist " + str(self.dist) + ":pred \n\t[" + str(self.pred)+ "]\n"
    
    def getId(self): # 返回節點名稱
        return self.id


class Graph: # 添加邊
    def __init__(self):
        self.vertices = {}
        self.numVertices = 0
        
    def addVertex(self,key):
        self.numVertices = self.numVertices + 1
        newVertex = Vertex(key)
        self.vertices[key] = newVertex
        return newVertex
    
    def getVertex(self,n): # 獲得頂點
        if n in self.vertices:
            return self.vertices[n]
        else:
            return None

    def __contains__(self,n):
        return n in self.vertices
    
    def addEdge(self,f,t,cost=0):
            if f not in self.vertices:
                nv = self.addVertex(f)
            if t not in self.vertices:
                nv = self.addVertex(t)
            self.vertices[f].addNeighbor(self.vertices[t],cost)
    
    def getVertices(self):
        return list(self.vertices.keys())
        
    def __iter__(self):
        return iter(self.vertices.values())



class Queue: # 隊列: 使用隊列進行遍歷. (隊首進,隊尾出)
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def enqueue(self, item): # 隊首進
        self.items.insert(0,item)

    def dequeue(self): # 隊尾出
        return self.items.pop()

    def size(self):
        return len(self.items)




def buildGraph(wordFile): # 創建桶的函數
    d = {}
    g = Graph()    
    wfile = open(wordFile,'r')
    # create buckets of words that differ by one letter
    for line in wfile:
        word = line[:-1]
        for i in range(len(word)):
            bucket = word[:i] + '_' + word[i+1:]
            if bucket in d:
                d[bucket].append(word)
            else:
                d[bucket] = [word]
    # add vertices and edges for words in the same bucket
    for bucket in d.keys():
        for word1 in d[bucket]:
            for word2 in d[bucket]:
                if word1 != word2:
                    g.addEdge(word1,word2)
    return g
    


def bfs(g,start): # bfs算法.
    start.setColor('gray')
    start.setDistance(0) # 由於是起始點.所以起始點距離起始點的距離為0
    start.setPred(None) # 設置前驅頂點.起始頂點的前驅節點是為0
    vertQueue = Queue() # 創建一個空隊列
    vertQueue.enqueue(start) # 把起始頂點裝進空隊列里去
  
    while (vertQueue.size() > 0): # 截至條件是隊列為空
        currentVert = vertQueue.dequeue() # 取出第一個進行遍歷
        for nbr in currentVert.getConnections(): # 獲取此節點的所有鄰接點
            if (nbr.getColor() == 'white'): # 如果為白色. 就添加進隊列
                nbr.setColor('gray') # 同時設置為gray ( 白色代表尚未發現 / 灰色代表已經發現,但是尚未探索 / 黑色代表已經探索 )
                nbr.setDistance(currentVert.getDistance() + 1) # 同時設置距離 / 等於上一個元素的距離 加 1
        
                nbr.setPred(currentVert) # 同時設置此元素的前驅節點
                vertQueue.enqueue(nbr) # 將此節點插入到隊列中去

        currentVert.setColor('black') # 設置為黑色.代表已經探索完成
    
    
def traverse(y): # 回溯函數.
    x = y
    while (x.getPred()):
        print(x.getId())
        x = x.getPred()
    print(x.getId())


wordgraph = buildGraph("fourletterwords.txt") # 創建完成的桶

bfs(wordgraph, wordgraph.getVertex('FOOL')) #  把整個列表給遍歷完了.

traverse(wordgraph.getVertex('SAGE'))

#traverse(wordgraph.getVertex('COOL'))


'''
實際測試:代碼已經跑通.
深度優先比搜索和廣度優先搜索換個詞是 深度優先遍歷和廣度優先遍歷
'''

參考

待完善


免責聲明!

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



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