今天,我们一起来实践一下数据结构-图,具体实现代码如下:
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;
- };
- #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;
- }
- 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;
- }
- #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;
- }
- }
- #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 运行效果