数据结构与算法(图)

==引言:==这一次我们来学习数据结构最后一部分,同时也是我觉得最难的一部分——图的学习与应用。
声明:定义都是书中所写。

一.图的定义

定义为:图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
注意:
1.在图中的数据元素我们可以用顶点来表示。
2.图中的任意两个顶点都有可能存在某种关系,我们用边来表示。

二.各种图的定义

1.简单图

定义:在图中,若不存在顶点到其自身的边,且同一条边不重复出现,则称这样的图为简单图。

2.稠密图与稀疏图

定义:有很少条边或弧的图为稀疏图,反之为稠密图。

3.有向图与无向图

(1)有向边

若从顶点Vi到Vj的边有方向,则称这条边为有向边,也叫作弧。一般我们用<>来表示。

(2)无向边

若从顶点Vi到Vj的边没有方向,则称这条边为无向边。一般我们用()来表示。
了解了有向边与无向边的定义,那我们就可以知道有向图与无向图的定义。

三.图的相关术语

1.权

定义:有些图中的边具有相关的数字,这种我们称之为权。
这些带权值的图又称之为网。

2.度

定义:无向图顶点的边数叫做度,有向图的顶点分为入度与出度。

3.连通与环

图中顶点之间存在路径,如果两个顶点存在路径,则称这两个图是连通的。
如果路径从起点出发,最终回到起点位置,我们称为环。

四.图的实现

这里只给出无向图的代码,有向图在就是在有向图的代码上进行细小改动。

1.邻接矩阵

(1)定义

图的邻接矩阵设是用两个数组来存放。一个一维数组存放图中顶点的信息,一个二维数组存放图中边或弧的信息。

(2)无向图的邻接矩阵实现

定义:

struct Tu
{
	char vecs[N];//顶点表 
	int arc[N][N];//边表 
	int numVec,numEdges;//顶点数与边数 
};

实现:

void creat(struct Tu *p)
{
	int i,j,k,w;
	cout<<"请输入顶点数与边数"<<endl;
	cin>>p->numVec>>p->numEdges;
	cout<<"请输入顶点"<<endl; 
	for(i=0;i<p->numVec;i++)
		cin>>p->vecs[i];
	for(i=0;i<p->numVec;i++)//初始化邻接矩阵 
		for(j=0;j<p->numVec;j++)
			p->arc[i][j]=max;
	for(k=0;k<p->numEdges;k++)
	{
		cout<<"请输入行与列,还有权值"<<endl;
		cin>>i>>j>>w;
		p->arc[i][j]=w;
		p->arc[j][i]=p->arc[i][j];//无向图是中心对称的图 
	}
}

完整代码:

#include <iostream>
using namespace std;
#define N 103  //用来表示最大顶点数 
#define max 65536 //用来表示权值最大,也就是正无穷
struct Tu
{
	char vecs[N];//顶点表 
	int arc[N][N];//边表 
	int numVec,numEdges;//顶点数与边数 
};
void creat(struct Tu *p)
{
	int i,j,k,w;
	cout<<"请输入顶点数与边数"<<endl;
	cin>>p->numVec>>p->numEdges;
	cout<<"请输入顶点"<<endl; 
	for(i=0;i<p->numVec;i++)
		cin>>p->vecs[i];
	for(i=0;i<p->numVec;i++)//初始化邻接矩阵 
		for(j=0;j<p->numVec;j++)
			p->arc[i][j]=max;
	for(k=0;k<p->numEdges;k++)
	{
		cout<<"请输入行与列,还有权值"<<endl;
		cin>>i>>j>>w;
		p->arc[i][j]=w;
		p->arc[j][i]=p->arc[i][j];//无向图是中心对称的图 
	}
}
int main()
{
	struct Tu S;
	S.numVec=0;
	S.numEdges=0;
	int j,i;
	creat(&S);
	for(i=0;i<S.numVec;i++)
	{
		for(j=0;j<S.numVec;j++)
		cout<<S.arc[i][j]<<" ";
		cout<<endl;
	}	
	return 0;
}

2.邻接表

