数据结构(11)-----图(使用easyX将图还原)

图:图(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个顶点的无向完全图有\frac{n*(n-1)}{2}条边

在有向图中,如果任意两个顶点之间都存在方向互为相反的两条弧,则称该图为有向图完全图。含有n个顶点的有向完全图有n*(n-1)条边。

有很少条边或弧的图称为稀疏图,反之称为稠密图。当边数小于n*\log 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;
}

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值