老规矩,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,说明都找完了
附个结果图,大家看看:
可以这样讲,假如你看不懂,最重要的一点就是,你根本不明白,深度遍历,和广度遍历的过程,它们到底怎么工作的。