无向图DFS+BFS(不全)

这里
图可以看成有n个结点的树。

DFS,BFS
都是看这个结点的问题

两个指针:左孩子和右孩子

这里用指针数组的形式存
*child[2]
表示有两个指针,每一个指针指向一个结点。

在这里插入图片描述DFS=====前序遍历
在这里插入图片描述
这里看邻接表图
DFS(p->dest)
表示到相邻的结点访问,
递归找相邻结点的相邻结点访问。
直到为空
用int v 的原因是找数组下标比较容易,且数组的类型可能改变,顶点的值类型会变,这里提高代码的重用性。
P=p->link 是指向后找结点,找到下一个相邻结点。

先找完一串(从头连到尾,不分支),再找另外的相邻结点

在这里插入图片描述

邻接矩阵实现方式
还不完整

#include<iostream>
#include<queue>
using namespace std;

//图的邻接矩阵模式
extern const int maxWeight=9999;
const int maxSize = 100;
//邻接矩阵存储的图的类定义(无向图)
template <class T, class E>
class Graphmtx 				//图的邻接矩阵类定义
{
public:
	 Graphmtx(int sz);						//构造函数
	~Graphmtx()										//析构函数
	{
		delete[]VertexList;
		delete[]Edge;
	}
	T getValue(int i)								//取顶点i的值, i不合理返回0
	{
		return i >= 0 && i < numVertices ? VertexList[i] : 0;
	}
	
	void DFS(Graphmtx<T, E> &G, int v);
	void BFS(Graphmtx<T, E>& G, int k);
	void locata( T& vex1, T& vex2, int& m, int& n);
	void getGraphmtx();
private:
	int maxVertices;   //图中最大顶点数
	int numEdges;
	int numVertices;
	int getVertexPos(T vertex) //找到顶点的位置。可以优化成散列的方式找该顶点,效率更高
	{
		for (int i = 0; i < numVertices; i++)
		{
			if (VertexList[i] == vertex) return i;
		}
		return -1;
	}
	T* VertexList; 	 //顶点表
	E** Edge;		 //邻接矩阵, 数组的元素值为两个顶点之间的权值。
	bool *visited;   //遍历标记
};


//构造函数
template <class T, class E>
Graphmtx<T, E>::Graphmtx(int sz)
{
	int i = 0, j = 0;
	maxVertices = sz;
	numVertices = sz;  //初始化顶点数为0
	numEdges =0;     
	VertexList = new T[maxVertices];  //顶点只需要一维的矩阵存就可以。
	cout << "输入顶点的值: " << endl;
	for (i = 0; i <numVertices; i++)
	{
		cin >> VertexList[i];
	}
	cout << "输入边的数量" << endl;
	cin >> numEdges;
	Edge = (int**) new int* [maxVertices];		//创建邻接矩阵数组
	visited = new bool[maxVertices];
	for (i=0;i< maxVertices;i++)
	{
		visited[i] = false;
	}
	for (i = 0; i < maxVertices; i++)
	{
		Edge[i] = new int[maxVertices];
	}
	for (i = 0; i < maxVertices; i++)//浪费空间的做法,需要一开始就开很大的空间。
	{
		for (j = 0; j < maxVertices; j++)
		{
			Edge[i][j] = (i == j) ? 0 : maxWeight;  //除了对角线为0,其余都是无穷大(权值)
		}
	}
	getGraphmtx();
}
//创建图(以邻接矩阵的方式)
//通过结点信息(A,B,C,D之类)来查找对应矩阵下标
/*********************确定边在矩阵的位置*********************/
template <class T, class E>
void Graphmtx<T, E>::locata( T& vex1, T& vex2, int& m, int& n)
{
	for (int i = 0; i < maxVertices; i++)
	{
		if (vex1 == VertexList[i])
			m = i;
		if (vex2 == VertexList[i])
			n = i;
	}
}
/*********************创建图对应的邻接矩阵************************/
template <class T, class E>
void Graphmtx<T, E>::getGraphmtx()
{
	//根据输入的两个顶点,来更新矩阵的值(如输入A,B表示从A到B有一条边,就更新矩阵相应位置的值为1)
	for (int i = 1; i <= numEdges; i++)
	{
		T vex1, vex2; //接受输入的两个顶点,来表示从vex1到vex2这条边
		cout << "请输入边的信息(形如A B,表示从A到B的一条边):";
		cin >> vex1 >> vex2;
		int m=0, n=0;        //m和n是用来接受vex1和vex2所在的下标值,好据此更新矩阵相应位置的值
		locata( vex1, vex2, m, n);
		Edge[m][n] = 1;
		Edge[n][m] = 1;//无向图邻接矩阵对称,少掉这句代码就是有向图的邻接矩阵了
	}
}

template <class T, class E>
void Graphmtx<T, E>::DFS(Graphmtx<T, E> &G, int v) //输入图,和当前顶点的位置
{
	int j = 0;
	G.visited[v] = true;
	cout << G.VertexList[v]<<"-> ";
	for (j = 0; j < G.numVertices; j++)
		if (G.Edge[v][j]==1 && !visited[j])
			DFS(G, j);
}

