数据结构:图(十字链表存储 c++实现)

/************************************************************************************
		十字链表结构:主要针对的是有向图进行的存储优化
对于有向图来说,邻接表是有缺陷的。关心了出度问题,想了解入度就必须要遍
历整个图才能知道,反之,逆邻接表解决了入度却不了角出度的情况。有没有可
能把邻接表与逆邻接表结合起来呢?答案是肯定的,就是把它们整合在一起。所
以出现了十字链表结构。
顶点结构:[data | firstin | firstout ]
其中firstin表示入边表头指针,指向该顶点的入边表中的第一个结点
firstout表示出边表头指针,指向该顶点的出边表中的第一个结点。
弧结构:[tailvex | headvex | headlink | taillink]
其中tailevex是指弧起点在顶点表中的下标,headvex类似。headlink是指入边
表指针域,指向终点相同的下一条边,taillink类似。如果是网,可再增加一个
权值域。
**********************************************************************************/
#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 tailvex; //弧头下标
	int headvex;  //弧尾下标
	int weight;  //权值
	ArcType* headlink;  //指向下一个同一弧头的弧
	ArcType* taillink; //指向下一个同一弧尾的弧
}ArcType;
typedef struct  
{
	VertexType data;
	ArcType* firstin; //指向第一条入弧
	ArcType* firstout; //指向第一条出弧

}VertexNode;
typedef VertexNode CrossList[MAXVEXSIZE];

typedef struct  
{
	CrossList crossList; //十字链表
	int iVexNum;
	int iArcNum;  
}CrossGraph;


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

//创建有向图
Status CreateCrossGraph( CrossGraph& G )
{
	cout << "输入顶点个数以及边数:";
	cin >> G.iVexNum >> G.iArcNum;
	cout << "请输入" << G.iVexNum << "个顶点:";
	for ( int i = 0; i < G.iVexNum; ++i )
	{
		cin >> G.crossList[i].data;
		G.crossList[i].firstin = NULL;
		G.crossList[i].firstout = 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->headvex = m;
		pArc->tailvex = n;
		pArc->weight = 0;  //权值暂时不用

		pArc->taillink = G.crossList[m].firstout;//表头插入法
		G.crossList[m].firstout = pArc;

		pArc->headlink = G.crossList[n].firstin;//表头插入法
		G.crossList[n].firstin = pArc;
	}
	return SUCCESS;
}


//求顶点的度,在十字链表中还是挺方便的,因为其是邻接表与逆邻接表的结合体
int GetVertexDegree( const CrossGraph& G, VertexType val )
{
	int m = GetIndexByVertexVal( G, val );  //得到顶点的在顶点表中的索引
	if ( -1 == m )
		return -1;
	
	int TD = 0;
	//先求出度
	ArcType* pArcOut = G.crossList[m].firstout;
	while ( pArcOut )
	{
		++TD;
		pArcOut = pArcOut->taillink;
	}

	//再累加入度
	ArcType* pArcIn = G.crossList[m].firstin;
	while( pArcIn )
	{
		++TD;
		pArcIn = pArcIn->headlink;
	}
	return TD;
}


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

	ArcType* pArc = G.crossList[i].firstout;
	while( pArc )
	{
		int iVex = pArc->tailvex;
		if ( !visited[iVex] )
		{
			DFS( G, iVex );
		}
		pArc = pArc->taillink;
	}
}
void DFSTraverse( const CrossGraph& 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 CrossGraph& 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.crossList[i].data << " ";
			visited[i] = true;
			Q.push( i );
			 
			while ( !Q.empty() )
			{
				int iVex = Q.front();
				Q.pop();

				ArcType* pArc = G.crossList[iVex].firstout;
				while ( pArc )
				{
					int j = pArc->tailvex;
					if ( !visited[j] )
					{
						cout << G.crossList[j].data << " ";
						visited[j] = true;
						Q.push(j);
					}
					pArc = pArc->taillink;
				}
			}

		}
	}
}


//销毁图
void DestroyGraph( CrossGraph& G )
{
	for ( int i = 0; i < G.iVexNum; ++i )
	{
		ArcType* pArc = G.crossList[i].firstout;
		while( pArc )
		{
			ArcType* q = pArc;
			pArc = pArc->taillink;
			delete q;
		}
		G.crossList[i].firstout = NULL;
		G.crossList[i].firstin = NULL;
	}
	G.iVexNum = 0;
	G.iArcNum = 0;
}


int main()
{
	//创建有向图
	CrossGraph 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;

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


	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值