本科课程【数据结构与算法】实验6 - 创建哈希表、最短路径(Dijkstra算法)

x33g5p2x  于2022-03-25 转载在 其他  
字(6.6k)|赞(0)|评价(0)|浏览(495)

大家好,我是【1+1=王】, 热爱java的计算机(人工智能)渣硕研究生在读。
如果你也对java、人工智能等技术感兴趣,欢迎关注,抱团交流进大厂!!!
Good better best, never let it rest, until good is better, and better best.

近期会把自己本科阶段的一些课程设计、实验报告等分享出来,供大家参考,希望对大家有帮助。

博客更新至专栏【课程设计实验报告】:https://blog.csdn.net/weixin_43598687/category_11640051.html

一、 实验目的

  1. 实现哈希表的创建
  2. 利用线性探测在散列处理冲突
  3. 掌握图的邻接矩阵表示
  4. 实现图的最短路径查找操作(Di jkstra算法)

二、 实验内容

1. 实验任务

(1)创建哈希表
(2)利用Di jkstra算法寻找图的最短路径

2. 程序设计

1) 数据输入(输入哪些数据、个数、类型、来源、输入方式)
输入哈希表的关键数key(int 整型)

图的顶点数据(data)char字符型;
图的边关系(v1,v2)int 整型;
各边的权值(w)int 整型

2) 数据存储(输入数据在内存中的存储)
定义结构体Hash(key,si)
以数组HashList[i]存储各条数据

采用邻接矩阵存储图

3) 数据处理(说明处理步骤。若不是非常简单,需要绘制流程图)
(1)
①哈希表的查找
储存数据时,将数据存入通过哈希函数所得的地址里,使用同一个哈希函数通过关键字key计算出储存地址,通过该地址访问到查找的记录
②冲突解决
使用线性探测再散列法(冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表)
(2)
在所有从源点出发的弧中选取一条权值最小的弧,即为第一条最短路径;
设置一个顶点集合S,存放最短路径的终点。顶点k为当前最短路径的终点,将Vk加入集合S中,而Dist[k]为最短路径的长度;
每次从集合V-S中取出具有最短特殊路径长度的顶点u,将u加到S中,同时对数组Dist做必要的修改,若Dist[u]+G.arcs[u][k]<Dist[k]则将Dist[k]改为Dist[u]+arcs[u][k]。其中,特殊路径指从源点到u中间只经过S中顶点的路径;
重复操作2)、3)共n-1次1

4) 数据输出

三、 实验环境

  1. 操作系统:WINDOWS 10
  2. 开发工具:VC++ 2013
  3. 实验设备:PC

源代码(C++实现)

