无向图的深度优先生成树

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

#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是颠倒的 这里我想不通是哪里搞错了 希望知道的朋友帮忙指出

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值