//BFS用队列
//图可以看成n叉树,每一层都可以有n个子结点
//每次调用函数前都要设置visited矩阵为0
template <class T, class E>
void Graphmtx<T, E>::BFS(Graphmtx<T, E>& G, int k) //输入图,和当前顶点的位置
{
	int i = 0;
	for (i = 0; i < maxVertices; i++)
	{
		visited[i] = false;
	}
	queue <int> q;
	q.push(k);
	G.visited[k]= 1;
	i = 0;
	while (!q.empty()) 
	{
		i = q.front();
		q.pop();
		cout << G.VertexList[i] << "-> ";
		for (int j = 0; j < G.numVertices; j++) {
			if (G.Edge[i][j] == 1 && G.visited[j] == 0)//把所有子结点入队(或者理解为把所有相邻结点且未访问过的入队)
			{
				G.visited[j] = 1;                                                         
				q.push(j);                                                            
			}
		}
	}
}

邻接表的方式

const int DefaultVertices = 30;//默认最大顶点数

//边结点,下一个顶点的位置
template<class T,class E>//T为顶点名字
struct Edge {
	int dest;     //边的另一个顶点的位置
	E cost;     //边上的权值
	Edge<T, E>* link;            //这个点的下一条边
	Edge() { dest = -1; cost = 0; link = NULL; }
	Edge(int num, E weight) { dest = num; cost = weight; link = NULL; }
};

//顶点
template<class T,class E>//T为数据
struct Vertex {
	T data;                  //顶点名字
	Edge<T,E>* adj;           //边链表的头指针
	Vertex() {};
};

//图
template<class T, class E>         //T为顶点名字
class Graph
{
public:
	int maxVertices;               //图中最大顶点数
	int numEdges;                 //当前边数
	int numVertices;              //当前顶点数
	bool* visited;                // 成员属性 辅助数组
	Vertex<T,E>* NodeTable;       //顶点表(各边链表的头指针)
	Graph(int sz);
	~Graph();
	int getVertexPos(T vetrex) {//给出顶点vetrex在图中的位置,可以改成散列的方式
		for (int i = 0; i < numVertices; i++) {
			if (NodeTable[i].data == Vertex)return i;
		}
		return -1;
	}
	void CreateNodeTable();
	void DFS(int v);
	void BFS();
};

template<class T, class E>
Graph<T,E>::Graph(int sz ) {//初始化
	maxVertices = sz; numVertices = 0; numEdges = 0;
	NodeTable = new Vertex<T,E>[maxVertices];//创建顶点表数组
	visited = new bool[sz];
	int i;
	cout << " 请输入结点数 :" << endl;
	cin >> numVertices;
	if (NodeTable == NULL||visited == NULL)
	{
		cerr << "存储分配错误!" << endl;
		exit(0);
	}
	for (i = 0; i < maxVertices; i++) {
		NodeTable[i].adj = NULL;//边链表头指针赋空
	}
	for (i = 0; i < numVertices; i++)
	{
		visited[i] = false;
	}
	CreateNodeTable();
}

template<class T, class E>
Graph<T, E>::~Graph() {
	for (int i = 0; i < numVertices; i++)
	{
		Edge<T, E>* p = NodeTable[i].adj; //作为工作指针,记头结点
		//每一个顶点都要删除后面连的链表
		while (p != NULL)
		{
			NodeTable[i].adj = p->link;
			delete p;
			p = NodeTable[i].adj;
		}
	}
	delete[] NodeTable;
}

template<class T, class E>
void Graph<T, E>::CreateNodeTable()
{
	int n=0, j=0, i=0, m=0;
	Edge<T, E>* p;
	cout << "输入结点个数: " << endl;
	cin >> n;
	for (i = 0; i < n; i++)
	{
		NodeTable[i].adj = 0;
		cout << "输入该结点的值" << endl ;
		cin >> NodeTable[i].data;
		cout << "输入相邻的结点个数 : " << endl;
		cin >> m; //建立的链表的长度
		for (j = 0; j < m; j++)
		{
			p = new Edge<T, E>;
			cout << "输入连接点的 数组下标的位置: " << endl;
			cin >> p->dest;  //输入连接点的位置
			p->link = NodeTable[i].adj;
			NodeTable[i].adj = p;
		}
	}
}

//遍历
//DFSk=====类似前序遍历,
template<class T, class E>
void Graph<T, E>::DFS(int v)                   //v表示起点
{
	Edge<T, E> *p;
	visited[v] = true;
	cout << NodeTable[v].data<<" -> "; 
	p = NodeTable[v].adj;
	while (p != 0)
	{
		if (!visited[p->dest])
		DFS(p->dest);
		p = p->link;
	}
}


//BFS====层次遍历
//不需要初始值
template<class T, class E>
void Graph<T, E>::BFS()
{
	int v=0;  //根结点的下标
	Edge<T, E>* p;
	queue<int> qu;//定义一个队列
	cout << "输入一个出发点的位置:" << endl;
	cin >> v; //
	qu.push(v);
	visited[v] = true; //这里表示入列
	while (!qu.empty())
	{
		v = qu.front(); //取队头元素
		qu.pop();      //弹出队头元素
		cout << NodeTable[v].data<<" -> ";
		p = NodeTable[v].adj;
		//找邻接点
		while (p != 0)
		{
			qu.push(p->dest);
			p = p->link;
		}
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值