数据结构实验—最短路径C实现附带及简单界面

前言: 最短路径算法是图论中比较重要的算法之一,我们在课本中学到的最短路径算法有两种,分别为Dijkstra 算法 和 Floyd 算法,本文中采用的是 Dijkstra算法,该部分核心代码由我的同学完成,在征得其同意的情况下我们决定将代码分享给大家,虽然可能很蹩脚其中有很多不足之处,但是希望可以给需要的同学帮助。 等过一阵子,我会更新整理Floyd版本的算法。

下面展示C语言的代码。

#include"stdio.h"
#include"malloc.h"
#include"math.h"
#include"stdlib.h"
#include <windows.h>
#define max 100000
#define n 25
char vexs[25][15] = { "深圳","广州","南宁","昆明","柳州","贵阳","株洲","南昌","福州","上海","武汉","成都","南京","兰州","西安","郑州","徐州","天津","大连","乌鲁木齐","呼和浩特","北京","沈阳","长春","哈尔滨" };char vexs1[25][15] = { "" };
char output[1000];
int length = 0;
extern "C"{
void init(int map[n][n]) {map[0][1] = 140;map[1][0] = 140; map[1][2] = 506; map[1][6] = 675; map[1][7] = 673; map[1][8] = 693;map[2][1] = 506; map[2][3] = 629; map[2][4] = 255;map[3][2] = 629; map[3][5] = 639; map[3][11] = 1100;map[4][2] = 225; map[4][5] = 607; map[4][6] = 672;map[5][3] = 639; map[5][4] = 607; map[5][6] = 902; map[5][11] = 976;map[6][1] = 675; map[6][4] = 672; map[6][5] = 902; map[6][7] = 367; map[6][11] = 409;map[7][1] = 673; map[7][6] = 367; map[7][8] = 622; map[7][9] = 825; map[7][10] = 263;map[8][1] = 693; map[8][7] = 622; map[8][9] = 609;map[9][7] = 825; map[9][8] = 609; map[9][10] = 688; map[9][15] = 829; map[9][16] = 651;map[10][6] = 409; map[10][7] = 263; map[10][9] = 688; map[10][11] = 977; map[10][14] = 650; map[10][15] = 534;map[11][3] = 1100; map[11][5] = 967; map[11][10] = 977; map[11][13] = 601; map[11][14] = 842;map[12][13] = 216;map[13][11] = 601; map[13][12] = 216; map[13][14] = 676; map[13][19] = 1892; map[13][20] = 1145;map[14][10] = 650; map[14][11] = 842; map[14][13] = 676; map[14][15] = 511; map[14][20] = 774;map[15][9] = 829; map[15][10] = 534; map[15][14] = 511; map[15][16] = 349; map[15][17] = 575; map[15][20] = 694; map[15][21] = 695;map[16][9] = 651; map[16][15] = 349; map[16][17] = 674;map[17][15] = 575; map[17][16] = 674; map[17][21] = 137; map[17][22] = 704;map[18][22] = 397;map[19][13] = 1892;map[20][13] = 1145; map[20][14] = 774; map[20][15] = 694; map[20][21] = 668;map[21][15] = 695; map[21][17] = 137; map[21][20] = 668; map[21][22] = 627;map[22][17] = 704; map[22][18] = 397; map[22][21] = 627; map[22][23] = 305;map[23][22] = 305; map[23][24] = 242;map[24][23] = 242;
}void menu() {printf("    ****************全国主要城市交通查询图****************\n");printf("    **********本交通查询系统仅供实验,请勿当真************\n");printf("\n城市代号:\n\n");printf(" 1、深圳      2、广州     3、南宁     4、昆明      5、柳州\n");printf(" 6、贵阳      7、株洲     8、南昌     9、福州     10、上海\n");printf("11、武汉     12、成都    13、南京    14、兰州     15、西安\n");printf("16、郑州     17、徐州    18、天津    19、大连     20、乌鲁木齐\n");printf("21、呼和浩特 22、北京    23、沈阳    24、长春     25、哈尔滨\n");printf("\n");
}int DIJKSTRA(int C[25][25],int a, int b) {//c为有向网路的带权邻接矩阵int D[n];             //各顶点的距离值int P[n], S[n];int i, j, k, vl, pre;int min, inf = 10000;int start = a, end = b;       //起点、终点int v; // 用于暂时存储距离//把结果写入一个名为 a.txt的文件FILE* fp;fp = fopen("a.txt", "w");if (fp == NULL) return 0;//采用Dijsktra 规划最短路径vl = start - 1;for (i = 0; i < n; i++){D[i] = C[vl][i];if (D[i] != max) P[i] = start;else P[i] = 0;}for (i = 0; i < n; i++) S[i] = 0;S[vl] = 1; D[vl] = 0;for (i = 0; i < n - 1; i++){min = inf;for (j = 0; j < n; j++)if ((!S[j]) && (D[j] < min)){min = D[j]; k = j;}S[k] = 1;for (j = 0; j < n; j++)if ((!S[j]) && (D[j] > D[k] + C[k][j])){D[j] = D[k] + C[k][j];P[j] = k + 1;}}v = D[end - 1];char add[] = { "<--" };for (int i = 0; i < 15; i++) { fputc(vexs[end - 1][i], fp); }pre = P[end - 1];while (pre != 0){for (int i = 0; i < strlen(add); i++)fputc(add[i], fp);for (int i = 0; i < 15; i++) { fputc(vexs[pre - 1][i], fp); }pre = P[pre - 1];}printf("\n");//fclose(fp);return v;
}int start(int a, int b)
{int i, j;int map[n][n];for (i = 0; i < n; i++)for (j = 0; j < n; j++)map[i][j] = max;init(map);return DIJKSTRA(map, a, b);
}//这个主函数是用来测试的
int main() {menu();int a , b ;scanf("%d",&a);scanf("%d",&b);start(a, b);return 0;
}}

