将军莫虑,且看此图算法实现

简介: 将军莫虑,且看此图算法实现

图的表示一般有邻接列表和邻接矩阵,我学术不精,偏爱邻接列表

邻接表结构的定义

#define MAX_SIZE 1024
typedef struct _EdgeNode    //与节点连接的边的定义
{
  int weight;//可有可无的权重这题不需要但我习惯增加权重
  int adjvex;
  struct _EdgeNode* next;
}EdgeNode;
typedef struct _VertexNode   //顶点节点
{
  char data;
  struct _EdgeNode* first;
}VertexNode,AdjList;
typedef struct _AdjListGraph  //图
{
  AdjList* adjList;
  int vex;
  int edge;
}AdjListGraph;

邻接表的初始化

void Init(AdjListGraph& G)
{
  G.adjList = new AdjList[MAX_SIZE];
  G.edge = 0;
  G.edge = 0;
}

邻接表的创建

/*图的创建*/
void Create(AdjListGraph& G)
{
  cout << "请输入该图的顶点数以及边数" << endl;
  cin >> G.vex >> G.edge;
  cout << "请输入相关顶点" << endl;
  for (int i = 0; i < G.vex; i++)
  {
    cin >> G.adjList[i].data;
    G.adjList[i].first = NULL;//就是这个地方出了问题关键
  }
  char a1, a2;//保存输入的顶点的字符
  int i1, i2;//保存顶点在数组中的下标
  cout << "请输入相关联边的顶点" << endl;
  for (int i = 0; i < G.edge; i++)
  {
    cin >> a1 >> a2;
    i1 = Location(G, a1);
    i2 = Location(G, a2);
    if (i1 != -1 && i2 != -1)//寻找到位置
    {
      EdgeNode* tmp = new EdgeNode;
      tmp->adjvex = i2;
      tmp->next = G.adjList[i1].first;
      G.adjList[i1].first = tmp;
    }
  }
}

邻接表的深度遍历

深度优先遍历思想:

首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;

当没有未访问过的顶点时,则回到上一个顶点,继续试探别的顶点,直到所有的顶点都被访问过。

使用深度优先搜索来遍历这个图的具体过程是:

  1. 首先从一个未走到过的顶点作为起始顶点,比如 A 顶点作为起点。
  2. 沿 A 顶点的边去尝试访问其它未走到过的顶点,首先发现 E 号顶点还没有走到过,于是访问 E 顶点。
  3. 再以 E 顶点作为出发点继续尝试访问其它未走到过的顶点,接下来访问 D 顶点。
  4. 再尝试以 D 顶点作为出发点继续尝试访问其它未走到过的顶点。
  5. 但是,此时沿 D 顶点的边,已经不能访问到其它未走到过的顶点,接下来返回到 E 顶点。
  6. 返回到 E 顶点后,发现沿 E 顶点的边也不能再访问到其它未走到过的顶点。此时又回到顶点 A(D->E->A),再以 A 顶点作为出发点继续访问其它未走到过的顶点,于是接下来访问 C 顶点。
  7. 。。。。。。。。。。
  8. 最终访问的结果是 A -> E -> D -> C -> B(答案不唯一)
/*对图上的顶点进行深度遍历*/
void DFS(AdjListGraph& G, int v)
{
  int next = -1;
  if (visited[v]) return;
  cout << G.adjList[v].data << " ";
  visited[v] = true;//设置为已访问
  /*EdgeNode* temp = new EdgeNode;
  temp = G.adjList[v].first;*/
  EdgeNode* temp = G.adjList[v].first;
  while (temp)
  {
    next = temp->adjvex;
    temp = temp->next;
    if(visited[next]==false)
      DFS(G, next);
  }
}
/*对所有顶点进行深度遍历*/
void DFS_Main(AdjListGraph& G)
{
  for (int i = 0; i < G.vex; i++)
    if (visited[i] == false)
      DFS(G, i);
}

邻接表的广度遍历

广度优先遍历思想 :

首先以一个未被访问过的顶点作为起始顶点,访问其所有相邻的顶点;

