数据结构:图(邻接多重表存储 c++实现)

/***********************************************************************************************
                         邻接多重表结构:主要针对的是无向图进行的存储优化
如果我们在无向图的应用中,关注的重点是顶点,那么邻接表是不错的选择,但
如果我们更关注边的操作,比如对已访问过的边做标记,删除某一条边等操作,
那就意味着,需要找到这条边的两个边表结点进行操作,这其实还是比较麻烦的
。因此,我们也依照十字链表的方式,对表结点进行一下改造:
                        [ ivex | ilink | jvex | jlink]
其中ivex和jvex是与某条边依附的两个顶点在顶点表中下标。ilink指向依附点
ivex的下一条边,jlink指向依附点jvex的下一条边,这就是邻接多重表结构。
*************************************************************************************************/
#include <iostream>
#include <string>
#include <queue>
using namespace std;

#define MAXVEXSIZE 10
#define SUCCESS 1
#define UNSUCCESS 0
typedef int Status;
int visited[MAXVEXSIZE];  //指示顶点是否被访问


typedef string VertexType;  //顶点类型
typedef struct ArcType  
{
	int ivex; //该弧依附的两点的位置
	int jvex;  //
	int weight;  //权值
	ArcType* ilink;  //分别指向依附该弧的下一条弧
	ArcType* jlink; 
}ArcType;
typedef struct  
{
	VertexType data;
	ArcType* firstArc; //指向第一条弧

}VertexNode;
typedef VertexNode MulAdjList[MAXVEXSIZE];

typedef struct  
{
	MulAdjList mulAdjList; //多重邻接表
	int iVexNum;
	int iArcNum;  
}MulAdjGraph;


//由顶点值得到顶点索引
int GetIndexByVertexVal( const MulAdjGraph& G, VertexType val )
{
	for ( int i = 0; i < G.iVexNum; ++i )
	{
		if ( val == G.mulAdjList[i].data )
			return i;
	}
	return -1;
}

//创建无向图
Status CreateCrossGraph( MulAdjGraph& G )
{
	cout << "输入顶点个数以及边数:";
	cin >> G.iVexNum >> G.iArcNum;
	cout << "请输入" << G.iVexNum << "个顶点:";
	for ( int i = 0; i < G.iVexNum; ++i )
	{
		cin >> G.mulAdjList[i].data;
		G.mulAdjList[i].firstArc = NULL;
	}

	cout << "请输入由两点构成的边(" << G.iArcNum << "条):";
	for ( int i = 0; i < G.iArcNum; ++i )
	{
		VertexType first;
		VertexType second;
		cin >> first >> second;
		int m = GetIndexByVertexVal( G, first );
		int n = GetIndexByVertexVal( G, second ); 
		if ( m == -1 || n == -1 )
			return UNSUCCESS;

		ArcType* pArc = new ArcType;
		memset( pArc, 0, sizeof(ArcType) );
		pArc->ivex = m;
		pArc->jvex = n;
		pArc->weight = 0;  //权值暂时不用

		pArc->ilink = G.mulAdjList[m].firstArc;//表头插入法
		G.mulAdjList[m].firstArc = pArc;

		pArc->jlink = G.mulAdjList[n].firstArc;//表头插入法
		G.mulAdjList[n].firstArc = pArc;

	}
	return SUCCESS;
}


//求顶点的度
int GetVertexDegree( const MulAdjGraph& G, VertexType val )
{
	int m = GetIndexByVertexVal( G, val );  //得到顶点的在顶点表中的索引
	if ( -1 == m )
		return -1;

	int TD = 0;
	ArcType* pArc = G.mulAdjList[m].firstArc;
	while ( pArc )
	{
		++TD;
		if ( m == pArc->ivex )
			pArc = pArc->ilink;
		else
			pArc = pArc->jlink;
	}
	return TD;
}


