图的十字链表表示的c++实现

本文介绍了一种使用十字链表实现有向图的数据结构,并通过深度优先搜索(DFS)遍历该图。文章详细解释了VexNode和ArcNode类的设计,以及如何在AdjList类中实现DFS算法来遍历生成树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
using namespace std;

class VexNode;
class ArcNode;
typedef int VEXID;

#define MAXVEXNUM 1000

// 编程错误:函数的顺序写错,入s->v写成v->s
// 一定要有无参的构造函数且要初始化所有成员,不然disaster

class VexNode
{
	friend class AdjList;
	friend class ArcNode;
	friend class JunkSmsFilter;
public:
	VexNode();
	VexNode(VEXID);	
private:
    VEXID vexname;
	int inDegree;
	int outDegree;
	ArcNode* firstInArc;  //邻接表只是存一个arc,而十字链表存两个
	ArcNode* firstOutArc;  //邻接表只是存一个arc,而十字链表存两个
	//firstInArc为横向链表的头指针,firstInArc为纵向链表的头指针
};
VexNode::VexNode()
{     
	  vexname=0;
	  inDegree=0;
	  outDegree=0;
	  firstInArc=NULL;
      firstOutArc=NULL;
	  firstInArc=NULL;
      firstOutArc=NULL;

}
VexNode::VexNode(VEXID id)
	{ vexname=id;
	  inDegree=0;
	  outDegree=0;
	  firstInArc=NULL;
      firstOutArc=NULL;
	}
class ArcNode
{
	friend class AdjList;
	friend class JunkSmsFilter;
public:
	ArcNode();
	ArcNode(VEXID mdest,VEXID msrc);	
private:
	VEXID dest;  // 标示弧指向的那个顶点,比邻接表多出一个顶点
    VEXID src;  // 标示弧指向的那个顶点,比邻接表多出一个顶点
	int weight; // 有多少个边
	ArcNode* nextArc_comSrc;//十字链表的横向链接出度边
	ArcNode* nextArc_comDes;//十字链表的纵向链接出度边
};
ArcNode::ArcNode()
{

   nextArc_comSrc=NULL;
   nextArc_comDes=NULL;
}
ArcNode::ArcNode(VEXID msrc,VEXID mdest)
{
   dest=mdest;
   src=msrc;
   weight=1;
   nextArc_comSrc=NULL;
   nextArc_comDes=NULL;
}

class AdjList
{
public:
	AdjList();
	int getVexIndegree(VEXID);
	int getVexOutdegree(VEXID);
	int getSingleDLinkDestNum(VEXID);
	bool addDLink(VEXID,VEXID);
	bool existDArc(int sendId,int revId);
	void appendDWeight(int i,int j,int weight);
	void DFS(VEXID);
	void DFSTraverse(VEXID);
    void BFS(VEXID);
	void BFSTraverse(VEXID);
	bool existOutArc(int p);
    bool existInArc(int p);
	int locateVexById(VEXID sendId);
	int getDArcWeight(int,int);
protected:
	int vexnum;
	bool visited[MAXVEXNUM];
	VexNode vexList[MAXVEXNUM];
};

int AdjList::getDArcWeight(int s,int v)
{
   ArcNode* ptemp=vexList[s].firstOutArc;
			ArcNode* pparent=ptemp;
			while(ptemp!=NULL)
			{
				if((ptemp->dest)==v) 
				{
					return ptemp->weight;	
				}
				pparent=ptemp;
				ptemp=ptemp->nextArc_comSrc;
			}

}
AdjList::AdjList()
{

}

void AdjList::DFS(VEXID svex)//只能遍历一颗生成树,无法遍历生成森林
{
	int ivex=locateVexById(svex);
	ArcNode* arcIter=vexList[ivex].firstOutArc;
	cout<<"starting from-vex- to"<<svex<<"-";
	//递归出口的另一种形式是把递归放在分支内部
    while(arcIter!=NULL)
	{
		cout<<"-vex"<<arcIter->dest<<"-";// 在递归前输出,这点很重要
		DFS(arcIter->dest);//递归放在while内部则while执行下一轮前递归,故为深度优先
		arcIter=arcIter->nextArc_comDes;//递归后才执行广度操作 		
	}
}

