今天,我们一起来实践一下数据结构-图,具体实现代码如下:
Edge.h具体内容如下:
template<typename DistType> struct Edge{ public: Edge(int dest, DistType cost) : m_ndest(dest), m_cost(cost), m_pnext(NULL){} public: int m_ndest; DistType m_cost; Edge<DistType> *m_pnext; };Graph.h具体内容如下:
#include "Vertex.h" template<typename NameType, typename DistType> class Graph{ public: Graph(int size = m_nDefaultSize); //create the Graph with the most vertex of size ~Graph(); bool GraphEmpty() const{ //Is empty? return 0 == m_nnumvertex; } bool GraphFull() const{ //Is full? return m_nMaxNum == m_nnumvertex; } int NumberOfVertex() const{ //get the number of vertex return m_nnumvertex; } int NumberOfEdge() const{ //get the number of edge return m_nnumedges; } NameType GetValue(int v); //get the value of the vth vertex DistType GetWeight(int v1, int v2); //get the weight between v1 and v2 int GetFirst(int v); //get the first neighbor vertex of v int GetNext(int v1, int v2);//get the next neighbor vertex of v1 behind v2 bool InsertVertex(const NameType vertex); //insert vertex with the name of vertex bool Removevertex(int v); //remove the vth vertex //insert the edge between v1 and v2 bool InsertEdge(int v1, int v2, DistType weight = m_Infinity); bool RemoveEdge(int v1, int v2); //delete the edge between v1 and v2 void Print(); //print the graph Edge<DistType> *GetMin(int v, int *visited); //get the min weight of the neighbor vertex of v void Prim(Graph<NameType, DistType> &graph); //get the minimize span tree void DFS(int v, int *visited); //depth first search void DFS(); void Dijkstra(int v, DistType *shotestpath); //get the min weight from v to other vertex private: Vertex<NameType, DistType> *m_pnodetable; //neighbor list int m_nnumvertex; const int m_nMaxNum; static const int m_nDefaultSize = 10; //the default maximize vertex static const DistType m_Infinity = 100000; //there is no edge int m_nnumedges; int Getvertexpos(const NameType vertex); //get the vertex's position with the name of vertex }; template<typename NameType, typename DistType> Graph<NameType, DistType>::Graph(int size) : m_nnumvertex(0), m_nMaxNum(size), m_nnumedges(0){ m_pnodetable = new Vertex<NameType, DistType>[size]; } template<typename NameType, typename DistType> Graph<NameType, DistType>::~Graph(){ Edge<DistType> *pmove; for (int i = 0; i < this->m_nnumvertex; i++){ pmove = this->m_pnodetable[i].adj; if (pmove){ this->m_pnodetable[i].adj = pmove->m_pnext; delete pmove; pmove = this->m_pnodetable[i].adj; } } delete[] m_pnodetable; } template<typename NameType, typename DistType> int Graph<NameType, DistType>::GetFirst(int v){ if (v < 0 || v >= this->m_nnumvertex){ return -1; } Edge<DistType> *ptemp = this->m_pnodetable[v].adj; return m_pnodetable[v].adj ? m_pnodetable[v].adj->m_ndest : -1; } template<typename NameType, typename DistType> int Graph<NameType, DistType>::GetNext(int v1, int v2){ if (-1 != v1){ Edge<DistType> *pmove = this->m_pnodetable[v1].adj; while (NULL != pmove->m_pnext){ if (pmove->m_ndest == v2){ return pmove->m_pnext->m_ndest; } pmove = pmove->m_pnext; } } return -1; } template<typename NameType, typename DistType> NameType Graph<NameType, DistType>::GetValue(int v){ if (v < 0 || v >= this->m_nnumvertex){ cerr << "The vertex is not exsit" << endl; exit(1); } return m_pnodetable[v].m_data; } template<typename NameType, typename DistType> int Graph<NameType, DistType>::Getvertexpos(const NameType vertex){ for (int i = 0; i < this->m_nnumvertex; i++){ if (vertex == m_pnodetable[i].m_data){ return i; } } return -1; } template<typename NameType, typename DistType> DistType Graph<NameType, DistType>::GetWeight(int v1, int v2){ if (v1 >= 0 && v1 < this->m_nnumvertex && v2 >= 0 && v2 < this->m_nnumvertex){ if (v1 == v2){ return 0; } Edge<DistType> *pmove = m_pnodetable[v1].adj; while (pmove){ if (pmove->m_ndest == v2){ return pmove->m_cost; } pmove = pmove->m_pnext; } } return m_Infinity; } template<typename NameType, typename DistType> bool Graph<NameType, DistType>::InsertEdge(int v1, int v2, DistType weight){ if (v1 >= 0 && v1 < this->m_nnumvertex && v2 >= 0 && v2 < this->m_nnumvertex){ Edge<DistType> *pmove = m_pnodetable[v1].adj; if (NULL == pmove){ //the first neighbor m_pnodetable[v1].adj = new Edge<DistType>(v2, weight); return 1; } while (pmove->m_pnext){ if (pmove->m_ndest == v2){ break; } pmove = pmove->m_pnext; } if (pmove->m_ndest == v2){ //if the edge is exist, change the weight pmove->m_cost = weight; return 1; } else{ pmove->m_pnext = new Edge<DistType>(v2, weight); return 1; } } return 0; } template<typename NameType, typename DistType> bool Graph<NameType, DistType>::InsertVertex(const NameType vertex){ int i = this->Getvertexpos(vertex); if (-1 != i){ this->m_pnodetable[i].m_data = vertex; } else{ if (!this->GraphFull()){ this->m_pnodetable[this->m_nnumvertex].m_data = vertex; this->m_nnumvertex++; } else{ cerr << "The Graph is Full" << endl; return 0; } } return 1; } template<typename NameType, typename DistType> bool Graph<NameType, DistType>::RemoveEdge(int v1, int v2){ if (v1 >= 0 && v1 < this->m_nnumvertex && v2 >= 0 && v2 < this->m_nnumvertex){ Edge<DistType> *pmove = this->m_pnodetable[v1].adj, *pdel; if (NULL == pmove){ cerr << "the edge is not exist!" << endl; return 0; } if (pmove->m_ndest == v2){ //the first neighbor this->m_pnodetable[v1].adj = pmove->m_pnext; delete pmove; return 1; } while (pmove->m_pnext){ if (pmove->m_pnext->m_ndest == v2){ pdel = pmove->m_pnext; pmove->m_pnext = pdel->m_pnext; delete pdel; return 1; } pmove = pmove->m_pnext; } } cerr << "the edge is not exist!" << endl; return 0; } template<typename NameType, typename DistType> bool Graph<NameType, DistType>::Removevertex(int v){ if (v < 0 || v >= this->m_nnumvertex){ cerr << "the vertex is not exist!" << endl; return 0; } Edge<DistType> *pmove, *pdel; for (int i = 0; i < this->m_nnumvertex; i++){ pmove = this->m_pnodetable[i].adj; if (i != v){ //delete the edge point to v if (NULL == pmove){ continue; } if (pmove->m_ndest == v){ this->m_pnodetable[i].adj = pmove->m_pnext; delete pmove; continue; } else { if (pmove->m_ndest > v){ //the vertex more than v subtract 1 pmove->m_ndest--; } } while (pmove->m_pnext){ if (pmove->m_pnext->m_ndest == v){ pdel = pmove->m_pnext; pmove->m_pnext = pdel->m_pnext; delete pdel; } else { if (pmove->m_pnext->m_ndest > v){ pmove->m_pnext->m_ndest--; pmove = pmove->m_pnext; } } } } else { //delete the edge point from v while (pmove){ this->m_pnodetable[i].adj = pmove->m_pnext; delete pmove; pmove = this->m_pnodetable[i].adj; } } } this->m_nnumvertex--; for (int i = v; i < this->m_nnumvertex; i++) //delete the vertex { this->m_pnodetable[i].adj = this->m_pnodetable[i + 1].adj; this->m_pnodetable[i].m_data = this->m_pnodetable[i + 1].m_data; } this->m_pnodetable[this->m_nnumvertex].adj = NULL; return 1; } template<typename NameType, typename DistType> void Graph<NameType, DistType>::Print(){ Edge<DistType> *pmove; for (int i = 0; i < this->m_nnumvertex; i++){ cout << this->m_pnodetable[i].m_data << "--->"; pmove = this->m_pnodetable[i].adj; while (pmove){ cout << pmove->m_cost << "--->" << this->m_pnodetable[pmove->m_ndest].m_data << "--->"; pmove = pmove->m_pnext; } cout << "NULL" << endl; } } template<typename NameType, typename DistType> void Graph<NameType, DistType>::Prim(Graph<NameType, DistType> &graph){ int *node = new int[this->m_nnumvertex]; //using for store the vertex visited int *visited = new int[this->m_nnumvertex]; int count = 0; Edge<DistType> *ptemp, *ptemp2 = new Edge<DistType>(0, this->m_Infinity), *pmin; int min; for (int i = 0; i < this->m_nnumvertex; i++){ graph.InsertVertex(this->m_pnodetable[i].m_data); node[i] = 0; visited[i] = 0; } visited[0] = 1; while (++count < this->m_nnumvertex){ pmin = ptemp2; pmin->m_cost = this->m_Infinity; //get the minimize weight between the vertex visited and the vertex which is not visited for (int i = 0; i<count; i++){ ptemp = GetMin(node[i], visited); if (NULL == ptemp){ continue; } if (pmin->m_cost > ptemp->m_cost){ pmin = ptemp; min = node[i]; } } node[count] = pmin->m_ndest; visited[node[count]] = 1; graph.InsertEdge(pmin->m_ndest, min, pmin->m_cost); graph.InsertEdge(min, pmin->m_ndest, pmin->m_cost); } graph.DFS(); delete ptemp2; delete[] node; delete[] visited; } template<typename NameType, typename DistType> void Graph<NameType, DistType>::DFS(int v, int *visited){ cout << "--->" << this->GetValue(v); visited[v] = 1; int weight = this->GetFirst(v); while (-1 != weight){ if (!visited[weight]){ cout << "--->" << this->GetWeight(v, weight); DFS(weight, visited); } weight = this->GetNext(v, weight); } } template<typename NameType, typename DistType> void Graph<NameType, DistType>::DFS(){ int *visited = new int[this->m_nnumvertex]; for (int i = 0; i < this->m_nnumvertex; i++){ visited[i] = 0; } cout << "head"; DFS(0, visited); cout << "--->end"; } template<typename NameType, typename DistType> Edge<DistType>* Graph<NameType, DistType>::GetMin(int v, int *visited){ Edge<DistType> *pmove = this->m_pnodetable[v].adj, *ptemp = new Edge<DistType>(0, this->m_Infinity), *pmin = ptemp; while (pmove){ if (!visited[pmove->m_ndest] && pmin->m_cost > pmove->m_cost){ pmin = pmove; } pmove = pmove->m_pnext; } if (pmin == ptemp){ delete ptemp; return NULL; } delete ptemp; return pmin; } template<typename NameType, typename DistType> void Graph<NameType, DistType>::Dijkstra(int v, DistType *shotestpath){ int *visited = new int[this->m_nnumvertex]; int *node = new int[this->m_nnumvertex]; for (int i = 0; i < this->m_nnumvertex; i++){ visited[i] = 0; node[i] = 0; shotestpath[i] = this->GetWeight(v, i); } visited[v] = 1; for (int i = 1; i < this->m_nnumvertex; i++){ DistType min = this->m_Infinity; int u = v; for (int j = 0; j < this->m_nnumvertex; j++){ //get the minimize weight if (!visited[j] && shotestpath[j] < min){ min = shotestpath[j]; u = j; } } visited[u] = 1; for (int w = 0; w < this->m_nnumvertex; w++){ //change the weight from v to other vertex DistType weight = this->GetWeight(u, w); if (!visited[w] && weight != this->m_Infinity && shotestpath[u] + weight < shotestpath[w]){ shotestpath[w] = shotestpath[u] + weight; } } } delete[] visited; delete[] node; }MinHeap.h具体内容如下:
template<typename Type> class MinHeap{ public: MinHeap(Type heap[], int n); //initialize heap by a array ~MinHeap(){ delete[] m_pheap; } public: bool Insert(const Type item); bool DeleteMin(Type &first); private: void Adjust(const int start, const int end); //adjust the elements from start to end private: const int m_nMaxSize; Type *m_pheap; int m_ncurrentsize; }; template<typename Type> void MinHeap<Type>::Adjust(const int start, const int end){ int i = start, j = i * 2 + 1; Type temp = m_pheap[i]; while (j <= end){ if (j<end && m_pheap[j]>m_pheap[j + 1]){ j++; } if (temp <= m_pheap[j]){ break; } else{ m_pheap[i] = m_pheap[j]; i = j; j = 2 * i + 1; } } m_pheap[i] = temp; } template<typename Type> MinHeap<Type>::MinHeap(Type heap[], int n) :m_nMaxSize(n){ m_pheap = new Type[m_nMaxSize]; for (int i = 0; i < n; i++){ m_pheap[i] = heap[i]; } m_ncurrentsize = n; int pos = (n - 2) / 2; //Find the last tree which has more than one element; while (pos >= 0){ Adjust(pos, n - 1); pos--; } } template<typename Type> bool MinHeap<Type>::DeleteMin(Type &first){ first = m_pheap[0]; m_pheap[0] = m_pheap[m_ncurrentsize - 1]; m_ncurrentsize--; Adjust(0, m_ncurrentsize - 1); return 1; } template<typename Type> bool MinHeap<Type>::Insert(const Type item){ if (m_ncurrentsize == m_nMaxSize){ cerr << "Heap Full!" << endl; return 0; } m_pheap[m_ncurrentsize] = item; int j = m_ncurrentsize, i = (j - 1) / 2; Type temp = m_pheap[j]; while (j > 0){ if (m_pheap[i] <= temp){ break; } else{ m_pheap[j] = m_pheap[i]; j = i; i = (j - 1) / 2; } } m_pheap[j] = temp; m_ncurrentsize++; return 1; }Vertex.h具体内容如下:
#include "Edge.h" template<typename NameType, typename DistType> struct Vertex{ public: Vertex() : adj(NULL){} NameType m_data; Edge<DistType> *adj; ~Vertex(); }; template<typename NameType, typename DistType> Vertex<NameType, DistType>::~Vertex(){ Edge<DistType> *pmove = adj; while (pmove){ adj = pmove->m_pnext; delete pmove; pmove = adj; } }main.cpp具体内容如下:
#include <iostream> using namespace std; #include "Graph.h" int main(){ Graph<char *, int> graph, graph2; int shotestpath[7]; char *vertex[] = { "清华", "武大", "华科", "交大", "北大", "地大", "复旦" }; int edge[][3] = { { 0, 1, 43 }, { 0, 2, 12 }, { 1, 2, 38 }, { 2, 3, 1325 } , { 3, 6, 55 }, { 4, 5, 34 }, { 4, 6, 248 } }; for (int i = 0; i < 7; i++){ graph.InsertVertex(vertex[i]); } graph.Print(); cout << endl << endl << endl; for (int i = 0; i < 7; i++){ graph.InsertEdge(edge[i][0], edge[i][1], edge[i][2]); graph.InsertEdge(edge[i][1], edge[i][0], edge[i][2]); } graph.Print(); cout << endl << endl << endl; graph.Dijkstra(0, shotestpath); for (int i = 0; i < 7; i++){ cout << graph.GetValue(0) << "--->" << graph.GetValue(i) << ": " << shotestpath[i] << endl; } cout << endl << endl << endl; graph.Prim(graph2); cout << endl << endl << endl; graph.Removevertex(2); graph.Print(); cin.get(); return 0; }运行效果如图1所示:
图1 运行效果