//深度优先遍历
void DFS( const MulAdjGraph& G, int i )
{
	cout << G.mulAdjList[i].data << " ";
	visited[i] = true;

	ArcType* pArc = G.mulAdjList[i].firstArc;
	while( pArc )
	{
		int iVex = pArc->jvex;
		if ( !visited[iVex] )
		{
			DFS( G, iVex );
		}
		pArc = pArc->ilink;
	}
}
void DFSTraverse( const MulAdjGraph& G )
{
	for ( int i = 0; i < G.iVexNum; ++i )
	{
		visited[i] = false;
	}

	for ( int i = 0; i < G.iVexNum; ++i )
	{
		if ( !visited[i] )
		{
			DFS( G, i );
		}
	}
}

//广度优先遍历
void BFSTraverse( const MulAdjGraph& G )
{
	for ( int i = 0; i < G.iVexNum; ++i )
	{
		visited[i] = false;
	}

	queue<int> Q;
	for ( int i = 0; i < G.iVexNum; ++i )
	{
		if ( !visited[i] )
		{
			cout << G.mulAdjList[i].data << " ";
			visited[i] = true;
			Q.push( i );

			while ( !Q.empty() )
			{
				int iVex = Q.front();
				Q.pop();

				ArcType* pArc = G.mulAdjList[iVex].firstArc;
				while ( pArc )
				{
					int j = pArc->jvex;
					if ( !visited[j] )
					{
						cout << G.mulAdjList[j].data << " ";
						visited[j] = true;
						Q.push( j );
					}
					pArc = pArc->ilink;
				}
			}

		}
	}
}


//销毁图
void DestroyGraph( MulAdjGraph& G )
{
	for ( int i = 0; i < G.iVexNum; ++i )
	{
		ArcType* pArc = G.mulAdjList[i].firstArc;
		while( pArc )
		{
			ArcType* q = pArc;
			pArc = pArc->ilink;

			int m = q->ivex;
			//在m号顶点下找当前边的前一条边
			ArcType* pmArc = G.mulAdjList[m].firstArc;
			ArcType* pmPreArc = NULL;
			while ( pmArc != q )
			{
				pmPreArc = pmArc;
				if ( m == pmArc->ivex )
				{
					pmArc = pmArc->ilink;
				}
				else 
				{
					pmArc = pmArc->jlink;
				}
			}
			if ( !pmPreArc )
			{
				G.mulAdjList[m].firstArc = q->ilink;
			}
			else
			{
				if ( m == pmPreArc->ivex )
				{
					pmPreArc->ilink = q->ilink;
				}
				else 
				{
					 pmPreArc->jlink = q->ilink;
				}
			}


			int n = q->jvex;
			//在n号顶点下找当前边的前一条边
			ArcType* pnArc = G.mulAdjList[n].firstArc;
			ArcType* pnPreArc = NULL;
			while ( pnArc != q )
			{
				pnPreArc = pnArc;
				if ( n == pnArc->ivex )
				{
					pnArc = pnArc->ilink;
				}
				else 
				{
					pnArc = pnArc->jlink;
				}
			}
			if ( !pnPreArc )
			{
				G.mulAdjList[n].firstArc = q->jlink;
			}
			else
			{
				if ( n == pnPreArc->ivex )
				{
					pnPreArc->ilink = q->jlink;
				}
				else 
				{
					pnPreArc->jlink = q->jlink;
				}
			}
			delete q;
		}
	}
	G.iVexNum = 0;
	G.iArcNum = 0;
}


int main()
{
	//创建有向图
	MulAdjGraph G;
	CreateCrossGraph( G );

	//深度优先遍历图
	cout << "深度优先遍历:" << endl;
	DFSTraverse( G );
	cout << endl << endl;

	//广度优先遍历图
	cout << "广度优先遍历:" << endl;
	BFSTraverse( G );
	cout << endl << endl;

	//结点的度
	cout << "输入求度的结点:";
	VertexType v;
	cin >> v;
	cout << "度为:" << GetVertexDegree( G, v ) << endl;

	cout << "再输入求度的结点:";
	cin >> v;
	cout << "度为:" << GetVertexDegree( G, v ) << endl;

	cout << "再输入求度的结点:";
	cin >> v;
	cout << "度为:" << GetVertexDegree( G, v ) << endl;

	//销毁有向图
	DestroyGraph( G );


	return 0;
}

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值