One: Common graph structure
#ifndef _graph_h#define _graph_h#include <iostream> #include <string.h> #include <assert.h> #include <queue>using namespace::std; #define Max_cost 0x7FFFFFFF//Spend infinitely large set to integer maximum////////////////////////////////////// General graph Structure Template <typename T, typename E>class graph{ Public:bool is_empty () const;bool is_full () const;int get_numvertices () const; Current vertex number int get_numedges () const; Current number of sides public:virtual bool Insert_vertex (const t&) = 0; Insert vertex virtual bool Insert_edge (const t&, const t&, E) = 0; Insert Edge Virtual int Get_firstneighbor (const t&) const = 0; Gets the first adjacency vertex of the virtual int get_nextneighbor (const t&, const t&) const = 0; Next adjacency vertex of an adjacency vertex virtual void print_graph () const = 0;virtual int Get_vertex_index (const t&) const = 0; Get vertex ordinal virtual void Depth_first (const t&) = 0;virtual void Broad_first (const t&) = 0;virtual void Min_spantree_kr Uskal () = 0;virtual void miN_spantree_prim (const t&) = 0;protected:static const int vertices_default_size = 10; Default graph vertex number int max_vertices;int num_vertices;int num_edges;}; Template <typename T, typename E>bool graph<t, E>::is_empty () const{return num_edges = = 0;} Template <typename T, typename E>bool graph<t, E>::is_full () const{return num_vertices >= max_vertices | | Num_edges >= max_vertices* (max_vertices-1)/2; Full, divided into vertex full and full}template <typename T, TypeName E>int graph<t, E>::get_numvertices () Const{return num_ vertices;} Template <typename T, typename E>int graph<t, E>::get_numedges () Const{return num_edges;} #define Vertices_ Default_size graph<t, E>::vertices_default_size#define num_vertices graph<t, E>::num_vertices #defi Ne num_edges graph<t, e>::num_edges#define max_vertices graph<t, e>::max_vertices #endif/*graph.h*/ Two: adjacency matrix diagram structure
#pragma once#include "graph.h"//graph of adjacency matrix notation template <typename T, typename E>class graph_mtx:public graph<t, E> ; {public:graph_mtx (int); ~GRAPH_MTX (); Public:bool Insert_vertex (const t&); bool Insert_edge (const t&, const t&; E); int Get_firstneighbor (const t&) const;int Get_nextneighbor (const t&, const t&) const;int Get_vertex_index ( const t&) const; t& get_vertex_symbol (const int) const;void print_graph () const;void depth_first (const t&); void Broad_first ( Const t&), void Min_spantree_kruskal (), void Min_spantree_prim (const t&);p rotected:void depth_first (const T &, BOOL *);p rivate:t* vertices_list; Vertex linear table E **edge; Internal Matrix};template <typename T, TypeName e>graph_mtx<t, e>::graph_mtx (int sz = vertices_default_size) {Max_ vertices = SZ > vertices_default_size? Sz:vertices_default_size;vertices_list = new T[max_vertices];edge = newInt*[max_vertices]; Dynamically apply a two-dimensional array for (int i=0; i<max_vertices; ++i) {Edge[i] = new int[max_vertices];} for (int i=0, i<max_vertices; ++i) for (int j=0; j<max_vertices; ++j) {if (i! = j) Edge[i][j] = max_cost;elseedge[i][j] = 0;} num_vertices = 0;num_edges = 0;} Template <typename T, TypeName E>graph_mtx<t, E>::~graph_mtx () {for (int i=0; i<max_vertices; ++i) Delete [ ]edge[i]; Separate destruction, and then the total destruction of the delete edge;delete []vertices_list;} Template <typename T, typename E>bool graph_mtx<t, E>::insert_vertex (const t& vert) {if (this->is_ Full ())//derived class function call parent class function, with this or add scope return false;vertices_list[num_vertices++] = Vert;return true;} Template <typename T, typename E>bool graph_mtx<t, E>::insert_edge (const t& vert1, const t& VERT2, E C OST = Max_cost)//due to the existence of the default value of the value, Get_neighbor operation to determine whether equal to max_cost, otherwise it will not get the adjacency vertex {if (This->is_full ())//Full RE Turn False;int INDEX_V1 = Get_vertex_index (VERT1); Get the vertex ordinal int index_v2 = Get_vertex_index (VERT2); if (index_v1 = =-1 | | index_v2 =-1) return FALSE;EDGE[INDEX_V1][INDEX_V2] = Edge[index_v2][index_v1] = Cost; Graph ++num_edges;return true;} Template <typename T, typename E>int graph_mtx<t, E>::get_firstneighbor (const t& vert) Const{int index = g Et_vertex_index (vert); if (Index! =-1) {for (int i=0; i<num_vertices; ++i) {if (edge[index][i]! = 0 && Edge[index ][i] = max_cost)//plus Judge Max_costreturn I;}} return-1;} Template <typename T, typename E>int graph_mtx<t, E>::get_nextneighbor (const t& vert1, const t& VERT2 ) Const{int INDEX_V1 = Get_vertex_index (vert1); int index_v2 = Get_vertex_index (VERT2); if (index_v1! =-1 && index_ V2! =-1) {for (int i=index_v2+1; i<num_vertices; ++i) {if (edge[index_v1][i]! = 0 && edge[index_v1][i]! = Max_cos T) return i;}} return-1;} Template <typename T, typename E>int graph_mtx<t, E>::get_vertex_index (const t& vert) const{for (int i=0; I<num_vertices; ++i) {if (vertices_list[i] = = vert) return i;} return-1;} Template <typename T, typename e>t& graph_mtx<t, e>::get_vertex_symbol (const int index) Const{assert ( Index >= 0 && Index < this->get_numvertices ())//assert (index >= 0 && Index < num_vertices) ; Error, because num_vertices itself is we replace the parent class with a macro that element, where use will appear double macro return Vertices_list[index];} Template <typename T, typename e>void graph_mtx<t, E>::p rint_graph () const{if (This->is_empty ()) {cout << "Nil graph" << Endl; Null output Nilreturn;} for (int i=0; i<num_vertices; ++i) {cout << vertices_list[i] << "";} cout << endl;for (int i=0; i<num_vertices; ++i) {for (int j=0; j<num_vertices; ++j) {if (edge[i][j]! = max_cost) cout << Edge[i][j] << ""; elsecout << ' @ ' << ' "; If the weights are infinitely large, replace}cout << vertices_list[i] << Endl;}} Template <typename T, typename e>void graph_mtx<t, E>::d Epth_first (consT t& Vert)//depth First, look for a way to die, no way to go back {int num = this->get_numvertices (); bool *visited = new Bool[num];memset (visited , 0, sizeof (BOOL) *num); First of all the assignment is false, after the traversal is true, to prevent the graph dead loop Depth_first (vert, visited); cout << "end."; delete []visited;} Template <typename T, typename e>void graph_mtx<t, E>::d epth_first (const t& vert, bool *visited) {cout < ;< Vert << "--"; int index = Get_vertex_index (vert); Visited[index] = True;int Neighbor_index = Get_firstneigh Bor (vert), while (neighbor_index! =-1) {if (!visited[neighbor_index]) Depth_first (Get_vertex_symbol (Neighbor_index), visited); Recursive neighbor_index = Get_nextneighbor (Vert,get_vertex_symbol (Neighbor_index));}} Template <typename T, typename e>void graph_mtx<t, E>::broad_first (const t& vert) {int num = this->get_ Numvertices (); bool *visited = new Bool[num];int index = Get_vertex_index (vert); assert (Index! =-1); memset (visited, 0, siz EOF (BOOL) *num);queue<int> que; Through the queue, the metaQue.push (index), cout << vert << "--"; Visited[index] = True;while (!que.empty ()) {int index_tmp = Que.front (); Que.pop (); int neighbor_index = Get_firstneighbor (Get_vertex_symbol (index_tmp)); while (neighbor_index! = -1) {if (!visited[neighbor_index]) {cout << get_vertex_symbol (neighbor_index) << "-"; visited[ Neighbor_index] = true; After the traversal is true, prevent the graph from looping Que.push (Neighbor_index);} Neighbor_index = Get_nextneighbor (Get_vertex_symbol (index_tmp), Get_vertex_symbol (Neighbor_index));}} cout << "end."; delete []visited;} Min_spactree_kruskaltemplate <typename T, TypeName e>struct _mst_edge{//minimum spanning tree edge structure, <begin, end> for a set of edges, cost for spending int begin;int end; E cost;}; Template <typename T, typename E>int Compare (const void* VP1, const void* VP2) {return (* (_mst_edge<t, e> *) v p1). Cost – (* (* (_mst_edge<t, e> *) VP2). Cost; BOOL _is_same (int *father, int begin, int end)//determine if in the same sub-graph {while (Father[begin]! = begin) Begin = Father[begin];while (Father[end]! = end) End = Fath Er[end]; return begin = = END; Determine if the last element has a parent-child relationship}void mark_same (int *father, int begin, int end) {while (Father[begin]! = begin) begin = Father[begin]; while (father[end]! = end) End = Father[end];father[end] = begin; Let the last element join together, making them the elements of the same sub-graph}template <typename T, TypeName e>void graph_mtx<t, E>::min_spantree_kruskal () {int num = this->get_numvertices (); _mst_edge<t, e> *mst_edge = new _mst_edge<t, e>[num* (num-1)/2];int k = 0 ; for (int i=0; i<num; ++i) for (int j=i+1; j<num; ++j) {//Create an array of valid edge structures, starting with i+1, direct statistical matrix 1/2-side number, no duplicate if (edge[i][j]! = MA X_cost) {mst_edge[k].begin = I;mst_edge[k].end = J;mst_edge[k].cost = Edge[i][j];++k;}} Qsort (Mst_edge, K, sizeof (_mst_edge<t, e>), compare<t, e>); Call the quick sort function int *father = new Int[num]; Initialize causes all elements of the parent to point to themselves for (int i=0; i<num; ++i) father[I] = i;for (int i=0; i<num; ++i) if (!_is_same (father, Mst_edge[i].begin, mst_edge[i].end)) {//Decide whether to cout in the same sub-chart << Get_vertex_symbol (Mst_edge[i].begin) << "-" << Get_vertex_symbol (mst_edge[i].end) << ":" < < Mst_edge[i].cost << Endl;mark_same (father, Mst_edge[i].begin, mst_edge[i].end); After adding mark}delete []father;delete []mst_edge;} Min_spantree_primtemplate <typename T, TypeName E>void graph_mtx<t, E>::min_spantree_prim (const t& vert) {int num = this->get_numvertices (); int *lowcost = new Int[num]; Minimum spend array int *mst = new Int[num]; Starting position array <mst[i], i> as a set of edges, starting with mst[i]int index = Get_vertex_index (vert), assert (Index! =-1); for (int i=0; i<num; + +) i) {//Initialize so that the default cost per element is vert as the starting edge, so mst[i] corresponds to subscript vert subscript indexif (edge[index][i]! = 0) {Lowcost[i] = edge[index][i];mst[ I] = index;} Elselowcost[i] = 0;} for (int i=0; i<num-1; ++i) {//Xunhua, num elements total num-1 stripe inT min = max_cost;int min_index = -1;for (int j=0; j<num; ++j) {if (lowcost[j]! = 0 && lowcost[j] < min) {//Find Minimum cost min = Lowcost[j];min_index = j;}} cout << Get_vertex_symbol (Mst[min_index]) << "--" << Get_vertex_symbol (Min_index) << ":" & lt;< min << Endl;lowcost[min_index] = 0; The cost is 0, equivalent to join the generated tree for (int j=0; j<num; ++j) {//loop, if an element to the new element cost less than the default, then update it, int cost = edge[min_index][j];// The next time you loop to the top to find the minimum cost, it's possible to find the minimum cost of the update, which is equivalent to the IF (Cost < Lowcost[j]) {///other vertices pick out the minimum spent on all vertices of the spanning tree each time a new element is added, and update lowcost[j] = costs ; mst[j] = Min_index;}}} delete []lowcost;delete []mst;}Three: Test part of the test diagram: Test code:
#include " Graph.h "#include" graph_mtx.h "#define Vertex_size 4int Main () {Graph_mtx<char, int> gm;gm.insert_vertex (' A '); Gm.insert_vertex (' B '); Gm.insert_vertex (' C '); Gm.insert_vertex (' D '); Gm.insert_vertex (' E '); Gm.insert_vertex (' F '); Gm.insert_edge (' A ', ' B ', 6); Gm.insert_edge (' A ', ' C ', 1); Gm.insert_edge (' A ', ' D ', 5); Gm.insert_edge (' B ', ' C ', 5); Gm.insert_edge (' B ', ' E ', 3); Gm.insert_edge (' C ', ' D ', 5); Gm.insert_edge (' C ', ' F ', 4); Gm.insert_edge (' D ', ' F ', 2); Gm.insert_edge (' E ', ' F ', 6); Gm.insert_edge (' C ', ' E ', 6); Gm.print_graph (); cout << "Depth_first Traverse:" < < Endl;gm.depth_first (' A '); cout << endl;cout << "Broad_first traverse:" << endl;gm.broad_first (' A '); cout << endl;cout << "Min_spantree_kruskal:" << Endl;gm.min_spantree_kruskal (); cout << " Min_spantree_prim: "<< endl;gm.min_spantree_prim (' A '); return 0;}
Test results:
Depth-first search and breadth-first search algorithm, minimum spanning tree two algorithms--c++ implementation of graphs