然后是python部分的代码

(因为图片不好上传,所以我把显示图片的一行给注释了, 图片可以自行截图然后改名为 a.gif 放在python 源文件 同目录 就可以显示。)

import ctypes
import tkinter as tk
import tkinter.messageboxwindow = tk.Tk()  #用于创建一个图形界面
window.title('最短路径')
window.geometry('1000x600')ll = ctypes.cdll.LoadLibrary
lib = ll('./map.so')f1=tk.Frame(window)
f2=tk.Frame(window)
f3=tk.Frame(window)
f4=tk.Frame(window)
l_text0=tk.StringVar()   #用于显示的字符串,最终打印路径用
l_text1=tk.IntVar(0)      #用于显示第一个城市的编号
l_text2=tk.IntVar(0)       #用于显示第二个城市的编号
l_text7=tk.StringVar()
l_text9=tk.StringVar(0)  # 用于显示最短距离
e0_text=tk.IntVar()    #用户输入
e1_text=tk.IntVar()
t_text=tk.StringVar()
t_text7=('''***************城市编号************************1、深圳  2、广州    3、南宁   4、昆明   5、柳州6、贵阳   7、株洲    8、南昌   9、福州   10、上海11、武汉  12、成都   13、南京  14、兰州  15、西安16、郑州  17、徐州   18、天津  19、大连  20、乌鲁木齐21、呼和浩特 22、北京 23、沈阳  24、长春  25.哈尔滨 ''')#################定义按键命令区域##############
def hit0():number=e0_text.get()number=number*10+0e0_text.set(number)def hit1():number = e0_text.get()number = number * 10 + 1e0_text.set(number)def hit2():number = e0_text.get()number = number * 10 + 2e0_text.set(number)def hit3():number = e0_text.get()number = number * 10 + 3e0_text.set(number)def hit4():number = e0_text.get()number = number * 10 + 4e0_text.set(number)def hit5():number = e0_text.get()number = number * 10 + 5e0_text.set(number)def hit6():number = e0_text.get()number = number * 10 + 6e0_text.set(number)def hit7():number = e0_text.get()number = number * 10 + 7e0_text.set(number)def hit8():number = e0_text.get()number = number * 10 + 8e0_text.set(number)def hit9():number = e0_text.get()number = number * 10 + 9e0_text.set(number)#把输入框中的值传给起点城市
def hit10():tem=e0_text.get()if((tem>0)and(tem<26)):l_text1.set(tem)else:tkinter.messagebox.showerror(title='出错', message='你输入的编号不能大于25或小于1')#把输入框中的值传给终点城市
def hit11():tem = e0_text.get()if ((tem > 0) and (tem < 26)):l_text2.set(tem)else:tkinter.messagebox.showerror(title='出错', message='你输入的编号不能大于25或小于1')#退格键,把输入的值向前退一个数字
def hit12():number=e0_text.get()number =int( (number-number%10)/10)e0_text.set(number)
#开始键,开始执行程序
def hit13():start_city=l_text1.get()end_city=l_text2.get()if((start_city>0)and(start_city<26)and(end_city>0)and(end_city<26)):t.insert('insert',start_city+end_city)temp=lib.start(int(start_city), int(end_city))l_text9.set(temp)with open('a.txt', "r") as file_obj:a = file_obj.read()file_obj.close()l_text0.set(a)else:tkinter.messagebox.showwarning(title='警告', message='你的输入不太正确,请检查!')def hit14():e0_text.set(0)
###########################################   用于显示输入的数字###########################################
#控件部分
canvas = tk.Canvas(f2, bg='yellow', height=600, width=600)
image_file = tk.PhotoImage(file='a.gif')
image = canvas.create_image(300, 0, anchor='n',image=image_file)  #图片b0=tk.Button(f1,text='0',command=hit0,height=2,width=3)
b1=tk.Button(f1,text='1',command=hit1,height=2,width=3)
b2=tk.Button(f1,text='2',command=hit2,height=2,width=3)
b3=tk.Button(f1,text='3',command=hit3,height=2,width=3)
b4=tk.Button(f1,text='4',command=hit4,height=2,width=3)
b5=tk.Button(f1,text='5',command=hit5,height=2,width=3)
b6=tk.Button(f1,text='6',command=hit6,height=2,width=3)
b7=tk.Button(f1,text='7',command=hit7,height=2,width=3)
b8=tk.Button(f1,text='8',command=hit8,height=2,width=3)
b9=tk.Button(f1,text='9',command=hit9,height=2,width=3)
b10=tk.Button(f1,text='start_city',command=hit10,height=2,width=5)
b11=tk.Button(f1,text='end_city',command=hit11,height=2,width=5)
b12=tk.Button(f1,text='delete',command=hit12,height=2,width=5)
b13=tk.Button(f1,text='start',command=hit13,height=2,width=5)
b14=tk.Button(f1,text='clear',command=hit14,height=2,width=5)
############################################
e0=tk.Entry(f3,textvariable=e0_text)
e1=tk.Entry(f3,textvariable=e1_text)
########################################
t=tk.Text(f3,height=3)
#########################################l0=tk.Label(f3,textvariable=l_text0)  #最终打印结果的标签
l1=tk.Label(f3,textvariable=l_text1)  #出发城市的标签
l2=tk.Label(f3,textvariable=l_text2)   #结束城市的标签
l3=tk.Label(f3,text='起点')
l4=tk.Label(f3,text='终点')
l5=tk.Label(f3,text='路径')
l6=tk.Label(f3,text='输入')
l7=tk.Label(f4,text=t_text7,bg='blue')
l8=tk.Label(f3,text="最短距离")
l9=tk.Label(f3,textvariable=l_text9)
#########################################################################################
#放置部件
#t. grid()
f1.grid(row=2,column=1)
f2.grid(row=2,column=2)
f3.grid(row=1,column=1)
f4.grid(row=1,column=2)
l0. grid(row=1,column=2)  #打印路径
l1. grid(row=2,column=2)  #打印出发城市
l2. grid(row=3,column=2)  #打印结束城市
l3.grid(row=2,column=1)   #起点
l4.grid(row=3,column=1)   #终点
l5.grid(row=1,column=1)   #路径
l6.grid(row=4,column=1)    #输入
l7.grid()              #绘图部分标签
l8.grid(row=0,column=1)  #最短距离
l9.grid(row=0,column=2)  #打印最短距离e0. grid(row=4,column=2)
#e1. grid()b0. grid(row=4,column=1,padx=1, pady=10, ipadx=10, ipady=1)
b1. grid(row=4,column=2,padx=1, pady=10, ipadx=10, ipady=1)
b2. grid(row=4,column=3,padx=1, pady=10, ipadx=10, ipady=1)
b3. grid(row=5,column=1,padx=1, pady=10, ipadx=10, ipady=1)
b4. grid(row=5,column=2,padx=1, pady=10, ipadx=10, ipady=1)
b5. grid(row=5,column=3,padx=1, pady=10, ipadx=10, ipady=1)
b6. grid(row=6,column=1,padx=1, pady=10, ipadx=10, ipady=1)
b7. grid(row=6,column=2,padx=1, pady=10, ipadx=10, ipady=1)
b8. grid(row=6,column=3,padx=1, pady=10, ipadx=10, ipady=1)
b9. grid(row=7,column=1,padx=1, pady=10, ipadx=10, ipady=1)
b10. grid(row=7,column=2,padx=1, pady=10, ipadx=10, ipady=1)
b11. grid(row=7,column=3,padx=1, pady=10, ipadx=10, ipady=1)
b12. grid(row=8,column=1,padx=1, pady=10, ipadx=10, ipady=1)
b13. grid(row=8,column=2,padx=1, pady=10, ipadx=10, ipady=1)
b14. grid(row=8,column=3,padx=1, pady=10, ipadx=10, ipady=1)
canvas.grid(row=0)#显示窗口及其部件tkinter.messagebox.showinfo(title='使用需知(1/3)', message='欢迎使用本查询系统,本查询系统纯属娱乐,其中距离仅供参考')
tkinter.messagebox.showinfo(title='使用需要知(2/3)', message='在输入框输入相应的数字后点击strat_city 把这个数字存入 起点城市中,终点城市也是同样的操作,点击strat运行')
tkinter.messagebox.showinfo(title='使用需知(3/3)', message='如果输入错了或者想要更改 只需要点击 delete 或者 clear 即可\n 体验愉快!')
window.mainloop()

