用邻接表存储的无向图的深度优先生成树,树结点用孩子兄弟结构保存。下面是代码
#include<iostream>
#include<string>
using namespace std;
#define MAX_VERTEX_NUM 20
bool visited[20];//用于遍历时辅助使用
bool searched[20];//用于建树时辅助使用
//循环队列模版
template<class T>
class My_queue;
template<class T>
class Node
{
private:
T data;
Node<T> *next;
public:
Node()
{
next=0;
}
Node(T d)
{
data=d;
next=0;
}
friend My_queue<T>;
};
template<class T>
class My_queue
{
private:
Node<T> *tail;
public:
My_queue()
{
tail=new Node<T>();
tail->next=tail;
}
bool empty()
{
return (tail->next==tail);
}
void push(T d)
{
Node<T> *p=new Node<T>(d);
p->next=tail->next;
tail->next=p;
tail=p;
}
T front()
{
if(empty())
{
cout<<"queue is empty!"<<endl;
exit(0);
}
Node<T> *p=tail->next;
T data=p->next->data;
return data;
}
void pop()
{
Node<T> *p=tail->next;
Node<T> *q=p->next;
p->next=q->next;
if(q==tail)
tail=p;
delete q;
}
};
class ALGraph;
class CS_Tree;
//树结点
class CSnode
{
string data;
CSnode *firstchild;
CSnode *nextsibling;
friend class CS_Tree;
friend class ALGraph;
};
//树类定义
class CS_Tree
{
public:
void PreRoot_Traverse(CSnode *T) //先根遍历
{
if(T)
{
cout<<T->data<<" ";
PreRoot_Traverse(T->firstchild);
PreRoot_Traverse(T->nextsibling);
}
}
void PostRoot_Traverse(CSnode *T) //后根遍历
{
if(T)
{
PostRoot_Traverse(T->firstchild);
cout<<T->data<<" ";
PostRoot_Traverse(T->nextsibling);
}
}
void LevelOrder_Traverse(CSnode *T) //层次遍历
{
My_queue<CSnode *> q;
CSnode *t;
q.push(T);
do
{
t=q.front();
do
{
cout<<t->data<<" ";
if(t->firstchild)
q.push(t->firstchild);
t=t->nextsibling;
}while(t);
q.pop();
}while(!q.empty());
}
};
class VNode;
//表结点
class ArcNode
{
public:
int adjvex;
ArcNode *nextarc;
friend class VNode;
};
class ALGraph;
//头结点
class VNode
{
string data;
ArcNode *firstarc;
friend class ALGraph;
};
class ALGraph
{
private:
VNode vertices[MAX_VERTEX_NUM];
int vexnum;
int arcnum;
static int VEX_NUM; //统计输出顶点数目,节省时间
public:
void CreateUDG_ALG()
{
//采用邻接表构造无向图G
string v1,v2;
int i,j,k;
cout<<"输入顶点数和边数:";
cin>>vexnum>>arcnum;
cout<<"输入顶点民称:";
for(i=0;i<vexnum;i++)
{
cin>>vertices[i].data;
vertices[i].firstarc=NULL;
}
//输入各弧并构造邻接表
for(k=0;k<arcnum;k++)
{
cout<<"输入边所对应的两个顶点:";
cin>>v1>>v2;
i=Locate_Vex(v1);
j=Locate_Vex(v2);
while(i<0|| i>vexnum-1 || j<0 || j>vexnum-1)
{
cout<<"结点位置输入错误,重新输入: ";
cin>>v1>>v2;
i=Locate_Vex(v1);
j=Locate_Vex(v2);
}
ArcNode *p=new ArcNode;
p->adjvex=j;
p->nextarc=vertices[i].firstarc;
vertices[i].firstarc=p;
ArcNode *q=new ArcNode;
q->adjvex=i;
q->nextarc=vertices[j].firstarc;
vertices[j].firstarc=q;
}
}
int Locate_Vex(string v) //返回顶点在数组中的位置
{
for(int k=0;vertices[k].data!=v;k++);
return k;
}
void DFS_Traverse() //深度优先遍历
{
VEX_NUM=0;
int i,k;
for(i=0;i<vexnum;i++)
visited[i]=false;
for(k=0;k<vexnum;k++)
if(!visited[k])
DFS(k);
}
void DFS(int v)
{
visited[v]=true;
cout<<vertices[v].data<<" ";
VEX_NUM++;
if(VEX_NUM==vexnum)
return;
ArcNode *p;
int w;
for(p=vertices[v].firstarc;p;p=p->nextarc)
{
w=p->adjvex;
if(!visited[w])
DFS(w);
}
}
//在建立深度优先生成树之前,先将v号位置的顶点给根节点T
CSnode *Pre_Tree(int v,CSnode *T)
{
T=new CSnode;
T->data=vertices[v].data;
return T;
}
void DFS_Tree(int v,CSnode *&T)
{
/*---------------------------------------------/
//深度优先生成树,从v位置开始建立以T为根节点的树 //
//如果在这里面才进行第一个结点给根结点,那么 //
//在递归过程中会出现错误,所以才在进入建树前 //
//先将v号结点给根节点 //
/------------------------------------------*///
T->firstchild=T->nextsibling=NULL;
searched[v]=true;
bool first=true;//判断是否为v的第一个未访问尚的邻接结点
int w;
CSnode *t,*q;
ArcNode *f;
for(f=vertices[v].firstarc;f;f=f->nextarc)
{
w=f->adjvex;
if(!searched[w])
{
q=new CSnode;
q->data=vertices[w].data;
q->firstchild=q->nextsibling=NULL;
if(first)
{
T->firstchild=q;
first=0;
}
else
t->nextsibling=q;
t=q;
DFS_Tree(w,t);
}
}
}
};
int ALGraph::VEX_NUM=0;
int main()
{
CSnode *T;
CS_Tree tree;
ALGraph G;
G.CreateUDG_ALG();
cout<<"深度优先遍历图为:";
G.DFS_Traverse();
cout<<endl;
for(int i=0;i<20;i++)
searched[i]=false;
cout<<"输入要从第几号顶点开始建立深度优先生成树:";
int v;
cin>>v;
T=G.Pre_Tree(v,T);
cout<<"____建立深度优先生成树____"<<endl;
G.DFS_Tree(v,T);
cout<<"____建树完成____"<<endl;
cout<<"生成树的先根遍历为:";
tree.PreRoot_Traverse(T);
cout<<endl;
cout<<"生成树的后根遍历为:";
tree.PostRoot_Traverse(T);
cout<<endl;
cout<<"生成树的层次遍历为:";
tree.LevelOrder_Traverse(T);
cout<<endl;
return 0;
}
测试结果:
输入顶点数和边数:9 15
输入顶点民称:v1 v2 v3 v4 v5 v6 v7 v8 v9
输入边所对应的两个顶点:v1 v6
输入边所对应的两个顶点:v1 v7
输入边所对应的两个顶点:v1 v2
输入边所对应的两个顶点:v2 v7
输入边所对应的两个顶点:v2 v3
输入边所对应的两个顶点:v6 v5
输入边所对应的两个顶点:v6 v9
输入边所对应的两个顶点:v7 v9
输入边所对应的两个顶点:v7 v8
输入边所对应的两个顶点:v3 v8
输入边所对应的两个顶点:v3 v4
输入边所对应的两个顶点:v9 v5
输入边所对应的两个顶点:v9 v8
输入边所对应的两个顶点:v8 v4
输入边所对应的两个顶点:v5 v4
深度优先遍历图为:v1 v2 v3 v4 v5 v9 v8 v7 v6
输入要从第几号顶点开始建立深度优先生成树:0
____建立深度优先生成树____
____建树完成____
生成树的先根遍历为:v1 v2 v3 v4 v5 v9 v8 v7 v6
生成树的后根遍历为:v7 v8 v6 v9 v5 v4 v3 v2 v1
生成树的层次遍历为:v1 v2 v3 v4 v5 v9 v8 v6 v7
Press any key to continue
按照上面的输入生产的无向图和生成树分别为:
红色路线就是深度优先生成树的过程
按照生成树的层次遍历和先根遍历
树的中序遍历应该是 v7 v8 v9 v6 v5 v4 v3 v2 v1 但是输出结果那里 v9 和v6是颠倒的 这里我想不通是哪里搞错了 希望知道的朋友帮忙指出