图:图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
(1)线性表中的数据元素叫元素,树中将数据元素叫结点,在图中数据元素称为顶点。
(2) 图不存在空图的概念,图中至少有一个顶点。
(3)线性表中,相邻的数据元素之间具有线性关系,树结构中,相邻两层的结点具有层次关系,而图中,任意两个顶点之间都能有关系,顶点之间的逻辑关系用边来表示,边集可以是空的。
图的一些概念:
无向边:若顶点Vi到Vj之间的边没有方向,则称为这条边为无向边(Edge),用无序偶对(Vi,Vj)来表示。如果图中任意两个顶点之间的边都是无向边,则称该图为无向图。
有向边:若从顶点Vi到Vj的边有方向,则称为这条边为,也称为弧(Arc)。用有序偶<Vi,Vj>来表示,Vi称为弧尾(Tail),Vj称为弧头(Head)。如果图中任意两个顶点之间的边都是有向边,则称该图为有向图。连接顶点A到D的有向边就是弧,A是弧尾,D是弧头,<A,D>表示弧,注意不能写成<D,A>。如果无向图用()来表示。
在图中,若不存在在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。
在无向图中,如果任意两个顶点之间都存在边,则称该图为无向完全图。含有n个顶点的无向完全图有条边。
在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向图完全图。含有n个顶点的有向完全图有条边。
有很少条边或弧的图称为稀疏图,反之称为稠密图。当边数小于时称为小。
有些图的边或或者弧具有与他相关的数字,这种与图的边或弧相关的数叫做权(Weight)。这些权可以表示从一个顶点到另外顶点的距离或耗费。这种带权的图通常称为网(Network)。
假设有两个图G=(V,{E})和G‘=(V’,{E‘}),如果V’是V的子集且E‘是E的子集,则称G’为G的子图,右边的图时左边图的子图。
图的存储:
图的邻接矩阵存储方式是用两个数组来表示图。一个一维数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。
设图G有n个顶点,则邻接矩阵是一个n*n的方阵(无权图),定义为:
有权图:
代码实现:
画图需要用easyX库。
#include <iostream>
#include <vector>
#include <graphics.h>
#include <conio.h>
using namespace std;
typedef char VertexType;
typedef int EdgeType;
class Point
{
public:
int px;
int py;
};
class Graph
{
public:
void createrGraph();
void setVertexPoint();
void showGraph();
void insertVertex();
void drawGraph();
protected:
vector<VertexType> vertex;
vector<vector<EdgeType>> edge;
vector<Point> vertexPoint;
int vertexCount;
int edgeCount;
int graphFlag;
};
#include "graph.h"
void Graph::createrGraph()
{
cout << "您需要创建一个“无向图(0)”还是“有向图(1)”:";
cin >> graphFlag;
edgeCount = 0;
cout << "请输入图的顶点数:" << endl;
cin >> vertexCount;
cout << "请输入顶点的名称和坐标:" << endl;
VertexType vValue;
Point point;
for (int i = 0; i < vertexCount; ++i)
{
cout << "第" << i + 1 << "个顶点的名称和坐标:" << endl;
cin >> vValue;
cin >> point.px >> point.py;
vertexPoint.push_back(point);
vertex.push_back(vValue);
}
cout << "请输入图的领接矩阵:" << endl;
EdgeType eValue;
vector<EdgeType> ver;
for (int i = 0; i < vertexCount; ++i)
{
for (int j = 0; j < vertexCount; ++j)
{
cin >> eValue;
if (eValue == 1)
{
++edgeCount;
}
ver.push_back(eValue);
}
edge.push_back(ver);
ver.clear();
}
if (graphFlag == 0)
{
edgeCount /= 2;
}
}
void Graph::insertVertex()
{
cout << "请输入新顶点的名称:" << endl;
VertexType vValue;
cin >> vValue;
vertex.push_back(vValue);
cout << "其他"<<vertexCount<<"顶点是否和新顶点是否有联系:" << endl;
EdgeType eValue;
int len = vertexCount;
for (int i = 0; i < len; ++i)
{
cin >> eValue;
edge[i].push_back(eValue);
}
cout << "新顶点和其他" << vertexCount << "顶点是否有联系:" << endl;
vector<EdgeType> ver;
++len;
for (int i = 0; i < len; ++i)
{
cin >> eValue;
ver.push_back(eValue);
++edgeCount;
}
edge.push_back(ver);
++vertexCount;
}
void Graph::showGraph()
{
cout << "共有" << vertexCount << "个顶点:" << endl;
for (int i = 0; i < vertexCount; ++i)
{
cout << vertex[i];
}
cout << endl << "共有" << edgeCount << "条边。" << endl;
cout << "图的领接矩阵为:" << endl;
for (int i = 0; i < vertexCount; ++i)
{
for (int j = 0; j < vertexCount; ++j)
{
cout << edge[i][j] << " ";
}
cout << endl;
}
}
void drawCircle(int x, int y, char ch)
{
int r = 20, rx = x, ry = y;
setfillcolor(RGB(255,128,0));
fillcircle(rx, ry, r);
settextcolor(BLUE);
outtextxy(rx - r / 5, ry - r / 4, ch);
}
void Graph::drawGraph()
{
//初始化屏幕
initgraph(640, 480);
setbkcolor(YELLOW);
cleardevice();
for (int i = 0; i < vertexCount; ++i)
{
int x = vertexPoint[i].px;
int y = vertexPoint[i].py;
drawCircle(x, y, vertex[i]);
//vertexPoint.push_back(point);
}
setlinecolor(RED);
for (int i = 0; i < vertexCount; ++i)
{
for (int j = 0; j < vertexCount; ++j)
{
if (edge[i][j] == 1)
{
line(vertexPoint[i].px, vertexPoint[i].py, vertexPoint[j].px, vertexPoint[j].py);
}
}
}
_getch();
closegraph();
}
int main()
{
Graph g;
g.createrGraph();
g.drawGraph();
return 0;
}