今天,我们一起来实践一下数据结构-图,具体实现代码如下:

Edge.h具体内容如下:

[cpp]  view plain copy
  1. template<typename DistType> struct Edge{  
  2. public:  
  3.     Edge(int dest, DistType cost) : m_ndest(dest), m_cost(cost), m_pnext(NULL){}  
  4.   
  5. public:  
  6.     int m_ndest;  
  7.     DistType m_cost;  
  8.     Edge<DistType> *m_pnext;  
  9.   
  10. };  
Graph.h具体内容如下:

[cpp]  view plain copy
  1. #include "Vertex.h"  
  2.   
  3. template<typename NameType, typename DistType> class Graph{  
  4. public:  
  5.     Graph(int size = m_nDefaultSize);   //create the Graph with the most vertex of size  
  6.     ~Graph();  
  7.     bool GraphEmpty() const{    //Is empty?  
  8.         return 0 == m_nnumvertex;  
  9.     }  
  10.     bool GraphFull() const{     //Is full?  
  11.         return m_nMaxNum == m_nnumvertex;  
  12.     }  
  13.     int NumberOfVertex() const//get the number of vertex  
  14.         return m_nnumvertex;  
  15.     }  
  16.     int NumberOfEdge() const{   //get the number of edge  
  17.         return m_nnumedges;  
  18.     }  
  19.     NameType GetValue(int v);   //get the value of the vth vertex  
  20.     DistType GetWeight(int v1, int v2); //get the weight between v1 and v2  
  21.     int GetFirst(int v);        //get the first neighbor vertex of v  
  22.     int GetNext(int v1, int v2);//get the next neighbor vertex of v1 behind v2  
  23.     bool InsertVertex(const NameType vertex);   //insert vertex with the name of vertex  
  24.     bool Removevertex(int v);   //remove the vth vertex  
  25.   
  26.     //insert the edge between v1 and v2  
  27.     bool InsertEdge(int v1, int v2, DistType weight = m_Infinity);  
  28.   
  29.     bool RemoveEdge(int v1, int v2);    //delete the edge between v1 and v2  
  30.     void Print();   //print the graph  
  31.   
  32.     Edge<DistType> *GetMin(int v, int *visited);    //get the min weight of the neighbor vertex of v  
  33.     void Prim(Graph<NameType, DistType> &graph);    //get the minimize span tree  
  34.     void DFS(int v, int *visited);      //depth first search  
  35.     void DFS();  
  36.     void Dijkstra(int v, DistType *shotestpath);    //get the min weight from v to other vertex  
  37.   
  38. private:  
  39.     Vertex<NameType, DistType> *m_pnodetable;   //neighbor list  
  40.     int m_nnumvertex;  
  41.     const int m_nMaxNum;  
  42.     static const int m_nDefaultSize = 10;       //the default maximize vertex  
  43.     static const DistType m_Infinity = 100000;  //there is no edge  
  44.     int m_nnumedges;  
  45.     int Getvertexpos(const NameType vertex);    //get the vertex's position with the name of vertex  
  46. };  
  47.   
  48.   
  49. template<typename NameType, typename DistType> Graph<NameType, DistType>::Graph(int size)  
  50.     : m_nnumvertex(0), m_nMaxNum(size), m_nnumedges(0){  
  51.     m_pnodetable = new Vertex<NameType, DistType>[size];  
  52. }  
  53.   
  54. template<typename NameType, typename DistType> Graph<NameType, DistType>::~Graph(){  
  55.     Edge<DistType> *pmove;  
  56.     for (int i = 0; i < this->m_nnumvertex; i++){  
  57.         pmove = this->m_pnodetable[i].adj;  
  58.         if (pmove){  
  59.             this->m_pnodetable[i].adj = pmove->m_pnext;  
  60.             delete pmove;  
  61.             pmove = this->m_pnodetable[i].adj;  
  62.         }  
  63.     }  
  64.     delete[] m_pnodetable;  
  65. }  
  66.   
  67. template<typename NameType, typename DistType> int Graph<NameType, DistType>::GetFirst(int v){  
  68.     if (v < 0 || v >= this->m_nnumvertex){  
  69.         return -1;  
  70.     }  
  71.     Edge<DistType> *ptemp = this->m_pnodetable[v].adj;  
  72.     return m_pnodetable[v].adj ? m_pnodetable[v].adj->m_ndest : -1;  
  73. }  
  74.   
  75. template<typename NameType, typename DistType> int Graph<NameType, DistType>::GetNext(int v1, int v2){  
  76.     if (-1 != v1){  
  77.         Edge<DistType> *pmove = this->m_pnodetable[v1].adj;  
  78.         while (NULL != pmove->m_pnext){  
  79.             if (pmove->m_ndest == v2){  
  80.                 return pmove->m_pnext->m_ndest;  
  81.             }  
  82.             pmove = pmove->m_pnext;  
  83.         }  
  84.     }  
  85.     return -1;  
  86. }  
  87.   
  88. template<typename NameType, typename DistType> NameType Graph<NameType, DistType>::GetValue(int v){  
  89.     if (v < 0 || v >= this->m_nnumvertex){  
  90.         cerr << "The vertex is not exsit" << endl;  
  91.         exit(1);  
  92.     }  
  93.     return m_pnodetable[v].m_data;  
  94.   
  95. }  
  96.   
  97. template<typename NameType, typename DistType> int Graph<NameType, DistType>::Getvertexpos(const NameType vertex){  
  98.     for (int i = 0; i < this->m_nnumvertex; i++){  
  99.         if (vertex == m_pnodetable[i].m_data){  
  100.             return i;  
  101.         }  
  102.     }  
  103.     return -1;  
  104. }  
  105.   
  106. template<typename NameType, typename DistType> DistType Graph<NameType, DistType>::GetWeight(int v1, int v2){  
  107.     if (v1 >= 0 && v1 < this->m_nnumvertex && v2 >= 0 && v2 < this->m_nnumvertex){  
  108.         if (v1 == v2){  
  109.             return 0;  
  110.         }  
  111.         Edge<DistType> *pmove = m_pnodetable[v1].adj;  
  112.         while (pmove){  
  113.             if (pmove->m_ndest == v2){  
  114.                 return pmove->m_cost;  
  115.             }  
  116.             pmove = pmove->m_pnext;  
  117.         }  
  118.     }  
  119.     return m_Infinity;  
  120. }  
  121.   
  122. template<typename NameType, typename DistType> bool Graph<NameType, DistType>::InsertEdge(int v1, int v2, DistType weight){  
  123.     if (v1 >= 0 && v1 < this->m_nnumvertex && v2 >= 0 && v2 < this->m_nnumvertex){  
  124.         Edge<DistType> *pmove = m_pnodetable[v1].adj;  
  125.         if (NULL == pmove){ //the first neighbor  
  126.             m_pnodetable[v1].adj = new Edge<DistType>(v2, weight);  
  127.             return 1;  
  128.         }  
  129.         while (pmove->m_pnext){  
  130.             if (pmove->m_ndest == v2){  
  131.                 break;  
  132.             }  
  133.             pmove = pmove->m_pnext;  
  134.         }  
  135.         if (pmove->m_ndest == v2){  //if the edge is exist, change the weight  
  136.             pmove->m_cost = weight;  
  137.             return 1;  
  138.         }  
  139.         else{  
  140.             pmove->m_pnext = new Edge<DistType>(v2, weight);  
  141.             return 1;  
  142.         }  
  143.     }  
  144.     return 0;  
  145. }  
  146. template<typename NameType, typename DistType> bool Graph<NameType, DistType>::InsertVertex(const NameType vertex){  
  147.     int i = this->Getvertexpos(vertex);  
  148.     if (-1 != i){  
  149.         this->m_pnodetable[i].m_data = vertex;  
  150.     }  
  151.     else{  
  152.         if (!this->GraphFull()){  
  153.             this->m_pnodetable[this->m_nnumvertex].m_data = vertex;  
  154.             this->m_nnumvertex++;  
  155.         }  
  156.         else{  
  157.             cerr << "The Graph is Full" << endl;  
  158.             return 0;  
  159.         }  
  160.     }  
  161.     return 1;  
  162. }  
  163. template<typename NameType, typename DistType> bool Graph<NameType, DistType>::RemoveEdge(int v1, int v2){  
  164.     if (v1 >= 0 && v1 < this->m_nnumvertex && v2 >= 0 && v2 < this->m_nnumvertex){  
  165.         Edge<DistType> *pmove = this->m_pnodetable[v1].adj, *pdel;  
  166.         if (NULL == pmove){  
  167.             cerr << "the edge is not exist!" << endl;  
  168.             return 0;  
  169.         }  
  170.         if (pmove->m_ndest == v2){  //the first neighbor  
  171.             this->m_pnodetable[v1].adj = pmove->m_pnext;  
  172.             delete pmove;  
  173.             return 1;  
  174.         }  
  175.         while (pmove->m_pnext){  
  176.             if (pmove->m_pnext->m_ndest == v2){  
  177.                 pdel = pmove->m_pnext;  
  178.                 pmove->m_pnext = pdel->m_pnext;  
  179.                 delete pdel;  
  180.                 return 1;  
  181.             }  
  182.             pmove = pmove->m_pnext;  
  183.         }  
  184.     }  
  185.     cerr << "the edge is not exist!" << endl;  
  186.     return 0;  
  187. }  
  188. template<typename NameType, typename DistType> bool Graph<NameType, DistType>::Removevertex(int v){  
  189.     if (v < 0 || v >= this->m_nnumvertex){  
  190.         cerr << "the vertex is not exist!" << endl;  
  191.         return 0;  
  192.     }  
  193.     Edge<DistType> *pmove, *pdel;  
  194.     for (int i = 0; i < this->m_nnumvertex; i++){  
  195.         pmove = this->m_pnodetable[i].adj;  
  196.         if (i != v){    //delete the edge point to v  
  197.             if (NULL == pmove){  
  198.                 continue;  
  199.             }  
  200.             if (pmove->m_ndest == v){  
  201.                 this->m_pnodetable[i].adj = pmove->m_pnext;  
  202.                 delete pmove;  
  203.                 continue;  
  204.             }  
  205.             else {  
  206.                 if (pmove->m_ndest > v){    //the vertex more than v subtract 1  
  207.                     pmove->m_ndest--;  
  208.                 }  
  209.             }  
  210.             while (pmove->m_pnext){  
  211.                 if (pmove->m_pnext->m_ndest == v){  
  212.                     pdel = pmove->m_pnext;  
  213.                     pmove->m_pnext = pdel->m_pnext;  
  214.                     delete pdel;  
  215.                 }  
  216.                 else {  
  217.                     if (pmove->m_pnext->m_ndest > v){  
  218.                         pmove->m_pnext->m_ndest--;  
  219.                         pmove = pmove->m_pnext;  
  220.                     }  
  221.                 }  
  222.             }  
  223.         }  
  224.         else {      //delete the edge point from v  
  225.             while (pmove){  
  226.                 this->m_pnodetable[i].adj = pmove->m_pnext;  
  227.                 delete pmove;  
  228.                 pmove = this->m_pnodetable[i].adj;  
  229.             }  
  230.         }  
  231.     }  
  232.     this->m_nnumvertex--;  
  233.     for (int i = v; i < this->m_nnumvertex; i++)    //delete the vertex  
  234.     {  
  235.         this->m_pnodetable[i].adj = this->m_pnodetable[i + 1].adj;  
  236.         this->m_pnodetable[i].m_data = this->m_pnodetable[i + 1].m_data;  
  237.     }  
  238.     this->m_pnodetable[this->m_nnumvertex].adj = NULL;  
  239.     return 1;  
  240. }  
  241.   
  242. template<typename NameType, typename DistType> void Graph<NameType, DistType>::Print(){  
  243.     Edge<DistType> *pmove;  
  244.     for (int i = 0; i < this->m_nnumvertex; i++){  
  245.         cout << this->m_pnodetable[i].m_data << "--->";  
  246.         pmove = this->m_pnodetable[i].adj;  
  247.         while (pmove){  
  248.             cout << pmove->m_cost << "--->" << this->m_pnodetable[pmove->m_ndest].m_data << "--->";  
  249.             pmove = pmove->m_pnext;  
  250.         }  
  251.         cout << "NULL" << endl;  
  252.     }  
  253. }  
  254.   
  255. template<typename NameType, typename DistType> void Graph<NameType, DistType>::Prim(Graph<NameType, DistType> &graph){  
  256.     int *node = new int[this->m_nnumvertex];    //using for store the vertex visited  
  257.     int *visited = new int[this->m_nnumvertex];  
  258.     int count = 0;  
  259.     Edge<DistType> *ptemp, *ptemp2 = new Edge<DistType>(0, this->m_Infinity), *pmin;  
  260.     int min;  
  261.     for (int i = 0; i < this->m_nnumvertex; i++){  
  262.         graph.InsertVertex(this->m_pnodetable[i].m_data);  
  263.         node[i] = 0;  
  264.         visited[i] = 0;  
  265.     }  
  266.     visited[0] = 1;  
  267.     while (++count < this->m_nnumvertex){  
  268.         pmin = ptemp2;  
  269.         pmin->m_cost = this->m_Infinity;  
  270.   
  271.         //get the minimize weight between the vertex visited and the  vertex which is not visited  
  272.         for (int i = 0; i<count; i++){  
  273.             ptemp = GetMin(node[i], visited);  
  274.             if (NULL == ptemp){  
  275.                 continue;  
  276.             }  
  277.             if (pmin->m_cost > ptemp->m_cost){  
  278.                 pmin = ptemp;  
  279.                 min = node[i];  
  280.             }  
  281.         }  
  282.   
  283.         node[count] = pmin->m_ndest;  
  284.         visited[node[count]] = 1;  
  285.         graph.InsertEdge(pmin->m_ndest, min, pmin->m_cost);  
  286.         graph.InsertEdge(min, pmin->m_ndest, pmin->m_cost);  
  287.     }  
  288.     graph.DFS();  
  289.     delete ptemp2;  
  290.     delete[] node;  
  291.     delete[] visited;  
  292. }  
  293.   
  294. template<typename NameType, typename DistType> void Graph<NameType, DistType>::DFS(int v, int *visited){  
  295.     cout << "--->" << this->GetValue(v);  
  296.     visited[v] = 1;  
  297.     int weight = this->GetFirst(v);  
  298.     while (-1 != weight){  
  299.         if (!visited[weight]){  
  300.             cout << "--->" << this->GetWeight(v, weight);  
  301.             DFS(weight, visited);  
  302.         }  
  303.         weight = this->GetNext(v, weight);  
  304.     }  
  305. }  
  306.   
  307. template<typename NameType, typename DistType> void Graph<NameType, DistType>::DFS(){  
  308.     int *visited = new int[this->m_nnumvertex];  
  309.     for (int i = 0; i < this->m_nnumvertex; i++){  
  310.         visited[i] = 0;  
  311.     }  
  312.     cout << "head";  
  313.     DFS(0, visited);  
  314.     cout << "--->end";  
  315. }  
  316.   
  317. template<typename NameType, typename DistType> Edge<DistType>* Graph<NameType, DistType>::GetMin(int v, int *visited){  
  318.     Edge<DistType> *pmove = this->m_pnodetable[v].adj, *ptemp = new Edge<DistType>(0, this->m_Infinity), *pmin = ptemp;  
  319.     while (pmove){  
  320.         if (!visited[pmove->m_ndest] && pmin->m_cost > pmove->m_cost){  
  321.             pmin = pmove;  
  322.         }  
  323.         pmove = pmove->m_pnext;  
  324.     }  
  325.     if (pmin == ptemp){  
  326.         delete ptemp;  
  327.         return NULL;  
  328.     }  
  329.     delete ptemp;  
  330.     return pmin;  
  331. }  
  332. template<typename NameType, typename DistType> void Graph<NameType, DistType>::Dijkstra(int v, DistType *shotestpath){  
  333.     int *visited = new int[this->m_nnumvertex];  
  334.     int *node = new int[this->m_nnumvertex];  
  335.     for (int i = 0; i < this->m_nnumvertex; i++){  
  336.         visited[i] = 0;  
  337.         node[i] = 0;  
  338.         shotestpath[i] = this->GetWeight(v, i);  
  339.     }  
  340.     visited[v] = 1;  
  341.     for (int i = 1; i < this->m_nnumvertex; i++){  
  342.         DistType min = this->m_Infinity;  
  343.         int u = v;  
  344.   
  345.         for (int j = 0; j < this->m_nnumvertex; j++){   //get the minimize weight  
  346.             if (!visited[j] && shotestpath[j] < min){  
  347.                 min = shotestpath[j];  
  348.                 u = j;  
  349.             }  
  350.         }  
  351.   
  352.         visited[u] = 1;  
  353.         for (int w = 0; w < this->m_nnumvertex; w++){   //change the weight from v to other vertex  
  354.             DistType weight = this->GetWeight(u, w);  
  355.             if (!visited[w] && weight != this->m_Infinity  
  356.                 && shotestpath[u] + weight < shotestpath[w]){  
  357.                 shotestpath[w] = shotestpath[u] + weight;  
  358.             }  
  359.         }  
  360.     }  
  361.     delete[] visited;  
  362.     delete[] node;  
  363. }  