创建哈希表

  1. #include <stdio.h>
  2. #include<iostream>
  3. using namespace std;
  4. #define MaxSize 100 //定义最大哈希表长度
  5. #define NULLKEY -1 //定义空关键字值
  6. #define DELKEY -2 //定义被删关键字值
  7. typedef int KeyType; //关键字类型
  8. typedef char *InfoType; //其他数据类型
  9. typedef struct{
  10. KeyType key; //关键字域
  11. InfoType data; //其他数据域
  12. int count; //探查次数域
  13. }HashTable[MaxSize]; //哈希表类型
  14. void InsertHT(HashTable ha, int &n, KeyType k, int p);
  15. void CreateHT(HashTable ha, KeyType x[], int n, int m, int p);
  16. int SearchHT(HashTable ha, int p, KeyType k);
  17. int DeleteHT(HashTable ha, int p, int k, int &n);
  18. void DispHT(HashTable ha, int n, int m);
  19. void CompASL(HashTable ha, int m);
  20. void main()
  21. {
  22. int x[] = { 16, 74, 60, 43, 54, 90, 46, 31, 29, 88, 77 };
  23. int n = 11, m = 13, p = 13, i, k = 29;
  24. HashTable ha;
  25. CreateHT(ha, x, n, m, p);
  26. cout << endl;
  27. DispHT(ha, n, m);
  28. i = SearchHT(ha, p, k);
  29. if (i != -1)
  30. printf(" ha[%d].key=%d\n", i, k);
  31. else
  32. cout << "未找到" << k << endl;
  33. k = 77;
  34. printf(" 删除关键字%d\n", k);
  35. DeleteHT(ha, p, k, n);
  36. DispHT(ha, n, m);
  37. i = SearchHT(ha, p, k);
  38. if (i != -1)
  39. printf(" ha[%d].key=%d\n", i, k);
  40. else
  41. printf(" 未找到%d\n", k);
  42. printf(" 插入关键字%d\n", k);
  43. InsertHT(ha, n, k, p);
  44. DispHT(ha, n, m);
  45. cout << endl;
  46. system("pause");
  47. }
  48. //将关键字k插入到哈希表中
  49. void InsertHT(HashTable ha, int &n, KeyType k, int p)
  50. {
  51. int i, adr;
  52. adr = k%p;
  53. if (ha[adr].key == NULLKEY || ha[adr].key == DELKEY)
  54. {
  55. ha[adr].key = k;
  56. ha[adr].count = 1;
  57. }
  58. else //发生冲突时,采用线性探查法解决冲突
  59. {
  60. i = 1;
  61. do
  62. {
  63. adr = (adr + 1) % p;
  64. i++;
  65. } while (ha[adr].key != NULLKEY && ha[adr].key != DELKEY);
  66. ha[adr].key = k;
  67. ha[adr].count = i;
  68. }
  69. n++;
  70. }
  71. //创建哈希表
  72. void CreateHT(HashTable ha, KeyType x[], int n, int m, int p)
  73. {
  74. int i, n1 = 0;
  75. for (i = 0; i<m; i++) //哈希表置初值
  76. {
  77. ha[i].key = NULLKEY;
  78. ha[i].count = 0;
  79. }
  80. for (i = 0; i<n; i++)
  81. InsertHT(ha, n1, x[i], p);
  82. }
  83. //在哈希表中查找关键字k
  84. int SearchHT(HashTable ha, int p, KeyType k)
  85. {
  86. int i = 0, adr;
  87. adr = k%p;
  88. while (ha[adr].key != NULLKEY && ha[adr].key != k)
  89. {
  90. i++; //采用线性探查法找下一个地址
  91. adr = (adr + 1) % p;
  92. }
  93. if (ha[adr].key == k) //查找成功
  94. return adr;
  95. else //查找失败
  96. return -1;
  97. }
  98. //删除哈希表中关键字k
  99. int DeleteHT(HashTable ha, int p, int k, int &n)
  100. {
  101. int adr;
  102. adr = SearchHT(ha, p, k);
  103. if (adr != -1) //在哈希表中找到关键字
  104. {
  105. ha[adr].key = DELKEY;
  106. n--; //哈希表长度减1
  107. return 1;
  108. }
  109. else //在哈希表中未找到该关键字
  110. return 0;
  111. }
  112. //输出哈希表
  113. void DispHT(HashTable ha, int n, int m)
  114. {
  115. float avg = 0;
  116. int i;
  117. cout<<" 哈希表地址:";
  118. for (i = 0; i<m; i++)
  119. cout<<i<<" ";
  120. cout << endl;
  121. cout<<" 哈希表关键字:";
  122. for (i = 0; i<m; i++)
  123. if (ha[i].key == NULLKEY || ha[i].key == DELKEY)
  124. cout<<" ";
  125. else
  126. cout<<ha[i].key<<" ";
  127. cout<<endl;
  128. cout<<" 搜索次数:\t";
  129. for (i = 0; i<m; i++)
  130. if (ha[i].key == NULLKEY || ha[i].key == DELKEY)
  131. cout<<" ";
  132. else
  133. cout<<ha[i].count<<" ";
  134. cout << endl;
  135. for (i = 0; i<m; i++)
  136. if (ha[i].key != NULLKEY && ha[i].key != DELKEY)
  137. avg = avg + ha[i].count;
  138. avg = avg / n;
  139. cout << " 平均搜索长度ASL=" << avg << endl;
  140. }
  141. //查找成功时,平均查找长度
  142. void CompASL(HashTable ha, int m)
  143. {
  144. int i;
  145. int s = 0, n = 0;
  146. for (i = 0; i<m; i++)
  147. if (ha[i].key != DELKEY && ha[i].key != NULLKEY)
  148. {
  149. s = s + ha[i].count;
  150. n++;
  151. }
  152. printf(" 查找成功的ASL=%.3g\n", s*1.0 / n);
  153. }

