2026/4/4 2:42:11
网站建设
项目流程
响应式企业网站设计与实现,网站宜昌,中国商业网址,济南网络优化厂家5.4.3 计算最短路径
文件connecting_flights.py定义了类ConnectingFlights#xff0c;用于计算连接航班的最短路径。该类通过调用 Floyd-Warshall 算法计算所有标准的最短路径#xff0c;并将结果存储在数据库中。它提供了添加单个或多个航班信息的方法#xff0c;并能够打…5.4.3 计算最短路径文件connecting_flights.py定义了类ConnectingFlights用于计算连接航班的最短路径。该类通过调用 Floyd-Warshall 算法计算所有标准的最短路径并将结果存储在数据库中。它提供了添加单个或多个航班信息的方法并能够打印每对起始和目标机场之间的最短路径。通过与数据库的交互该类能够实现航空运输领域中连接航班最短路径的计算与管理。from shortest.Database import Database # import time class ConnectingFlights: 用于计算连接航班的类 def __init__(self, database): 构造函数。接受数据库对象 self.db database def add_one_flight(self, orig, dest, **kwargs): 向数据库添加一条航班信息。接受多个权重作为关键字参数 print(kwargs) self.db.add_flight(orig, dest, **kwargs) self.calc_all() # 计算最短路径 def add_many_flights(self, arr): 接受列表的列表格式为[orig, dest, **weight] for new_flight in arr: orig new_flight[0] dest new_flight[1] self.db.add_flight(orig, dest, **new_flight[2]) self.calc_all() # 计算最短路径 def calc_all(self): 计算所有标准的邻接表 self.db.clear_adj() print(正在计算最短路径...) # 计算每个标准的最短路径 for cri in Database.Criterion: print(正在计算 {}....format(cri.name)) # t1 time.time() self.floyd_warshal(cri) # t2 time.time() # print(用时 {}s.\n.format(t2-t1)) # 打印计算时间 def floyd_warshal(self, criterion): 使用 Floyd Warshal 算法在数据库中生成最短路径数据 all_airports self.db.all_airports # 初始化邻接表 self.make_adj(criterion) for thru in all_airports: # thru 中间顶点 for orig in all_airports: if orig thru: continue # 如果中间顶点与起点相同则跳过中间顶点与起点相同的情况 for dest in all_airports: if dest thru or dest orig: # 如果目标或中间顶点与起点相同则跳过目标点等于中间顶点或起点的情况 continue # 起点到中间顶点中间顶点到目标 orig_to_thru self.db.get_adj(criterion, orig, thru) thru_to_dest self.db.get_adj(criterion, thru, dest) if orig_to_thru is None or thru_to_dest is None: # 如果无法通过中间顶点访问不做任何操作 continue # 计算通过中间顶点 thru 的新权重 new_weight float(orig_to_thru[weight]) float(thru_to_dest[weight]) last_path thru_to_dest[thru] last_flight thru_to_dest[last_flight] # 获取现有的邻接表条目 orig_adj self.db.get_adj(criterion, orig, dest) if orig_adj is None: # 如果之前没有发现路径则添加。 self.db.add_to_adj(criterion, orig, dest, last_path, new_weight, last_flight) else: # 如果新权重总和较小则使用中间顶点作为最短路径的一部分 old_weight float(orig_adj[weight]) if new_weight old_weight: self.db.update_adj(criterion, orig, dest, last_path, new_weight, last_flight) def print_floyd_warshal(self, criterion): 打印每对起点和目标机场之间的最短路径 # 获取所有机场的字符串列表 all_airports self.db.all_airports for orig in all_airports: for dest in all_airports: print(\n{} 到 {}:.format(orig, dest)) # 获取最短路径信息 result self.get_shortest_floyd_warshal(criterion, orig, dest) if len(result[path]) ! 0: for o, d, w, f in result[path]: if f is None: f weight self.get_str_from_cri(criterion, w) print({} {}-{}: {}.format(f, o, d, weight)) total self.get_str_from_cri(criterion, result[total_weight]) print(总 {}: {}.format(criterion.name, total)) else: print(没有数据) def get_shortest_floyd_warshal(self, criterion, orig, dest): 接受标准、起点和目标并返回最短路径信息 output {} shortest [] start orig end dest total 0.0 while start ! end: # 回溯以找到最短路径 # 获取起点到终点的最短路径 adj self.db.get_adj(criterion, start, end) if adj is None: # 如果没有找到数据则终止 break mid adj[thru] # 获取最短路径中终点之前的最后一个顶点 weight float(self.db.get_weight(criterion, mid, end)) airline_id adj[last_flight] shortest.append((mid, end, weight, airline_id)) total weight end mid # 回溯使用中间点作为终点 output[path] shortest[::-1] # 反转列表 output[total_weight] total return output staticmethod def get_str_from_cri(criterion, target): 返回关联单位的格式化字符串 if criterion Database.Criterion.price: return ${}.format(%.2f % target) elif criterion Database.Criterion.duration: return {} 小时 {} 分钟.format(int(target // 60), int(target % 60)) elif criterion Database.Criterion.distance: return {} 英里.format(target) def make_adj(self, criterion): 使用航班初始化邻接表 weight_name criterion.name for flight in self.db.all_flights: orig flight[orig] dest flight[dest] try: last_flight_info (flight[airline], flight[no]) except KeyError: # 如果没有信息 last_flight_info None try: weight float(flight[weight_name]) find_existing self.db.get_adj(criterion, orig, dest) if find_existing is None: # 如果不存在该起点目标对的邻接表则添加 self.db.add_to_adj(criterion, orig, dest, orig, weight, last_flight_info) continue if weight float(find_existing[weight]): # 如果存在邻接表但新权重较小则更新邻接表 self.db.update_adj(criterion, orig, dest, orig, weight, last_flight_info) except KeyError: pass # 如果指定的权重属性不存在则忽略对上述代码的具体说明如下所示。__init__(self, database)初始化方法接受一个数据库对象作为参数并将其存储在类的属性中。add_one_flight(self, orig, dest, **kwargs)添加单个航班信息到数据库中的方法。接受起始机场、目的地机场和多个权重作为关键字参数并将航班信息添加到数据库中并计算最短路径。add_many_flights(self, arr)添加多个航班信息到数据库中的方法。接受一个包含多个航班信息的列表并将其添加到数据库中并计算最短路径。calc_all(self)计算所有标准的最短路径的方法。清除现有的邻接表数据然后使用 Floyd-Warshall 算法计算所有标准的最短路径并将结果存储在数据库中。floyd_warshal(self, criterion)使用 Floyd-Warshall 算法计算指定标准的最短路径的方法。根据指定的标准计算所有顶点对之间的最短路径并更新数据库中的邻接表。print_floyd_warshal(self, criterion)打印指定标准的所有起始和目标机场之间的最短路径的方法。对于每对起始和目标机场打印其最短路径以及总权重。get_shortest_floyd_warshal(self, criterion, orig, dest)获取指定标准下起始和目标机场之间的最短路径的方法。根据指定的标准、起始机场和目标机场返回最短路径的相关信息。get_str_from_cri(criterion, target)根据指定的标准和目标值返回格式化的字符串的静态方法。根据不同的标准返回对应的格式化字符串。make_adj(self, criterion)使用航班信息初始化指定标准的邻接表的方法。根据指定的标准遍历数据库中的航班信息初始化邻接表并更新数据库中的邻接表。5.4.4 Flask Web前端1文件server.py是一个基于Flask的Web应用程序的入口文件实现了一个基于Flask的Web应用程序。用户可以通过网页界面查询航班的最短路径信息并将结果展示在网页上。from flask import Flask, render_template from shortest.webapp.forms import find_form from shortest.Database import Database from shortest.connecting_flights import ConnectingFlights import os def setup_app(): # 初始化Flask应用 app Flask(__name__) # 生成随机密钥 SECRET_KEY os.urandom(32) # 设置应用的密钥 app.config[SECRET_KEY] SECRET_KEY # 初始化数据库对象 db Database(localhost, 27017, connecting_flight) # 初始化连接航班对象 cf ConnectingFlights(db) app.route(/, methods[GET, POST]) def index(): # 创建表单实例 form find_form() dbresult [] result [] total if form.orig.data ! None and form.dest.data ! None and form.cri.data ! None: print(form.orig.data, form.dest.data, form.cri.data) # 获取选择的路径优先标准 cri Database.Criterion[form.cri.data] # 获取起点和终点 search_orig form.orig.data.split()[0].upper() search_dest form.dest.data.split()[0].upper() # 查询最短路径的航班信息 dbresult cf.get_shortest_floyd_warshal(cri, search_orig, search_dest) # 获取最短路径上的航班 for flight in dbresult[path]: orig flight[0] dest flight[1] weight cf.get_str_from_cri(cri, flight[2]) airline, no flight[3] result.append({orig: orig, dest: dest, weight: weight, airline: airline, no: no}) # 获取总权重 total cf.get_str_from_cri(cri, dbresult[total_weight]) print(result) # 渲染模板 return render_template(index.html, formform, resultresult, totaltotal) return app if __name__ __main__: # 运行Flask应用 setup_app.run()上述代码的实现流程如下所示。首先导入了必要的模块和类包括Flask、render_template函数、表单类find_form、Database类和ConnectingFlights类。然后定义了一个名为setup_app的函数该函数用于配置和初始化Flask应用并设置了应用的密钥。接下来它创建了Database和ConnectingFlights的实例并将它们传递给Flask应用。然后定义了路由/它接受GET和POST请求。在这个路由中首先创建一个表单实例然后根据用户的输入查询数据库获取最短路径的航班信息并将结果渲染到模板index.html中。最后它使用run()方法运行Flask应用。2文件forms.py定义了一个名为find_form的Flask表单类用于在Web应用中接收用户输入的起点、目的地和路径优先标准。在这个表单中包含了三个字段起点orig、目的地dest和路径优先标准cri以及一个提交按钮submit。其中起点和目的地字段是字符串字段要求用户输入并且不能为空且长度为3个字符以上路径优先标准字段是下拉选择字段提供了从数据库中获取的路径优先标准选项。from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, SelectField from wtforms.validators import DataRequired, Length from shortest.Database import Database class find_form(FlaskForm): orig StringField(uOrigin, validators[DataRequired(), Length(3)]) dest StringField(uDestination, validators[DataRequired(), Length(3)]) options [] for option in Database.Criterion: name option.name options.append((name, name.capitalize() )) cri SelectField(uBy,validators[DataRequired()], choicesoptions) submit SubmitField(Search)3文件index.html是一个HTML模板文件用于渲染Web应用的主页。!doctype html html langen head !-- Required meta tags -- meta charsetutf-8 meta nameviewport contentwidthdevice-width, initial-scale1, shrink-to-fitno !-- Bootstrap CSS -- link relstylesheet href{{ url_for(static, filenamecss/bootstrap.min.css) }} link relstylesheet href{{ url_for(static, filenamecss/index.css) }} body div classjumbotron jumbotron-fluid stylebackground-image: url({{ url_for(static, filenameconn.jpg) }}); background-size: cover; div classcontainer div classback stylebackground-image: url({{ url_for(static, filenameback.png) }}) h1 classdisplay-4Connecting Flights/h1 p classleadShortest path through Floyd-Warshall algorithm/p /div /div /div div classrow div classcontainer form methodPOST action div classform-row {{ form.hidden_tag() }} div classcol {{ form.orig.label(classform-control-lable) }} {{ form.orig(classform-control) }} /div div classcol {{ form.dest.label(classform-control-lable)}} {{ form.dest(classform-control) }} /div div classcol {{ form.cri.label(classform-control-lable)}} {{ form.cri(classform-control) }} /select /div /div br div classform-row styletop-margin: 1rm div classcol {{ form.submit(classbtn btn-outline-info) }} /div /div /form /div /div br div classrow div classcontainer ul classlist-group {%if total ! %} li classlist-group-item {%if result|length ! 0%} h3Lowest {{total}}/h3 {%else%} pNo data for this query/p {%endif%} /li {%endif%} {%for path in result%} li classlist-group-item div classcontainer h2 stylecolor:darkblue{{path[orig]}}-{{path[dest]}}/h2 h4 stylecolor:grey{{path[airline]}} {{path[no]}} /h4 p{{path[weight]}}/p /div /li {%endfor%} /ul /div /div /body /html在页面中包含了一个带有背景图的jumbotron展示了Connecting Flights的标题和一个简短的描述。页面下方是一个表单用于用户输入起点、目的地和路径优先标准并有一个提交按钮。在表单下方会展示用户查询结果包括最短路径的航班信息。如果有结果会显示最短路径的航班信息包括起点、目的地、航空公司、航班号和权重信息例如总飞行距离或耗时。如图5-5所示。图5-5 主页查询效果