MinHeap.h具体内容如下:

[cpp]  view plain copy
  1. template<typename Type> class MinHeap{  
  2. public:  
  3.     MinHeap(Type heap[], int n);        //initialize heap by a array  
  4.     ~MinHeap(){  
  5.         delete[] m_pheap;  
  6.     }  
  7.   
  8. public:  
  9.     bool Insert(const Type item);  
  10.     bool DeleteMin(Type &first);  
  11.   
  12. private:  
  13.     void Adjust(const int start, const int end);    //adjust the elements from start to end  
  14.   
  15.   
  16. private:  
  17.     const int m_nMaxSize;  
  18.     Type *m_pheap;  
  19.     int m_ncurrentsize;  
  20. };  
  21.   
  22. template<typename Type> void MinHeap<Type>::Adjust(const int start, const int end){  
  23.     int i = start, j = i * 2 + 1;  
  24.     Type temp = m_pheap[i];  
  25.     while (j <= end){  
  26.         if (j<end && m_pheap[j]>m_pheap[j + 1]){  
  27.             j++;  
  28.         }  
  29.         if (temp <= m_pheap[j]){  
  30.             break;  
  31.         }  
  32.         else{  
  33.             m_pheap[i] = m_pheap[j];  
  34.             i = j;  
  35.             j = 2 * i + 1;  
  36.         }  
  37.     }  
  38.     m_pheap[i] = temp;  
  39. }  
  40.   
  41. template<typename Type> MinHeap<Type>::MinHeap(Type heap[], int n) :m_nMaxSize(n){  
  42.     m_pheap = new Type[m_nMaxSize];  
  43.     for (int i = 0; i < n; i++){  
  44.         m_pheap[i] = heap[i];  
  45.     }  
  46.     m_ncurrentsize = n;  
  47.     int pos = (n - 2) / 2;  //Find the last tree which has more than one element;  
  48.     while (pos >= 0){  
  49.         Adjust(pos, n - 1);  
  50.         pos--;  
  51.     }  
  52. }  
  53.   
  54. template<typename Type> bool MinHeap<Type>::DeleteMin(Type &first){  
  55.     first = m_pheap[0];  
  56.     m_pheap[0] = m_pheap[m_ncurrentsize - 1];  
  57.     m_ncurrentsize--;  
  58.     Adjust(0, m_ncurrentsize - 1);  
  59.     return 1;  
  60. }  
  61.   
  62. template<typename Type> bool MinHeap<Type>::Insert(const Type item){  
  63.     if (m_ncurrentsize == m_nMaxSize){  
  64.         cerr << "Heap Full!" << endl;  
  65.         return 0;  
  66.     }  
  67.     m_pheap[m_ncurrentsize] = item;  
  68.     int j = m_ncurrentsize, i = (j - 1) / 2;  
  69.     Type temp = m_pheap[j];  
  70.     while (j > 0){  
  71.         if (m_pheap[i] <= temp){  
  72.             break;  
  73.         }  
  74.         else{  
  75.             m_pheap[j] = m_pheap[i];  
  76.             j = i;  
  77.             i = (j - 1) / 2;  
  78.         }  
  79.     }  
  80.     m_pheap[j] = temp;  
  81.     m_ncurrentsize++;  
  82.     return 1;  
  83. }  