最短路径

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include<iostream>
  4. #include <string.h>
  5. using namespace std;
  6. #define MAX 100 // 矩阵最大容量
  7. #define INF 65535 // 最大值65535
  8. #define LENGTH(a) (sizeof(a)/sizeof(a[0]))
  9. // 图的邻接矩阵存储
  10. typedef struct _graph
  11. {
  12. char vexs[MAX]; // 顶点集合
  13. int vexnum; // 顶点数
  14. int edgnum; // 边数
  15. int matrix[MAX][MAX]; // 邻接矩阵
  16. }Graph, *PGraph;
  17. // 边的结构体
  18. typedef struct _EdgeData
  19. {
  20. char start; // 边的起点
  21. char end; // 边的终点
  22. int weight; // 边的权重
  23. }EData;
  24. Graph* create_graph();
  25. void print_graph(Graph G);
  26. void dijkstra(Graph G, int vs, int prev[], int dist[]);
  27. int main()
  28. {
  29. int vs;
  30. int prev[MAX] = { 0 };
  31. int dist[MAX] = { 0 };
  32. Graph* pG;
  33. pG = create_graph();
  34. print_graph(*pG); // 打印图
  35. cout << "从第几个节点开始寻找最短路径:";
  36. cin >> vs;
  37. dijkstra(*pG, vs, prev, dist);
  38. system("pause");
  39. return 0;
  40. }
  41. /*
  42. * 创建图(用已提供的矩阵)
  43. */
  44. Graph* create_graph()
  45. {
  46. char vexs[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
  47. int matrix[][9] = {
  48. /*A*//*B*//*C*//*D*//*E*//*F*//*G*/
  49. /*A*/{ 0, 12, INF, INF, INF, 16, 14 },
  50. /*B*/{ 12, 0, 10, INF, INF, 7, INF },
  51. /*C*/{ INF, 10, 0, 3, 5, 6, INF },
  52. /*D*/{ INF, INF, 3, 0, 4, INF, INF },
  53. /*E*/{ INF, INF, 5, 4, 0, 2, 8 },
  54. /*F*/{ 16, 7, 6, INF, 2, 0, 9 },
  55. /*G*/{ 14, INF, INF, INF, 8, 9, 0 } };
  56. int vlen = LENGTH(vexs);
  57. int i, j;
  58. Graph* pG;
  59. pG = (Graph*)malloc(sizeof(Graph));
  60. pG->vexnum = vlen;
  61. for (i = 0; i < pG->vexnum; i++)
  62. pG->vexs[i] = vexs[i];
  63. for (i = 0; i < pG->vexnum; i++)
  64. {
  65. for (j = 0; j < pG->vexnum; j++)
  66. pG->matrix[i][j] = matrix[i][j];
  67. }
  68. for (i = 0; i < pG->vexnum; i++)
  69. {
  70. for (j = 0; j < pG->vexnum; j++)
  71. if (i != j && pG->matrix[i][j] != INF)
  72. pG->edgnum++;
  73. }
  74. pG->edgnum /= 2;
  75. return pG;
  76. }
  77. /*
  78. * 打印矩阵队列图
  79. */
  80. void print_graph(Graph G)
  81. {
  82. int i, j;
  83. cout << "Martix Graph:" << endl;;
  84. for (i = 0; i < G.vexnum; i++)
  85. {
  86. for (j = 0; j < G.vexnum; j++)
  87. printf("%10d ", G.matrix[i][j]);
  88. cout << endl;
  89. }
  90. }
  91. /*
  92. * Dijkstra最短路径。
  93. * 统计图(G)中"顶点vs"到其它各个顶点的最短路径。
  94. *
  95. * 参数说明:
  96. * G -- 图
  97. * vs -- 起始顶点(start vertex)。计算"顶点vs"到其它顶点的最短路径。
  98. * prev -- 前驱顶点数组。
  99. * dist -- 长度数组。
  100. */
  101. void dijkstra(Graph G, int vs, int prev[], int dist[])
  102. {
  103. int i, j, k;
  104. int min;
  105. int tmp;
  106. int flag[MAX]; // flag[i]=1表示"顶点vs"到"顶点i"的最短路径已成功获取。
  107. // 初始化
  108. for (i = 0; i < G.vexnum; i++)
  109. {
  110. flag[i] = 0; // 顶点i的最短路径还没获取到。
  111. prev[i] = 0; // 顶点i的前驱顶点为0。
  112. dist[i] = G.matrix[vs][i];// 顶点i的最短路径为"顶点vs"到"顶点i"的权。
  113. }
  114. // 对"顶点vs"自身进行初始化
  115. flag[vs] = 1;
  116. dist[vs] = 0;
  117. // 遍历G.vexnum-1次;每次找出一个顶点的最短路径。
  118. for (i = 1; i < G.vexnum; i++)
  119. {
  120. // 寻找当前最小的路径;
  121. min = INF;
  122. for (j = 0; j < G.vexnum; j++)
  123. {
  124. if (flag[j] == 0 && dist[j]<min)
  125. {
  126. min = dist[j];
  127. k = j;
  128. }
  129. }
  130. // 标记"顶点k"为已经获取到最短路径
  131. flag[k] = 1;
  132. // 修正当前最短路径和前驱顶点
  133. // 即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
  134. for (j = 0; j < G.vexnum; j++)
  135. {
  136. tmp = (G.matrix[k][j] == INF ? INF : (min + G.matrix[k][j])); // 防止溢出
  137. if (flag[j] == 0 && (tmp < dist[j]))
  138. {
  139. dist[j] = tmp;
  140. prev[j] = k;
  141. }
  142. }
  143. }
  144. // 打印dijkstra最短路径的结果
  145. printf("dijkstra(%c): \n", G.vexs[vs]);
  146. for (i = 0; i < G.vexnum; i++)
  147. printf(" shortest(%c, %c)=%d\n", G.vexs[vs], G.vexs[i], dist[i]);
  148. }

博客更新至专栏【课程设计实验报告】:https://blog.csdn.net/weixin_43598687/category_11640051.html

相关文章