• 邻接矩阵实现图的深度优先搜索和广度优先搜索-C++代码


    一、有向图概念:


    • 顶点:有向图的每一个节点
    • 弧:每一条线
      • 弧头:线的起始点
      • 弧尾:线的结束点
    • 出度/入度:
      • 出度:某一顶点发出去的弧的数量;
      • 入度:某一顶点射入的弧的数量

    二、无向图概念:


    • 邻接点:存在一条边连接两个点
    • 边:无向图中的连线;
    • 顶点:图中的节点;
    • 连通图:对于图内每一个顶点都直接或间接存在通往其他顶点的路径;
    • 完全图:图中任一顶点都存在和其他所有顶点的直接连线。边数n(n1)/2n(n-1)/2
    • 生成树:只有最小数量的边连接每一个顶点生成连通图。边数n1n-1(n为顶点个数)

    三、图存储结构:


    1.存储结构分类

    • 邻接矩阵:数组
    • 邻接表:链表-有向图
    • 十字链表:链表-有向图
    • 邻接多重表:链表-无向图
    1.1.邻接矩阵-数组存储
    • 无向图的邻接矩阵是对称矩阵
    • 算法实现
    struct Node
    {
        顶点索引;
        顶点数据;一维数组
    }
    struct Map
    {
        顶点数组;//存储所有顶点信息
        邻接矩阵;//存储顶点间连接关系。二维数组
    }
    
    1.2.邻接表-
    • 邻接表:
      顶点表示方法:
    顶点索引 出弧链表头指针 顶点数据
    • 弧的表示方法
    弧头顶点索引 下一条弧指针 弧数据
    • 邻接表的表示结构
    struct Node
    {
        顶点索引
        该顶点弧链表头节点;
        顶点数据;
    }
    struct Arc
    {
        指向的顶点索引
        指向下一条弧的指针
        弧信息
    }
    struct Map
    {
        顶点数组
    }
    
    • 逆邻接表
    顶点索引 入弧链表头指针 顶点数据
    • 弧的表示方法
    弧尾顶点索引 下一条弧指针 弧数据
    1.3.十字链表
    1.4.邻接多重表-

    四、图的遍历:


    • 深度优先搜索
      • 类似树的前序遍历
    • 广度优先搜索
      • 一层一层的搜索
    • 最小生成树
      • 实现搜索最小值
      • 普利姆Prim算法
      • 克鲁斯卡尔Kruskal算法

    五、利用邻接表实现图的深度优先搜索和广度优先搜索(其中深度优先搜索用递归方法;广度优先搜索用队列非递归方法)

    PS:邻接表方法并不合适,因为当图比较大的时候,会需要很多的连续内存占用,所以应该探索别的存储方法。

    //Node.h
    #pragma once
    #include<iostream>
    using namespace std;
    class Node
    {
    public:
    	Node(int d=0);
    	~Node();
    	int data;
    	bool is_vis;
    private:
    };
    //Node.cpp
    #include"Node.h"
    Node::Node(int d)
    {
    	data = d;
    	is_vis = false;
    }
    Node::~Node()
    {
    }
    
    //Graph.h
    #pragma once
    #include"Node.h"
    #include<vector>
    class Graph
    {
    public:
    	Graph(int c);
    	~Graph();
    	bool add_node(Node *n);//增加元素,第几个增加的元素其序号就为几,这个要注意。
    	bool reset_node();//重置所有元素为未访问状态
    	void print_matrix();//输出邻接矩阵
    	bool insert_edge(int row, int column, int wei=1);//增加节点连接关系
    	int get_matrix_value(int row, int column);//获得邻接矩阵的连接
    	void depth_search(int index);//深度优先搜索
    	void width_search(int index);//广度优先搜索
    private:
    	int capacity;
    	int node_count;
    	Node* node_array;
    	int* node_matrix;
    };
    
    //Graph.cpp
    
    #include"Graph.h"
    #include<queue>
    Graph::Graph(int c)
    {
    	capacity=c;
    	node_count=0;
    	node_array=new Node[c];//初始化node数组
    	node_matrix=new int[c*c];//n个节点
    	memset(node_matrix, 0, c * c * sizeof(int));//初始化
    }
    bool Graph::add_node(Node* n)
    {
    		node_array[node_count].data = n->data;//添加顺序就是节点编号
    		cout << node_count <<"  "<< n->data << endl;
    		node_count++;
    		return true;	
    }
    void Graph::print_matrix()
    {
    	for (int i=0;i<capacity;i++)
    	{
    		for (int j=0;j<capacity;j++)
    		{
    			cout << node_matrix[i * capacity + j]<<" ";
    		}
    		cout << endl;
    	}
    	cout<<"================================================================"<<endl;
    }
    bool Graph::insert_edge(int row, int column, int wei)
    {
    	if (row < 0 || row >= capacity) { return false; }
    	if (column < 0 || column >= capacity) { return false; }
    	node_matrix[row * capacity + column] = wei;
    	node_matrix[column * capacity + row] = wei;
    	return true;
    }
    int Graph::get_matrix_value(int row, int column)
    {
    	if (row < 0 || row >= capacity) { return 0; }
    	if (column < 0 || column >= capacity) { return 0; }
    	return node_matrix[row * capacity + column];
    }
    bool Graph::reset_node()
    {
    	for (int i = 0; i < node_count; i++)
    	{
    		node_array[i].is_vis = false;
    	}
    	return true;
    }
    void Graph::depth_search(int index)
    {
    	cout << node_array[index].data << " ";
    	node_array[index].is_vis = true;
    	for (int i = 0; i < capacity; i++)
    	{
    		if (get_matrix_value(index, i)==1)
    		{
    			if (!node_array[i].is_vis)
    			{
    				depth_search(i);
    			}
    			else
    			{
    				continue;
    			}
    		}
    	}
    }
    
    void Graph::width_search(int index)
    {
    	cout << node_array[index].data << "
    "<<endl;
    	node_array[index].is_vis = true;//第一个节点访问,并置为已访问
    	queue<int> q;
    	q.push(index);
    	int pre_q = 1;//统计第一层节点的个数,首节点当然个数为1;
    	while (!q.empty())
    	{
    		int value = 0;
    		int cur_q = 0;//记录下一层元素的个数
    		for (int i = 0; i < pre_q; i++)//注意这的截至条件是pre_q,说明每次循环都只会将上一层加入的节点取出,然后保存下一层的节点,根据先进先出原则,正好把上一层的取出完毕
    		{
    			int num = q.front();//得到先进入的第一个元素
    			q.pop();
    			for (int j = 0; j < capacity; j++)
    			{
    				value = node_matrix[num* capacity + j];
    				if (value)
    				{
    					if (!node_array[j].is_vis)//判断元素是否访问过。
    					{
    						cout << node_array[j].data << endl;
    						node_array[j].is_vis = true;
    						cur_q++;
    						q.push(j);//将下一层的节点入队
    					}
    				}				
    			}
    		}
    		pre_q = cur_q;//将本层元素个数作为下一层循环的父节点个数
    		cout << endl;
    	}
    	return;
    }
    Graph::~Graph()
    {
    	delete[]node_array;
    	delete[]node_matrix;
    }
    //main.cpp
    #include"Graph.h"
    
    int main()
    {
    	Graph g(8);
    	Node* n1 = new Node(1);
    	Node* n2 = new Node(2);
    	Node* n3 = new Node(3);
    	Node* n4 = new Node(4);
    	Node* n5 = new Node(5);
    	Node* n6 = new Node(6);
    	Node* n7 = new Node(7);
    	Node* n0 = new Node(0);
    
    	g.add_node(n0);
    	g.add_node(n1);
    	g.add_node(n2);
    	g.add_node(n3);
    	g.add_node(n4);
    	g.add_node(n5);
    	g.add_node(n6);
    	g.add_node(n7);
    	
    
    	//设置连接关系
    	g.insert_edge(0, 1);
    	g.insert_edge(2, 1);
    	g.insert_edge(0, 4);
    	g.insert_edge(3, 1);
    	g.insert_edge(2, 3);
    	g.insert_edge(4, 5);
    	g.insert_edge(4, 7);
    	g.insert_edge(5, 6);
    	g.insert_edge(6, 7);
    
    	g.depth_search(0);
    	g.reset_node();
    	cout << endl;
    	g.width_search(0);
    	//宽度遍历
    	return 0;
    }
    
    
    
    
    
    
    
    Higher you climb, more view you will see.
  • 相关阅读:
    linux mint安装成功
    js 兼容性
    程序员的肚子有多大,水平就有多高
    财富通直连接口for rails3
    ubuntu live cd版本是没有recuse broken system功能
    生活百科
    省市县导入mysql代码,通过csv
    省市县导入mysql代码,通过csv
    休眠、挂起、待机三者之间的区别 收藏
    支付宝接口for rails3
  • 原文地址:https://www.cnblogs.com/yyfighting/p/12500607.html
Copyright © 2020-2023  润新知