(1)定义

在邻接矩阵中,我们发现存在空间浪费问题,并且我们发现创建图的时间复杂度是O(n*n)。有联想到线性表知识,我们决定用链表来实现图。我们把数组与链表相结合的存储方式称之为邻接表。

(2)无向图的邻接表实现

邻接表的插入像极了链表中的头插法。
定义:

#define N 103  //用来表示最大顶点数 
#define max 65536 //用来表示权值最大,也就是正无穷
struct Edge//边表节点 
{
	int adjvex;//邻接域点,存放该点对应下表 
	int weigth;//权值 
	struct Edge *next;//指针域 
};
struct Vec//顶点表节点 
{
	char data;//顶点域 
	struct Edge *first;//边表节点 
};
struct Tu
{
	struct Vec tulist[N];
	int numVec,numEdge;//顶点数与边数 
};

实现:

void creat(struct Tu *p)
{
	int i,j,w,k;
	struct Edge *e;
	cout<<"请输入顶点数与边数"<<endl;
	cin>>p->numVec>>p->numEdge;
	cout<<"请输入顶点信息"<<endl;
	for(i=0;i<p->numVec;i++)
	{
		cin>>p->tulist[i].data;
		p->tulist[i].first=NULL;//将边表置空 
	}
	for(k=0;k<p->numEdge;k++)
	{
		cout<<"请输入行与列,还有权值"<<endl;
		cin>>i>>j>>w;
		e=new(struct Edge);
		e->adjvex=j;
		e->weigth=w;
		e->next=p->tulist[i].first;
		p->tulist[i].first=e;
		
		e=new(struct Edge);
		e->adjvex=i;
		e->weigth=w;
		e->next=p->tulist[j].first;
		p->tulist[j].first=e;
	}
}

完整代码:

#include <iostream>
using namespace std;
#define N 103  //用来表示最大顶点数 
#define max 65536 //用来表示权值最大,也就是正无穷
struct Edge//边表节点 
{
	int adjvex;//邻接域点,存放该点对应下表 
	int weigth;//权值 
	struct Edge *next;//指针域 
};
struct Vec//顶点表节点 
{
	char data;//顶点域 
	struct Edge *first;//边表节点 
};
struct Tu
{
	struct Vec tulist[N];
	int numVec,numEdge;//顶点数与边数 
};
void creat(struct Tu *p)
{
	int i,j,w,k;
	struct Edge *e;
	cout<<"请输入顶点数与边数"<<endl;
	cin>>p->numVec>>p->numEdge;
	cout<<"请输入顶点信息"<<endl;
	for(i=0;i<p->numVec;i++)
	{
		cin>>p->tulist[i].data;
		p->tulist[i].first=NULL;//将边表置空 
	}
	for(k=0;k<p->numEdge;k++)
	{
		cout<<"请输入行与列,还有权值"<<endl;
		cin>>i>>j>>w;
		e=new(struct Edge);
		e->adjvex=j;
		e->weigth=w;
		e->next=p->tulist[i].first;
		p->tulist[i].first=e;
		
		e=new(struct Edge);
		e->adjvex=i;
		e->weigth=w;
		e->next=p->tulist[j].first;
		p->tulist[j].first=e;
	}
}
void out(struct Tu *q)
{
	int n,m,j,k,l,i;
	struct Tu *r;
	struct Edge *s;
	r=q;
	for(i=0;i<r->numVec;i++)
	{
		cout<<"节点数  "<<r->tulist[i].data<<endl;
		if(r->tulist[i].first!=NULL)
		{
			s=r->tulist[i].first;
			while(s!=NULL)
			{
				cout<<"->"<<s->adjvex<<" ";
				cout<<s->weigth;
				s=s->next;
			}
			cout<<endl;
		}
	} 
}
int main()
{
	struct Tu S;
	S.numEdge=0;
	S.numVec=0;
	creat(&S);
	out(&S);	
	return 0;
}

五.后记

由于图的知识点很多,然后还有点难理解,所以这次的图分为两部分,下一部分在进行图遍历的学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风送雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值