地图

这张图是另一个大佬做的,因为找不到来源所以无法给出出处,我们这次的算法中邻接矩阵就是按照这个图做的。

如何创建库 以及如何运行

然后是关于如何运行这个程序,因为这个程序由两部分组成,一个C的后端和PYTHON的前端,所以需要把C编译成为 动态库 供 python 调用。 下面给出如何把c文件编译成动态库的方法,这是在windows 上的方法,在Linux上是类似的步骤。

首先打开cmd,(window键 + R 快捷打开 然后输入cmd 敲回车即可 或者可以搜索 命令提示符),然后找到.c 文件存储的位置,比如我这里放在了 D盘的mycode

然后输入命令(我这里的源文件名字是road.cpp,然后要生成的库名字叫 map.so) 库名一定要对应pyhthon里面名字。

mycode>g++ -o map.so -shared -fPIC road.cpp

然后我们获得了一个名为map.so的动态库,把这个文件要和py文件放在同一个目录下。

结果展示

最后运行python即可。
丝毫没有任何艺术气息的布局。

测试一下,输入一个21 敲start_city ,然后点击 clear归零,再输入17 点击end_city 最后 点击start 。

完美运行!

总结:本算法采用C语言与混编的形式,然后我简单的介绍了如何调用c语言的函数,这是我第一次采用C和python 混编, 因为我还没有系统性的学习python,所以有些语法不太明晰,代码写的很乱,感谢大家查看!