然后对每个相邻的顶点,再访问它们相邻的未被访问过的顶点,直到所有顶点都被访问过,遍历结束。

/*对图上的顶点进行广度遍历*/
void BFS(AdjListGraph& G, int v)
{
  queue<int> q;
  int cur;
  int next;
  q.push(v);
  while (!q.empty())//队列非空
  {
    cur = q.front();//取队头元素
    if (visited[cur] == false)//当前顶点还没有被访问
    {
      cout << G.adjList[cur].data << " ";
      visited[cur] = true;
    }   
    q.pop();//出队列
    EdgeNode* tp = G.adjList[cur].first;
    while (tp!=NULL)
    {
      next = tp->adjvex;
      tp = tp->next;
      q.push(next);//将第一个邻接点入队
    }
  }
}
/*对所有顶点进行广度遍历*/
void BFS_Main(AdjListGraph& G)
{
  for (int i = 0; i < G.vex; i++)
  {
    if (visited[i] == false)
      BFS(G, i);
  }
}

且看此完整图

#include<iostream>
#include<queue>
using namespace std;
#define MAX_SIZE 1024
typedef struct _EdgeNode    //与节点连接的边的定义
{
  int weight;//可有可无的权重这题不需要但我习惯增加权重
  int adjvex;
  struct _EdgeNode* next;
}EdgeNode;
typedef struct _VertexNode   //顶点节点
{
  char data;
  struct _EdgeNode* first;
}VertexNode,AdjList;
typedef struct _AdjListGraph  //图
{
  AdjList* adjList;
  int vex;
  int edge;
}AdjListGraph;
bool visited[MAX_SIZE];//全局数组,用来记录节点是否已被访问
void Init(AdjListGraph& G)
{
  G.adjList = new AdjList[MAX_SIZE];
  G.edge = 0;
  G.edge = 0;
  for (int i = 0; i < MAX_SIZE; i++)
  {
    visited[i] = false;
  }
}
/*通过顶点对应的字符寻找顶点在图中的邻接点*/
int Location(AdjListGraph& G, char c)
{
  for (int i = 0; i < G.vex; i++)
  {
    if (G.adjList[i].data == c)
      return i;
  }
  return -1;
}
/*图的创建*/
void Create(AdjListGraph& G)
{
  cout << "请输入该图的顶点数以及边数" << endl;
  cin >> G.vex >> G.edge;
  cout << "请输入相关顶点" << endl;
  for (int i = 0; i < G.vex; i++)
  {
    cin >> G.adjList[i].data;
    G.adjList[i].first = NULL;//就是这个地方出了问题关键
  }
  char a1, a2;//保存输入的顶点的字符
  int i1, i2;//保存顶点在数组中的下标
  cout << "请输入相关联边的顶点" << endl;
  for (int i = 0; i < G.edge; i++)
  {
    cin >> a1 >> a2;
    i1 = Location(G, a1);
    i2 = Location(G, a2);
    if (i1 != -1 && i2 != -1)//寻找到位置
    {
      EdgeNode* tmp = new EdgeNode;
      tmp->adjvex = i2;
      tmp->next = G.adjList[i1].first;
      G.adjList[i1].first = tmp;
    }
  }
}
/*对图上的顶点进行深度遍历*/
void DFS(AdjListGraph& G, int v)
{
  int next = -1;
  if (visited[v]) return;
  cout << G.adjList[v].data << " ";
  visited[v] = true;//设置为已访问
  /*EdgeNode* temp = new EdgeNode;
  temp = G.adjList[v].first;*/
  EdgeNode* temp = G.adjList[v].first;
  while (temp)
  {
    next = temp->adjvex;
    temp = temp->next;
    if(visited[next]==false)
      DFS(G, next);
  }
}
/*对所有顶点进行深度遍历*/
void DFS_Main(AdjListGraph& G)
{
  for (int i = 0; i < G.vex; i++)
    if (visited[i] == false)
      DFS(G, i);
}
/*对图上的顶点进行广度遍历*/
void BFS(AdjListGraph& G, int v)
{
  queue<int> q;
  int cur;
  int next;
  q.push(v);
  while (!q.empty())//队列非空
  {
    cur = q.front();//取队头元素
    if (visited[cur] == false)//当前顶点还没有被访问
    {
      cout << G.adjList[cur].data << " ";
      visited[cur] = true;
    }   
    q.pop();//出队列
    EdgeNode* tp = G.adjList[cur].first;
    while (tp!=NULL)
    {
      next = tp->adjvex;
      tp = tp->next;
      q.push(next);//将第一个邻接点入队
    }
  }
}
/*对所有顶点进行广度遍历*/
void BFS_Main(AdjListGraph& G)
{
  for (int i = 0; i < G.vex; i++)
  {
    if (visited[i] == false)
      BFS(G, i);
  }
}
int main()
{
  /*
  AdjList G;
  initAdjList(G);
  creatAdjList(G);
  DFS_main(G);
  */
  AdjListGraph G;
  //初始化
  Init(G);
  //创建图
  Create(G);
  cout << "深度遍历" << endl;
  DFS_Main(G);
  //cout << "广度遍历" << endl;
  //BFS_Main(G);
}

