目录
算法逻辑可能并不严谨,欢迎各位大佬批评指正!
一、非递归实现深度优先遍历
1、算法思想
(1)算法思想:
- 首先检查起始顶点的索引是否有效和图是否已经建立。
- 使用栈来实现深度优先搜索,首先将起始顶点入栈,并将起始顶点标记为已访问。
- 循环直到栈为空,每次取出栈顶顶点,打印并访问它的邻接顶点,并将未访问的邻接顶点入栈并标记为已访问。
(2)时间复杂度: O(V + E)
(3)空间复杂度: O(V),其中V是顶点数,E是边数。
2、算法流程图
3、算法
//深度优先
void DFS(int start) {
if (start < 0 || start >= numVertices) {
cout << "起始顶点不在图形中" << endl;
return;
}
if (checkGraphBuilt()) {
vector<bool> visited(numVertices, false);
stack<int> s;
s.push(start);
visited[start] = true;
while (!s.empty()) {
int current = s.top();
s.pop();
if (current < 0 || current >= numVertices) {
continue;
}
printNode(current);
for (auto node : adjList[current]) {
if (!visited[node.dest]) {
s.push(node.dest);
visited[node.dest] = true;
}
}
}
cout << endl;
}
}
二、广度优先遍历
1、算法思想
(1)算法思想:
- 首先检查起始顶点的索引是否有效和图是否已经建立。
- 使用队列来实现广度优先搜索,首先将起始顶点入队,并将起始顶点标记为已访问。
- 循环直到队列为空,每次取出队首顶点,打印并访问它的邻接顶点,并将未访问的邻接顶点入队并标记为已访问。
(2)时间复杂度: O(V + E)
(3)空间复杂度: O(V),其中V是顶点数,E是边数。
2、算法流程图
3、算法
//广度优先
void BFS(int start) {
if (start < 0 || start >= numVertices) {
cout << "起始顶点不在图形中" << endl;
return;
}
if (checkGraphBuilt()) {
vector<bool> visited(numVertices, false);
queue<int> q;
q.push(start);
visited[start] = true;
while (!q.empty()) {
int current = q.front();
q.pop();
if (current < 0 || current >= numVertices) {
continue;
}
printNode(current);
for (auto node : adjList[current]) {
if (!visited[node.dest]) {
q.push(node.dest);
visited[node.dest] = true;
}
}
}
cout << endl;
}
}
三、附检测算法完整程序(含无向图、有向图的构造)
1、操作说明
-
根据菜单指示输入要进行的操作相应的数字
-
输入数字1将会输出已经构造好的无向网。
-
输入数字2将进入键盘输入有向图的操作,输入顶点个数(规定顶点是从0开始的数字,如:顶点个数为4,则顶点分别是0、1、2、3),输入边的起点和终点。
-
输入数字3输出有向图
-
输入数字4输出无向图深度优先非递归遍历结果
-
输入数字5输出无向图广度优先遍历结果
-
输入数字6退出程序
2、测试结果图
- 构建无向网
- 构建有向图、输出邻接表
- 深度优先非递归遍历、广度优先遍
3、完整代码
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
class Graph {
private:
struct Node {
int dest;
Node(int d) : dest(d) {}
};
int numVertices;
vector<vector<int>> adjMatrix;
vector<vector<Node>> adjList;
vector<vector<Node>> adjGraph;
bool isDirected;
bool isGraphBuilt;
public:
Graph() : numVertices(0), isDirected(false), isGraphBuilt(false) {}
//初始化图
void initializeGraph(int n, bool directed) {
numVertices = n;
isDirected = directed;
adjMatrix = vector<vector<int>>(numVertices, vector<int>(numVertices, 0));
adjList = vector<vector<Node>>(numVertices);
adjGraph = vector<vector<Node>>(numVertices);
isGraphBuilt = true;
}
//将边添加到邻接矩阵中
void addEdgeToMatrix(int src, int dest, int weight) {
if (checkGraphBuilt() && checkVertexIndex(src) && checkVertexIndex(dest)) {
if (src <= numVertices && dest <= numVertices) {
adjMatrix[src][dest] = weight;
if (!isDirected) {
adjMatrix[dest][src] = weight;
}
}
else {
cout << "顶点索引越界!" << endl;
}
}
}
//将边添加到邻接表中
void addEdgeToAdjList(int src, int dest) {
if (checkGraphBuilt() && checkVertexIndex(src) && checkVertexIndex(dest)) {
if (src <= numVertices && dest <= numVertices) {
if (!isDirected) {
adjList[src].push_back(Node(dest));
adjList[dest].push_back(Node(src));
}
else {
adjGraph[src].push_back(Node(dest));
}
}
else {
cout << "顶点索引越界!" << endl;
}
}
}
//打印无向网
void printAdjMatrix() {
if (checkGraphBuilt()) {
cout << "无向网邻接矩阵表示:" << endl;
for (int i = 0; i < numVertices; i++) {
for (int j = 0; j < numVertices; j++) {
if (i < numVertices && j < numVertices) {
cout << adjMatrix[i][j] << " ";
}
else {
cout << "顶点索引越界!";
}
}
cout << endl;
}
}
}
//键盘输入有向图
void buildAdjListFromInput() {
if (checkGraphBuilt()) {
int src, dest;
cout << "请输入边的起点和终点 (格式: 起点 终点),输入-1 -1结束输入:" << endl;
while (true) {
cin >> src >> dest;
if (src == -1 && dest == -1) {
break;
}
if (checkVertexIndex(src) && checkVertexIndex(dest) && src <= numVertices && dest <= numVertices) {
addEdgeToAdjList(src, dest);
}
else {
cout << "无效的顶点索引!请重新输入:" << endl;
}
}
}
}
//打印有向图的邻接表
void printAdjList() {
if (checkGraphBuilt()) {
for (int i = 0; i < numVertices; ++i) {
if (checkVertexIndex(i)) {
cout << "顶点 " << i << " 的邻接表: ";
for (auto node : adjGraph[i]) {
if (checkVertexIndex(node.dest)) {
printNode(node.dest);
}
else {
cout << "无效的顶点索引:" << node.dest;
}
}
cout << endl;
}
else {
cout << "无效的顶点索引:" << i << endl;
}
}
}
}
//深度优先
void DFS(int start) {
if (start < 0 || start >= numVertices) {
cout << "起始顶点不在图形中" << endl;
return;
}
if (checkGraphBuilt()) {
vector<bool> visited(numVertices, false);
stack<int> s;
s.push(start);
visited[start] = true;
while (!s.empty()) {
int current = s.top();
s.pop();
if (current < 0 || current >= numVertices) {
continue;
}
printNode(current);
for (auto node : adjList[current]) {
if (!visited[node.dest]) {
s.push(node.dest);
visited[node.dest] = true;
}
}
}
cout << endl;
}
}
//广度优先
void BFS(int start) {
if (start < 0 || start >= numVertices) {
cout << "起始顶点不在图形中" << endl;
return;
}
if (checkGraphBuilt()) {
vector<bool> visited(numVertices, false);
queue<int> q;
q.push(start);
visited[start] = true;
while (!q.empty()) {
int current = q.front();
q.pop();
if (current < 0 || current >= numVertices) {
continue;
}
printNode(current);
for (auto node : adjList[current]) {
if (!visited[node.dest]) {
q.push(node.dest);
visited[node.dest] = true;
}
}
}
cout << endl;
}
}
private:
bool checkGraphBuilt() {
if (!isGraphBuilt) {
cout << "未建立图!" << endl;
return false;
}
return true;
}
bool checkVertexIndex(int index) {
if (index < 0 || index >= numVertices) {
cout << "无效的顶点索引!" << endl;
return false;
}
return true;
}
void printNode(int node) {
cout << "-> " << node;
}
};
int main() {
Graph graph;
int choice;
int numVertices = 0;
bool isDirected = false;
while (1) {
cout << "--------菜单--------" << endl;
cout << "1. 构造无向网" << endl;
cout << "2. 键盘输入有向图" << endl;
cout << "3. 输出邻接表" << endl;
cout << "4. 无向图的深度优先非递归遍历" << endl;
cout << "5. 无向图的广度优先遍历" << endl;
cout << "6. 退出程序" << endl;
cout << "请输入选项:";
cin >> choice;
switch (choice) {
case 1:
numVertices = 4;
isDirected = false;
graph.initializeGraph(numVertices, isDirected);
graph.addEdgeToMatrix(0, 1, 1);
graph.addEdgeToMatrix(0, 2, 2);
graph.addEdgeToMatrix(1, 2, 3);
graph.addEdgeToMatrix(2, 3, 4);
graph.printAdjMatrix();
break;
case 2:
cout << "请输入顶点个数(规定顶点是从0开始的数字,如:顶点个数为4,则顶点分别是0、1、2、3): ";
cin >> numVertices;
isDirected = true;
graph.initializeGraph(numVertices, isDirected);
graph.buildAdjListFromInput();
break;
case 3:
graph.printAdjList();
break;
case 4:
numVertices = 4;
isDirected = false;
graph.initializeGraph(numVertices, isDirected);
graph.addEdgeToAdjList(0, 1);
graph.addEdgeToAdjList(0, 2);
graph.addEdgeToAdjList(1, 2);
graph.addEdgeToAdjList(2, 3);
cout << "深度优先非递归遍历结果:" << endl;
graph.DFS(0);
break;
case 5:
numVertices = 4;
isDirected = false;
graph.initializeGraph(numVertices, isDirected);
graph.addEdgeToAdjList(0, 1);
graph.addEdgeToAdjList(0, 2);
graph.addEdgeToAdjList(1, 2);
graph.addEdgeToAdjList(2, 3);
cout << "广度优先遍历结果:" << endl;
graph.BFS(0);
break;
case 6:
return 0;
default:
cout << "无效的选项!" << endl;
break;
}
}
return 0;
}