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

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

  • 相关阅读:
    nyoj 199 无线网络覆盖
    hdoj 2682 Tree
    nyoj 845 无主之地1
    hdoj 1874 畅通工程续【dijkstra算法or spfa算法】
    hdoj 2544 最短路【dijkstra or spfa】
    hdoj 4548 美素数
    打表法
    hdoj 2098 分拆素数和
    hdoj 1262 寻找素数对
    bzoj1180,2843
  • 原文地址:https://www.cnblogs.com/new0801/p/6176933.html
Copyright © 2020-2023  润新知