数据结构B实验报告一、实验内容图的生成、图的遍历二、实验目的掌握图的基本存储结构掌握图的相关算法掌握图的两种遍历方法三、功能本实验要求实现以下功能:1.以邻接矩阵或者邻接表作为存储结构建立一个无向图。
2.深度优先搜索该无向图,输出遍历序列。
3.广度优先搜索该无向图,输出遍历序列。
四、主要代码#include<iostream>#include<fstream>using namespace std;enum Status{UNVISITED,VISITED,SUCCESS,OVER_FLOW, RANGE_ERROR, NOT_PRESENT, ENTRY_FOUND, UNDER_FLOW};const int DEFAULT_SIZE = 30;const int DEFAULT_INFAULTY =99999;const int MaxSize = 50;template<class ElemType>struct Node{ElemType data;Node<ElemType>*next;Node();//普通构造函数Node(ElemType e, Node<ElemType>*link = NULL);//带形参的构造函数};template<class ElemType>Node<ElemType>::Node(){next = NULL;}template<class ElemType>Node<ElemType>::Node(ElemType e, Node<ElemType>*link){data = e;next = link;}template<class ElemType>class LinkQueue{protected:Node<ElemType> *front, *rear; // 队头队尾指针public:LinkQueue();virtual ~LinkQueue();int GetLength() const;bool IsEmpty() const;void Clear();Status DelQueue(ElemType &e);Status GetHead(ElemType &e) const;Status EnQueue(const ElemType e);};template<class ElemType>LinkQueue<ElemType>::LinkQueue(){rear = front = new Node<ElemType>;}template<class ElemType>LinkQueue<ElemType>::~LinkQueue(){Clear();delete front;}template<class ElemType>int LinkQueue<ElemType>::GetLength() const{int count = 0;Node<ElemType> *p;for (p = front->next; p != NULL; p = p->next)count++;return count;}template<class ElemType>bool LinkQueue<ElemType>::IsEmpty() const{return rear == front;}template<class ElemType>void LinkQueue<ElemType>::Clear(){Node<ElemType> *p = front->next;while (p != NULL){front->next = p->next;delete p;p = front->next;}rear = front;}template<class ElemType>Status LinkQueue<ElemType>::EnQueue(const ElemType e) {Node<ElemType> *p;p = new Node<ElemType>(e);if (p){rear->next = p;rear = rear->next;return SUCCESS;}else return OVER_FLOW;}template<class ElemType>Status LinkQueue<ElemType>::GetHead(ElemType &e) const{if (!IsEmpty()){e = front->next->data;return SUCCESS;}else return UNDER_FLOW;}template<class ElemType>Status LinkQueue<ElemType>::DelQueue(ElemType &e){if (!IsEmpty()){Node<ElemType> *p = front->next;e = p->data;front->next = p->next;if (rear == p)rear = front;//队列中只有一个元素delete p;return SUCCESS;}else return UNDER_FLOW;}//定义有向网邻接表中弧结点的类模板template<class WeightType>struct AdjListNetworkArc{int adjVex;//弧头顶点序号WeightType weight;//边的权值AdjListNetworkArc<WeightType>*nextarc;//下一条边结点的指针AdjListNetworkArc();AdjListNetworkArc(int v, WeightType w, AdjListNetworkArc<WeightType>*next = NULL); };template<class WeightType>AdjListNetworkArc<WeightType>::AdjListNetworkArc(){adjVex = -1;}template<class WeightType>AdjListNetworkArc<WeightType>::AdjListNetworkArc(int v, WeightType w, AdjListNetworkArc<WeightType>*next){adjVex = v;weight = w;nextarc = next;}//定义有向网邻接表中顶点结点的类模板template <class ElemType, class WeightType>struct AdjListNetworkVex{ElemType data;//顶点信息AdjListNetworkArc<WeightType> *firstarc;//链表头指针AdjListNetworkVex();AdjListNetworkVex(ElemType val,AdjListNetworkArc<WeightType> *adj = NULL);};template <class ElemType, class WeightType>AdjListNetworkVex<ElemType, WeightType>::AdjListNetworkVex(){firstarc = NULL;}template <class ElemType, class WeightType>AdjListNetworkVex<ElemType, WeightType>::AdjListNetworkVex(ElemType val,AdjListNetworkArc<WeightType> *adj){data = val;firstarc = adj;}//有向图邻接表类模板的定义template<class ElemType, class WeightType>class AdjListDirNetwork{protected:int vexNum;//顶点结点的个数int vexMaxNum;//允许的顶点最大数目int arcNum;//弧数AdjListNetworkVex<ElemType, WeightType>*vexTable;//顶点表mutable Status*tag;//标志数组WeightType infinity;//无穷大值public:AdjListDirNetwork(ElemType es[], int vertexNum, int vertexMaxNum = DEFAULT_SIZE, WeightType infinit = (WeightType)DEFAULT_INFAULTY);AdjListDirNetwork(int vertexMaxNum = DEFAULT_SIZE, WeightType infinit = (WeightType)DEFAULT_INFAULTY);~AdjListDirNetwork() {}int GetVexNum()const;//求有向网的顶点个数int GetArcNum()const;//求有向网的弧数个数int GetOrder(ElemType&d)const;//求顶点的序号WeightType GetInfinity()const;//取无穷大的值WeightType GetWeight(int v1, int v2)const;//取从顶点为v1到v2的弧的权值Status GetElem(int v, ElemType&e)const;//求顶点的元素值Status GetTag(int v)const;//求顶点v的标志void SetTag(int v, Status tag)const;//修改顶点v的标志void InsertVex(const ElemType&d);//插入元素值为d的顶点void InsertArc(int v1, int v2, WeightType w);//插入从v1到v2、权为w的弧int FirstAdjVex(int v)const;//求顶点v的第一个邻接点序号int NextAdjVex(int v1, int v2)const;//求顶点v1的相对于v2的下一个邻接点};template<class ElemType, class WeightType>AdjListDirNetwork<ElemType, WeightType>::AdjListDirNetwork(int vertexMaxNum, WeightType infinit){if (vertexMaxNum < 0)cerr<<"允许的顶点最大数目不能为负!";vexNum = 0;vexMaxNum = vertexMaxNum;arcNum = 0;infinity = infinit;tag = new Status[vexMaxNum];vexTable = new AdjListNetworkVex<ElemType, WeightType>[vexMaxNum];}template<class ElemType, class WeightType>AdjListDirNetwork<ElemType, WeightType>::AdjListDirNetwork(ElemType es[], int vertexNum, int vertexMaxNum, WeightType infinit){if (vertexNum < 0)cerr << "允许的顶点最大数目不能为负!";if (vertexMaxNum < vexNum)cerr << "顶点数目不能大于允许的顶点最大数目!";vexMaxNum = vertexMaxNum;vexNum = vertexNum;arcNum = 0;infinity = infinit;tag = new Status[vexMaxNum];vexTable = new AdjListNetworkVex<ElemType, WeightType>[vexMaxNum];for (int v = 0; v < vexNum; v++){tag[v] = UNVISITED;vexTable[v].data = es[v];vexTable[v].firstarc = NULL;}}template<class ElemType,class WeightType>int AdjListDirNetwork<ElemType, WeightType>::GetVexNum()const{return vexNum;}template<class ElemType, class WeightType>int AdjListDirNetwork<ElemType, WeightType>::GetArcNum()const{return arcNum;}template<class ElemType, class WeightType>int AdjListDirNetwork<ElemType, WeightType>::GetOrder(ElemType&d)const{for (int i = 0; i < vexNum; i++)if (vexTable[i].data == d)return i;}、template<class ElemType,class WeightType>void AdjListDirNetwork<ElemType, WeightType>::InsertArc(int v1, int v2, WeightType w){if (v1 < 0 || v1 >= vexNum)cerr<<"v1不合法!";if (v2 < 0 || v2 >= vexNum)cerr<<"v2不合法!";if (v1 == v2)cerr<<"v1不能等于v2!";if (w == infinity)cerr<<"w不能为无穷大!";AdjListNetworkArc<WeightType>*p;p = vexTable[v1].firstarc;vexTable[v1].firstarc =new AdjListNetworkArc<WeightType>(v2, w, p);arcNum++;}//******************************创建图************************************************// template<class ElemType, class WeightType>bool LoadData(AdjListDirNetwork<ElemType, WeightType> &graph){//读取文件信息并赋值变量ifstream read("d:\\GraphData.txt");if (!read){cout << "File open error!\n";return 0;}int vexNum, arcNum;read >> vexNum >> arcNum;char*es;es = new char[vexNum];for (int i = 0; i < vexNum; i++)read >> es[i];int **arcTable;arcTable = new int*[arcNum];for (int i = 0; i <arcNum; i++)arcTable[i] = new int[3];for (int i = 0; i < arcNum; i++){for (int j = 0; j < 3; j++)read >> arcTable[i][j];}//开始创建有向图for (int i = 0; i < vexNum; i++)//插入顶点信息{graph.InsertVex(es[i]);}for (int i = 0; i < arcNum; i++)//插入弧结点信息{graph.InsertArc(arcTable[i][0],arcTable[i][1],arcTable[i][2]);}read.close();return 1;//创建完成}//***************************深度优先搜索*********************************//template <class ElemType, class WeightType>void DFS(AdjListDirNetwork<ElemType, WeightType> &graph, int v, void(*Visit)(const ElemType &)) {ElemType e;graph.SetTag(v, VISITED); //设置顶点v 已访问标记graph.GetElem(v, e); //取顶点v的数据元素Visit(e);//访问顶点vfor (int w = graph.FirstAdjVex(v); w != -1; w = graph.NextAdjVex(v, w))if (graph.GetTag(w) == UNVISITED)DFS(graph, w, Visit);//从v的邻接点w开始深度优先搜索}//对图graph进行深度优先遍历template <class ElemType, class WeightType>void DFSTraverse(AdjListDirNetwork<ElemType, WeightType> &graph, void(*Visit)(const ElemType &)){int v;for (v = 0; v<graph.GetVexNum(); v++)//设置未访问标志graph.SetTag(v, UNVISITED);//逐个判断顶点,从未访问顶点开始深度优先搜索for (v = 0; v<graph.GetVexNum(); v++)if (graph.GetTag(v) == UNVISITED)DFS(graph, v, Visit);}//**********************判断两点间是否存在路径(深度搜索)*************************************************template<class ElemType, class WeightType>bool PathDFS(AdjListDirNetwork<ElemType, WeightType> &graph, int start, int end){graph.SetTag(start, VISITED);for (int v = graph.FirstAdjVex(start); v != -1; v = graph.NextAdjVex(start, v))if (graph.GetTag(v) == UNVISITED){if (v == end)return 1;PathDFS(graph, v, end);}else return 0;}template<class ElemType, class WeightType>bool ExistPathDFS(AdjListDirNetwork<ElemType, WeightType> &graph, ElemType start, ElemType end){for (int v = 0; v < graph.GetVexNum(); v++)graph.SetTag(v, UNVISITED);int StartNum = graph.GetOrder(start);int EndNum = graph.GetOrder(end);return PathDFS(graph, StartNum, EndNum);}//*****************************广度优先搜索**********************************************////从顶点v开始广度优先搜索template <class ElemType, class WeightType>void BFS(AdjListDirNetwork<ElemType, WeightType> &graph, int v, void(*Visit)(const ElemType &)){LinkQueue<int> q;int u, w;ElemType e;graph.SetTag(v, VISITED); //设置访问标志graph.GetElem(v, e);//取顶点v的数据元素值Visit(e);//访问顶点vq.EnQueue(v);//顶点v入队while (!q.IsEmpty()){q.DelQueue(u);//队头顶点u出队//逐个判断u的邻接点,若未访问则访问之并入队for (w = graph.FirstAdjVex(u); w != -1; w = graph.NextAdjVex(u, w))if (graph.GetTag(w) == UNVISITED){graph.SetTag(w, VISITED);graph.GetElem(w, e);Visit(e);q.EnQueue(w);}}}//对图graph进行广度优先遍历template <class ElemType, class WeightType>void BFSTraverse(AdjListDirNetwork<ElemType, WeightType> &graph, void(*Visit)(const ElemType &)){int v;for (v = 0; v<graph.GetVexNum(); v++)//设置未访问标志graph.SetTag(v, UNVISITED);//逐个判断顶点,从未访问顶点开始广度优先搜索for (v = 0; v<graph.GetVexNum(); v++)if (graph.GetTag(v) == UNVISITED)BFS(graph, v, Visit);}//**********************判断两点间是否存在路径(广度搜索)*************************************************template <class ElemType, class WeightType>bool PathBFS(AdjListDirNetwork<ElemType, WeightType> &graph, int v,int end){LinkQueue<int> q;int u, w;graph.SetTag(v, VISITED); //设置访问标志q.EnQueue(v);//顶点v入队while (!q.IsEmpty()||w==end){q.DelQueue(u);//队头顶点u出队//逐个判断u的邻接点,若未访问则访问之并入队for (w = graph.FirstAdjVex(u); w != -1; w = graph.NextAdjVex(u, w))if (graph.GetTag(w) == UNVISITED){graph.SetTag(w, VISITED);q.EnQueue(w);}}if (graph.GetTag(end) == UNVISITED)return 0;else return 1;}void Display(const char &e){cout << e << " ";}void main(void){AdjListDirNetwork<char, int> graph(20, 9999);char start, end;//从文件GraphData.txt中读取有向图数据,建立图graphif (!LoadData(graph)){cout << "图建立失败!" << endl;exit(1);}cout << "图的深度优先遍历序列为:";DFSTraverse(graph, Display);cout << endl;cout << "图的广度优先遍历序列为:";BFSTraverse(graph, Display);cout << endl;//-----------------------------以下测试第1题------------------------------------------------cout << "请输入路径的起点名称(A):";cin >> start;//输入:Acout << "请输入路径的终点名称(G):";cin >> end;//输入:Gif (ExistPathDFS(graph, start, end))//------------------调用第1题函数-------------------------- cout << "按照深度优先搜索策略判断:" << start << "与" << end << "存在路径!" << endl;elsecout << "按照深度优先搜索策略判断:" << start << "与" << end << "不存在路径!" << endl;//-----------------------------以下测试第2题------------------------------------------------cout << "请输入路径的起点名称(A):";cin >> start;//输入:Acout << "请输入路径的终点名称(H):";cin >> end;//输入:Hif (ExistPathBFS(graph, start, end))//------------------调用第2题函数--------------------------cout << "按照广度优先搜索策略判断:" << start << "与" << end << "存在路径!" << endl;elsecout << "按照广度优先搜索策略判断:" << start << "与" << end << "不存在路径!" << endl;//-----------------------------以下测试第3题------------------------------------------------cout << "请输入计算最短路径的起点名称(A):";cin >> start;//输入:Aint *path = new int[graph.GetVexNum()], *dist = new int[graph.GetVexNum()];ShortestPathDij(graph, graph.GetOrder(start), path, dist);OutputShortestPathDij(graph, graph.GetOrder(start), path, dist);//调用OutputShortestPathDij函数输出结果,请自己实现delete[]path;delete[]dist;system("pause");}五、实验小结实验让我受益匪浅。