📄 graphlnk.h
字号:
//邻接表实现的图类
#ifndef GRAPHLNK_H
#define GRAPHLNK_H
#include <iostream>
using namespace std;
//#include "tree.h"
const int maxWeight = 10000; //代表无穷大的值(=)
const int DefaultVertices = 30; //默认最大顶点数(=n)
template <class T, class E>
struct Edge { //边结点的定义
int dest; //边的另一顶点位置
E cost; //边上的权值
Edge<T,E> *link; //下一条边链指针
Edge() {} //构造函数
Edge(int num, E weight) : dest(num), cost(weight), link (NULL) {} //构造函数
bool operator != (Edge<T,E>& R)const { //判边不等否
return (dest != R.dest) ? true : false;
}
};
template <class T, class E>
struct Vertex { //顶点的定义
T data; //顶点的名字
Edge<T,E> *adj; //边链表的头指针
};
template <class T, class E>
class Graphlnk { //图的类定义
public:
bool GraphEmpty() const { //判图空否
if (numEdges == 0) return true;
else return false;
}
bool GraphFull() const { //判图满否
if (numVertices == maxVertices ||
numEdges == maxVertices*(maxVertices-1)/2) return true;
else return false;
}
int NumberOfVertices() {return numVertices;} //返回当前顶点数
int NumberOfEdges() {return numEdges;} //返回当前边数
public:
Graphlnk(int sz = DefaultVertices); //构造函数
~Graphlnk(); //析构函数
T getValue(int i) //取位置为i的顶点中的值
{return (i >= 0 && i < NumberOfVertices()) ? NodeTable[i].data : 0;}
E getWeight(int v1, int v2); //返回边(v1,v2)上的权值
bool insertVertex(const T& vertex); //在图中插入一个顶点vertex
bool removeVertex(int v); //在图中删除一个顶点v
bool insertEdge(int v1, int v2, E weight); //在图中插入一条边(v1,v2)
bool removeEdge(int v1, int v2); //在图中删除一条边(v1,v2)
int getFirstNeighbor(int v); //取顶点v的第一个邻接顶点
int getNextNeighbor(int v, int w); //取v的邻接顶点w的下一邻接顶点
void DFS(const T& v); //深度优先遍历,子过程
void DFS(int v, bool visited[]); //深度优先遍历
private:
Vertex<T,E> *NodeTable; //顶点表 (各边链表的头结点)
int maxVertices; //图中最大顶点数
int numEdges; //当前边数
int numVertices;
public:
int getVertexPos(const T vertex) { //给出顶点vertex在图中的位置
for (int i = 0; i < numVertices; i++)
if (NodeTable[i].data == vertex) return i;
return -1;
}
};
template <class T, class E>
Graphlnk<T,E>::Graphlnk(int sz) {
//构造函数:建立一个空的邻接表
maxVertices = sz; numVertices = 0; numEdges = 0;
NodeTable = new Vertex<T,E>[maxVertices]; //创建顶点表数组
if (NodeTable == NULL) {cerr << "存储分配错!" << endl; exit(1);}
for (int i = 0; i < maxVertices; i++) NodeTable[i].adj = NULL;
};
template <class T, class E>
Graphlnk<T,E>::~Graphlnk() {
//析构函数:删除一个邻接表
for (int i = 0; i < numVertices; i++ ) { //删除各边链表中的结点
Edge<T,E> *p = NodeTable[i].adj; //找到其对应边链表的首结点
while (p != NULL) { //不断地删除第一个结点
NodeTable[i].adj = p->link;
delete p; p = NodeTable[i].adj;
}
}
delete []NodeTable; //删除顶点表数组
};
template <class T, class E>
E Graphlnk<T,E>::getWeight(int v1, int v2) {
//函数返回边(v1,v2)上的权值, 若该边不在图中, 则函数返回权值0。
if (v1 != -1 && v2 != -1) {
Edge<T,E> *p = NodeTable[v1].adj; //V1的第一条关联的边
while (p != NULL && p->dest != v2) //寻找邻接顶点v2
p = p->link;
if (p != NULL) return p->cost; //找到此边, 返回权值
}
return 0; //边(v1,v2)不存在
};
template <class T, class E>
bool Graphlnk<T,E>::insertVertex(const T& vertex) {
//在图的顶点表中插入一个新顶点vertex。若插入成功,函数返回true, 否则返回false。
if (numVertices == maxVertices) return false; //顶点表满, 不能插入
NodeTable[numVertices].data = vertex; //插入在表的最后
numVertices++; return true;
};
template <class T, class E>
bool Graphlnk<T,E>::insertEdge(int v1, int v2, E weight) {
//在带权图中插入一条边(v1,v2), 若此边存在或参数不合理,函数返回false, 否则返回
//true。对于非带权图, 最后一个参数weight不要。算法中相应语句也不要。
if (v1 >= 0 && v1 < numVertices && v2 >= 0 && v2 < numVertices) {
Edge<T,E> *q, *p = NodeTable[v1].adj; //v1对应的边链表头指针
while (p != NULL && p->dest != v2) //寻找邻接顶点v2
p = p->link;
if (p != NULL) return false; //找到此边, 不插入
p = new Edge<T,E>; q = new Edge<T,E>; //否则, 创建新结点
p->dest = v2; p->cost = weight;
p->link = NodeTable[v1].adj; //链入v1边链表
NodeTable[v1].adj = p;
q->dest = v1; q->cost = weight;
q->link = NodeTable[v2].adj; //链入v2边链表
NodeTable[v2].adj = q;
numEdges++; return true;
}
return 0;
};
template <class T, class E>
int Graphlnk<T,E>::getFirstNeighbor(int v) {
//给出顶点位置为v的第一个邻接顶点的位置, 如果找不到, 则函数返回-1。
if (v != -1) { //顶点v存在
Edge<T,E> *p = NodeTable[v].adj; //对应边链表第一个边结点
if (p != NULL) return p->dest; //存在, 返回第一个邻接顶点
}
return -1; //第一个邻接顶点不存在
};
template <class T,class E>
int Graphlnk<T,E>::getNextNeighbor(int v, int w) {
//给出顶点v的邻接顶点w的下一个邻接顶点的位置,
//若没有下一个邻接顶点, 则函数返回-1。
if (v != -1) { //顶点v存在
Edge<T,E> *p = NodeTable[v].adj; //对应边链表第一个边结点
while (p != NULL && p->dest != w) //寻找邻接顶点w
p = p->link;
if (p != NULL && p->link != NULL)
return p->link->dest; //返回下一个邻接顶点
}
return -1; //下一邻接顶点不存在
};
template <class T, class E>
bool Graphlnk<T,E>::removeEdge(int v1, int v2) {
//在图中删除一条边(v1, v2)
if (v1!= -1 && v2 != -1) {
Edge<T,E> *p = NodeTable[v1].adj, *q = NULL, *s = p;
while (p != NULL && p->dest != v2) //v1对应边链表中找被删边
{q = p; p = p->link;}
if (p != NULL) { //找到被删边结点
if (p == s) NodeTable[v1].adj = p->link; //该结点是边链表首结点
else q->link = p->link; //不是, 重新链接
delete p;
}
else return false; //没有找到被删边结点
p = NodeTable[v2].adj; q = NULL, s = p; //v2对应边链表中删除
while (p->dest != v1) {q = p; p = p->link;} //寻找被删边结点
if (p == s) NodeTable[v2].adj = p->link; //该结点是边链表首结点
else q->link = p->link; //不是, 重新链接
delete p;
return true;
}
return false; //没有找到结点
};
template <class T, class E>
bool Graphlnk<T,E>::removeVertex(int v) {
//在图中删除一个指定顶点v, v是顶点号。若删除成功, 函数返回true, 否则返回false。
if (numVertices == 1 || v < 0 || v >= numVertices) return false;
//表空或顶点号超出范围
Edge<T,E> *p, *s,*t; int i, k;
while (NodeTable[v].adj != NULL) { //删除第v个边链表中所有结点
p = NodeTable[v].adj; k = p->dest; //取邻接顶点k
s = NodeTable[k].adj; t = NULL; //找对称存放的边结点
while (s != NULL && s->dest != v) {
t = s; s = s->link;
}
if (s != NULL) { //删除对称存放的边结点
if (t == NULL) NodeTable[k].adj = s->link;
else t->link = s->link;
delete s;
}
NodeTable[v].adj = p->link; //清除顶点v的边链表结点
delete p; numEdges--; //与顶点v相关联的边数减一
}
numVertices--; //图的顶点个数减1
NodeTable[v].data = NodeTable[numVertices].data; //填补
NodeTable[v].adj = NodeTable[numVertices].adj;
p = NodeTable[v].adj;
while (p != NULL) {
s = NodeTable[p->dest].adj;
while (s!= NULL)
if (s->dest == numVertices) {s->dest = v; break;}
else s = s->link;
}
return true;
};
template<class T, class E>
void Graphlnk<T,E>::DFS(const T& v) {
//从顶点v出发,对图G进行深度优先遍历的主过程
int i, loc, n =NumberOfVertices(); //取图中顶点个数
bool *visited = new bool[n]; //创建辅助数组
for (i = 0; i < n; i++) visited [i] = false; //辅助数组visited初始化
loc = getVertexPos(v);
DFS(loc, visited); //从顶点0开始深度优先搜索
delete [] visited; //释放visited
};
template<class T, class E>
void Graphlnk<T,E>::DFS(int v, bool visited[]) { //子过程
//从顶点位置v出发, 以深度优先的次序访问所有可读入的尚未访问过的顶点。算法中用到一个
//辅助数组visited, 对已访问过的顶点作访问标记。
cout << getValue(v) << ' '; //访问顶点v
visited[v] = true; //顶点v作访问标记
int w = getFirstNeighbor(v); //找顶点v的第一个邻接顶点w
while (w != -1) { //若邻接顶点w存在
if (visited[w] == false) DFS(w, visited);
//若w未访问过, 递归访问顶点w
w = getNextNeighbor(v, w); //取v排在w后的下一个邻接顶点
}
};
#endif;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -