图的两种遍历实现

老规矩,1.你必须明白,什么是图?

2.图是干什么的?

3.图的最基本的物理存储有哪些?

4.遍历图到底是在干什么?有哪些方式?

弄清楚这些,我这里介绍一种,图的邻接表存储方式实现的,完成初始化,输出,和两种遍历方式。上代码,自己看

#include<iostream>
#include<fstream>
#include"sq_Queue.h"
using namespace std;
template <class T1>
struct node{
	int num;
	T1 val;
	node *next;
};

template <class T1,class T2>
struct gpnode{
	T2 data;
	node<T1> *link;
};

template <class T1,class T2>
class Link_GP{
	private:
		int nn;
		gpnode<T1,T2> *gp;
	public:
		Link_GP(){gp=NULL;return;}
		void create_Link_GP(int,T2[]);
		void create_Link_GP(int ,T2[],char *);
		void prt_Link_GP();
		void dfs_Link_GP();
		void bfs_Link_GP();
};

template <class T1,class T2>
void Link_GP<T1,T2>::create_Link_GP(int n,T2 d[]){
	node<T1> *p;
	int k,m;
	T1 v;
	nn=n;
	gp=new gpnode<T1,T2>[nn];
	for(k=0;k<n;k++){
	(gp+k)->data=d[k];
	(gp+k)->link=NULL;
	cout<<"input the "<<k<< "after the node the info:"<<endl;
	cin>>m>>v;
	while(m>=0){
	p=new node<T1>;
	p->num=m;p->val=v;
	p->next=(gp+k)->next;
	(gp+k)->link=p;
	cin>>m>>v;
	}
	}
	return;
}

template <class T1,class T2>
void Link_GP<T1,T2>::create_Link_GP(int n,T2 d[],char *filename){
	node<T1> *p;
	int k,m;
	T1 v;
	ifstream infile(filename,ios::in);
	nn=n;
	gp=new gpnode<T1,T2>[nn];
	for(k=0;k<n;k++){
	(gp+k)->data=d[k];
	(gp+k)->link=NULL;
	infile>>m>>v;
	while(m>=0){
	p=new node<T1>;
	p->num=m;p->val=v;
	p->next=(gp+k)->link;
	(gp+k)->link=p;
	infile>>m>>v;
	}
	}
	return;
}

template <class T1,class T2>
void Link_GP<T1,T2>::prt_Link_GP(){
	node<T1> *q;
	int k;
	for(k=0;k<nn;k++){
	cout<<(gp+k)->data;
	q=(gp+k)->link;
	while(q!=NULL){
	cout<<"-->";
	cout<<q->num<<","<<q->val;
	q=q->next;
	}
	cout<<endl;
	}
	return;
}

template <class T1,class T2>
void Link_GP<T1,T2>::dfs_Link_GP(){
	int k,*mark;
	mark=new int[nn];
	for(k=0;k<nn;k++)
		mark[k]=0;
	for(k=0;k<nn;k++)
		if(mark[k]==0) 
			dfs(gp,k,mark);
	cout<<endl;
	delete mark;
	return ;
}
template <class T1,class T2>
static dfs(gpnode<T1,T2> *q,int k,int *mark){
	node<T1> *p;
	cout<<(q+k)->data<<" ";
	mark[k]=1;
	p=(q+k)->link;
	while(p!=NULL)
	{
	if(mark[p->num-1]==0)
		dfs(q,p->num-1,mark);
	p=p->next;
	}
	return 0;
}

template <class T1,class T2>
void Link_GP<T1,T2>::bfs_Link_GP(){
	int *mark,k;
	sq_Queue<int> q(nn);
	node<T1> *p;
	mark=new int[nn];
	for(k=0;k<nn;k++)
		mark[k]=0;
	for(k=0;k<nn;k++)
	{
		if(mark[k]==0)
		{
			mark[k]=1;
			cout<<gp->data<<" ";
			q.ins_sq_Queue(k);
			while(q.flag_sq_Queue())
			{
				k=q.del_sq_Queue();
				p=(gp+k)->link;
				while(p!=NULL)
				{
				k=p->num-1;
				if(mark[k]==0)
					{
						cout<<(gp+k)->data<<" ";
						mark[k]=1;
						q.ins_sq_Queue(k);
					}
				p=p->next;
				}
			}
		}
	}
cout<< endl;
delete mark;
return;
}
写了两种初始化方式,你可以调用由键盘输入生成图的方式,也可以由文件数据生成图的方式

#include"Link_GP.h"
int main(){
	char d[8]={'A','B','C','D','E','F','G','H'};
	Link_GP<int,char> g;
	g.create_Link_GP(8,d,"f1.txt");
	cout<<"A=1,B=2,C=3,D=4,E=5,F=6,G=7,H=8"<<endl;
	cout<<endl;
	cout<<"图g邻接表:"<<endl;
	g.prt_Link_GP();
	cout<<"DFS :"<<endl;
	g.dfs_Link_GP();
	cout<<"BFS :"<<endl;
	g.bfs_Link_GP();
	return 0;
}
其中,f1.txt就放在当前项目的目录下,输入内容如下:
6 35 8 20 4 55 3 30 -1 -1
7 35 4 45 3 10 -1 -1
2 10 1 30 8 25 6 35 5 30 -1 -1
2 45 1 55 7 55 5 10 -1 -1
4 10 3 30 7 50 6 15 -1 -1
5 15 3 35 8 20 1 35 -1 -1
5 50 4 55 8 15 2 35 -1 -1
1 20 3 25 6 20 7 15 -1 -1
关于初始化:

其实,这个没什么难的,主要你明白图的顺序存储空间结点,和单链表结点,这两种类型,是怎么回事?那么初始化就很自然了。

关于深度遍历:

1.要记住,它是递归的深度遍历。

需要一个辅助数组,来标记它里面的元素是否,被查找过,具体怎么找?

那就是递归的找,找到第一个点之后,找这个点邻接的第一个点,这个点继续找邻接的邻接的第一个点,有点绕,不过,你要首先明白,深度遍历干什么?

假如,不理解递归,也可以这样想:

1.我找一个结点作为当前结点

2.我找它的第一个后件结点,那么现在判断:1)假如它已经标记找到,那么找当前节点的第二个结点

2)没标记过,那么调用这个函数,来遍历它。

就这么简单,因为递归就是一个循环,假如你绕乱了,你就这么简单的逻辑想就好了。

关于广度遍历:

2.千万记住,这个遍历,需要一种数据结构,就是前面说的队列,为什么要用呢?你自己看看广度遍历到底在干什么,相信我就不用说了

1.找一个结点把它进队列

2.把它出队列,然后,找到它依次的后件结点,继续把它们进队列

3.把刚才这些的点,继续出队列,然后同样的把后件进队列

4.重复这个过程,值得标志数组,都为1,说明都找完了

附个结果图,大家看看:


可以这样讲,假如你看不懂,最重要的一点就是,你根本不明白,深度遍历,和广度遍历的过程,它们到底怎么工作的。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值