补充

尴尬第一次发表忘记发表结果

相关文章
WK
|
2月前
|
机器学习/深度学习 算法 大数据
鱼群算法
鱼群算法(FSA)是一种基于仿生学的群智能算法,模拟鱼群在水中集群、觅食和逃避捕食的行为,寻找问题空间中的全局最优解。该算法由李晓磊等人于2002年提出,通过初始化鱼群、评估适应度、更新行为和终止条件等步骤进行迭代优化。其优点包括实现简单、全局搜索能力强和自适应性好,但收敛速度较慢且易陷入局部最优。FSA已广泛应用于函数优化、路径规划、图像分割等领域,并有望通过改进性能、结合其他算法及拓展应用领域等方式进一步提升其应用价值。
WK
47 0
|
5月前
|
算法 C++
【c/c++算法】曼哈顿算法简单运用
【c/c++算法】曼哈顿算法简单运用
110 0
|
算法 定位技术
图论的灵魂——带你走进迪杰斯特拉算法的世界
图论的灵魂——带你走进迪杰斯特拉算法的世界
图论的灵魂——带你走进迪杰斯特拉算法的世界
|
算法 JavaScript 前端开发
会一会改变世界的图算法——Dijkstra(狄克斯特拉)算法
狄克斯特拉算法是非常著名的算法,是改变世界的十大算法之一,用于解决【赋权】【有向无环图】的【单源最短路径】问题。
|
存储 算法
【趣学算法】贪心算法、海盗古董装船问题
贪心选择是指原问题的整体最优解可以通过一系列局部最优的选择得到,也就是先做出当前最优的选择,将原问题变为一个相似却规模更小的子问题,而后的每一步都是当前最优的选择。这种选择依赖于已做出的选择,但不依赖于未作出的选择。
|
算法
基础算法练习200题09、水池注水
基础算法练习200题09、水池注水
159 0
基础算法练习200题09、水池注水
|
算法 安全 区块链
白话讲解,拜占庭将军问题
作为服务端开发的同学,你可能听说过Paxos、Raft这类分布式一致性算法,也在工作中使用过ZooKeeper、etcd等工具来解决一致性问题。但你可能不知道,这些算法和工具解决的并不是一致性中最难的问题,要讨论这个最难的问题,这就要追溯到 Leslie Lamport 1982 年发表的著名论文 《拜占庭将军问题》(The Byzantine Generals Problem )上了。
白话讲解,拜占庭将军问题
【算法提高——第三讲(一)】图论(1)
【算法提高——第三讲(一)】图论(1)
【算法提高——第三讲(一)】图论(1)
【算法提高——第三讲(一)】图论(3)
【算法提高——第三讲(一)】图论(3)
【算法提高——第三讲(一)】图论(3)
【算法提高——第三讲(二)】图论(4)
【算法提高——第三讲(二)】图论(4)
【算法提高——第三讲(二)】图论(4)
下一篇
无影云桌面