Vertex.h具体内容如下:

[cpp]  view plain copy
  1. #include "Edge.h"  
  2.   
  3. template<typename NameType, typename DistType> struct Vertex{  
  4. public:  
  5.     Vertex() : adj(NULL){}  
  6.     NameType m_data;  
  7.     Edge<DistType> *adj;  
  8.     ~Vertex();  
  9. };  
  10.   
  11. template<typename NameType, typename DistType> Vertex<NameType, DistType>::~Vertex(){  
  12.     Edge<DistType> *pmove = adj;  
  13.     while (pmove){  
  14.         adj = pmove->m_pnext;  
  15.         delete pmove;  
  16.         pmove = adj;  
  17.     }  
  18. }  
main.cpp具体内容如下:

[cpp]  view plain copy
  1. #include <iostream>  
  2.   
  3. using namespace std;  
  4.   
  5. #include "Graph.h"  
  6.   
  7. int main(){  
  8.     Graph<char *, int> graph, graph2;  
  9.     int shotestpath[7];  
  10.     char *vertex[] = { "清华""武大""华科""交大""北大""地大""复旦" };  
  11.     int edge[][3] = { { 0, 1, 43 }, { 0, 2, 12 }, { 1, 2, 38 }, { 2, 3, 1325 }  
  12.     , { 3, 6, 55 }, { 4, 5, 34 }, { 4, 6, 248 } };  
  13.     for (int i = 0; i < 7; i++){  
  14.         graph.InsertVertex(vertex[i]);  
  15.     }  
  16.     graph.Print();  
  17.     cout << endl << endl << endl;  
  18.     for (int i = 0; i < 7; i++){  
  19.         graph.InsertEdge(edge[i][0], edge[i][1], edge[i][2]);  
  20.         graph.InsertEdge(edge[i][1], edge[i][0], edge[i][2]);  
  21.     }  
  22.     graph.Print();  
  23.     cout << endl << endl << endl;  
  24.     graph.Dijkstra(0, shotestpath);  
  25.     for (int i = 0; i < 7; i++){  
  26.         cout << graph.GetValue(0) << "--->" << graph.GetValue(i)  
  27.             << ":   " << shotestpath[i] << endl;  
  28.     }  
  29.   
  30.     cout << endl << endl << endl;  
  31.     graph.Prim(graph2);  
  32.     cout << endl << endl << endl;  
  33.     graph.Removevertex(2);  
  34.     graph.Print();  
  35.     cin.get();  
  36.     return 0;  
  37. }  
运行效果如图1所示:

图1 运行效果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值