void AdjList::DFSTraverse(VEXID svex)// 遍历生成森林
{
    for(int i=1;i<MAXVEXNUM;i++) visited[i]=false;
	for(int i=1;i<MAXVEXNUM;i++) 
	{
		if(visited[i]==false)
		{
			DFS(vexList[i].vexname);
		}
	}	
}
void AdjList::BFS(VEXID)
{

}
void AdjList::BFSTraverse(VEXID)
{



}

bool AdjList::existDArc(int isrc,int ides)
{
	cout<<"inside existDarc:"<<endl;
	ArcNode* ptemp=vexList[isrc].firstOutArc;
    cout<<"get arc pointer ok:"<<endl;
	while(ptemp!=NULL)
	{
		cout<<"inside existDarc: while"<<endl;
		if((ptemp->dest)==ides) 
		{
			cout<<"inside existDarc: exit Darc"<<endl;
			return true;
		}
		ptemp=ptemp->nextArc_comSrc;
	}
    cout<<"inside existDarc:no Darc"<<endl;
	return false;
}

bool AdjList::existOutArc(int isrc)
{
	if(vexList[isrc].firstOutArc==NULL) return false; 
	return true;
}
bool AdjList::existInArc(int idest)
{
   if(vexList[idest].firstInArc==NULL) return false;
   return true;
}

int AdjList::locateVexById(VEXID sendId)
{
	return sendId;
}
void AdjList::appendDWeight(int i, int j, int paraweight)
{
            ArcNode* ptemp=vexList[i].firstOutArc;
			ArcNode* pparent=ptemp;
			while(ptemp!=NULL)
			{
				if((ptemp->dest)==j) 
				{
					ptemp->weight+=paraweight;
					return;
				}
				pparent=ptemp;
				ptemp=ptemp->nextArc_comSrc;
			}
			if(ptemp==NULL) throw "append Weight null error!";
			
	
}

int AdjList::getSingleDLinkDestNum(int id)
{
//从id出去的边指向的顶点没有回边
    int num=0;	
	ArcNode* ptemp=vexList[id].firstOutArc;
	ArcNode* pparent=ptemp;
			while(ptemp!=NULL)
			{
				pparent=ptemp;
				if(getDArcWeight(ptemp->dest,id)==0) 
				{   cout<<"发现没有回边的点"<<endl;
					num++;
				}
				ptemp=ptemp->nextArc_comDes;
			}	
	        return num;
}
bool AdjList::addDLink(VEXID sendId,VEXID revId)
{
	cout<<"going to add link now inside addDlink"<<endl;
	int i=locateVexById(sendId);
	int j=locateVexById(revId);
    
	

	if(!existDArc(sendId,revId))  //如果不存在有向边
	{
		cout<<"going to creat new arc"<<endl;
		ArcNode* pNewArc=new ArcNode(sendId,revId);
        cout<<"creat new arc ok"<<endl;
		cout<<endl<<"no directed graph from "<<i<<" to "<<j<<" Now"<<endl;
		
		if(!existOutArc(i)) //增加i的出边链表
		{
			cout<<"增加i的出边链表"<<endl;
			vexList[i].firstOutArc=pNewArc;
		}
		else  // i已经有出边了
		{
			ArcNode* ptemp=vexList[i].firstOutArc;
			ArcNode* pparent=ptemp;
			while(ptemp!=NULL)
			{
				pparent=ptemp;
				ptemp=ptemp->nextArc_comSrc;
			}
			pparent->nextArc_comSrc=pNewArc;
		}
	    if(!existInArc(j)) //增加i的入边链表
		{
			vexList[j].firstInArc=pNewArc;
		}
		else
		{
			ArcNode* ptemp=vexList[i].firstInArc;
			ArcNode* pparent=ptemp;
			while(ptemp!=NULL)
			{
				pparent=ptemp;
				ptemp=ptemp->nextArc_comDes;
			}
			pparent->nextArc_comDes=pNewArc;

		}
  
	}//
	else
	{
		cout<<endl<<"ARC"<<i<<" to "<<j<<" Now IS"<<endl;
		appendDWeight(i,j,1);
	}
	return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值