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

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 运行效果

原文地址:https://www.cnblogs.com/new0801/p/6176933.html