数据结构实验---最短路径C实现附带及简单界面相关推荐

  1. 数据结构实验之串一:KMP简单应用

    Description 给定两个字符串string1和string2,判断string2是否为string1的子串. Input 输入包含多组数据,每组测试数据包含两行,第一行代表string1(长度 ...

  2. 大二数据结构实验(迪杰斯特拉最短路径)

    大二数据结构实验,有详细批注,代码可以直接运行,希望可以给大家提供到帮助. 实验目的 掌握图的邻接矩阵的存储定义. 掌握图的最短路径(Dijsktra)算法的实现. 实验内容 设计校园平面图,所含景点 ...

  3. 数据结构实验三 图的操作与实现

    系列文章: 数据结构实验一 线性表.堆栈和队列的操作与实现 数据结构实验二 二叉树的操作与实现 数据结构实验三 图的操作与实现 数据结构实验四 查找和排序算法实现 一.实验目的: 1.领会图的两种主要 ...

  4. SDUT-2449_数据结构实验之栈与队列十:走迷宫

    数据结构实验之栈与队列十:走迷宫 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 一个由n * m 个格子组成的迷宫,起 ...

  5. sdut 1479 数据结构实验之栈与队列九:行编辑器

    数据结构实验之栈与队列九:行编辑器 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Descript ...

  6. SDUT—2054数据结构实验之链表九:双向链表 (基本建立)

    点击打开链接 数据结构实验之链表九:双向链表 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Des ...

  7. java数据结构实验一顺序表,java数据结构实验代码之升序顺序表

    java数据结构实验代码之升序顺序表 数据结构实验报告 学院:管理学院 班级:13电子商务(1)班 姓名:廖秋君 学号:3213004779 2014年 10月 23 日 目录 一.需求分析----- ...

  8. 图的基本操作实现(数据结构实验)

    实验项目六 图结构基本操作的实现 课程名称:数据结构 实验项目名称:图结构基本操作的实现 实验目的: 1.掌握图的基本操作-遍历. 实验要求: 1.    分别用DFS和BFS的方法实现一个无向图的遍 ...

  9. SDUT 3347 数据结构实验之数组三:快速转置

    数据结构实验之数组三:快速转置 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 转置运算是一种最简单的矩阵运算,对于一个 ...

最新文章

  1. 以太坊RLP机制分析
  2. Python CRC32 文件校验
  3. 利用PySpark进行迁移学习的多类图像分类
  4. jsp中session 失效设置
  5. 【C++】 C++标准模板库(十一) 优先队列
  6. LeetCode每日一题 977. 有序数组的平方
  7. tpshop防止sql注入补丁
  8. Spring Data Redis与Jedis的选择(转)
  9. PHP 免费视频教程
  10. opencv中的腐蚀与膨胀(转)
  11. linux 审计工具auditd日志audit.log时间戳转换查看
  12. NOIP模拟测试25
  13. 特斯拉退市,是一个工程师的执拗
  14. Android:解决Failed to load D:\Android-Studio\sdk\build-tools\xx.xx.xx\lib\dx.jar
  15. 欺骗的艺术from凯文•米特尼克
  16. 五种知网文献免费下载方式
  17. word论文排版,页码和页眉
  18. 0xc000007b的解决办法(续)
  19. dw常用标签_dw常用单词
  20. 电脑蓝屏原因与手把手处理指南(关于0x00000124分析)

热门文章

  1. 关于文字音译的网页(基于百度AI)
  2. 21个经典的哲理故事
  3. 使用c++开发excel插件 (第3章动态链接库(dynamic-link library))
  4. 【ICC】icc基本使用步骤(转载)(初稿)
  5. 软件工程结对开发——返回一个整数数组中最大子数组的和(JAVA)
  6. python迭代遍历_迭代遍历思维
  7. 活体检测的几种手段分析
  8. java 返回ro,错误retrofit rxjava优雅的处理服务器返回异常、错误
  9. linux命令行颜色,技术|在 Linux 命令行中自定义文本颜色
  10. 用于自动驾驶的激光雷达里程计方法综述