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;
}
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 "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 "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;
}
#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();
return 0;
}