无向图的深度优先生成树

来源:互联网 发布:js图片上传预览删除 编辑:程序博客网 时间:2024/05/04 17:09

用邻接表存储的无向图的深度优先生成树,树结点用孩子兄弟结构保存。下面是代码

#include<iostream>#include<string>using namespace std;#define MAX_VERTEX_NUM 20bool 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(){//采用邻接表构造无向图Gstring 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号位置的顶点给根节点TCSnode *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;}elset->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  v7Press any key to continue

按照上面的输入生产的无向图和生成树分别为:

红色路线就是深度优先生成树的过程

按照生成树的层次遍历和先根遍历

树的中序遍历应该是 v7 v8 v9 v6  v5 v4 v3 v2 v1 但是输出结果那里 v9 和v6是颠倒的 这里我想不通是哪里搞错了 希望知道的朋友帮忙指出