数据结构lab3-图型结构的建立与搜索

news2024/11/23 8:31:31

title: 数据结构lab3-图型结构的建立与搜索
date: 2023-05-16 11:42:26
tags: 数据结构与算法


课程名称:数据结构与算法

课程类型:必修

实验项目:图型结构的建立与搜索

实验题目:图的存储结构的建立与搜索

实验日期:2021.11.10

班级:2003001

学号:120L021011

姓名:石卓凡

一、实验目的

1. 掌握图的邻接矩阵、邻接表等不同存储形式的表示方法。

2. 掌握图的两种不同遍历方法的基本思想并能编程实现。

3. 掌握构造最小生成树的两种算法思想,并能编程实现。

4. 掌握求单源最短路径和任意两顶点之间的最短路径的算法。

5. 掌握求关键路径的算法,并能编程实现。

6. 能够灵活运用图的相关算法解决相应的实际问题。

**二、**实验要求及实验环境

1**.分别实现图的邻接矩阵、邻接表存储结构的建立算法,分析和比较各建立算法的时间复杂度以及存储结构的空间占用情况;**

2**.实现图的邻接矩阵、邻接表两种存储结构的相互转换算法;**

3**.在上述两种存储结构上,分别实现图的深度优先搜索(递归和非递归)广度优先搜索算法。并以适当的方式存储和显示相应的搜索结果(深度优先或广度优先生成森林(或生成树)、深度优先或广度优先序列和编号);**

4**.**分析搜索算法的时间复杂度;

5**.以文件形式输入图的顶点和边,并显示相应的结果。要求顶点不少于10个,边不少于13个;**

6**.软件功能结构安排合理,界面友好,便于使用。**

实验环境:

操作系统:Win7/Win10

集成开发环境:devcpp++

外部库:暂无

三、设计思想(本程序中的用到的所有数据类型的定义,主程序的流程图及各程序模块之间的调用关系)

数据类型定义

typedef struct TNode {

char Data; //结点数据

int Parent; //该结点双亲再数组中的下标

}TNode;

typedef struct Tree{

TNode node[MaxVNode]; //结点数组

int numTNode; //结点数量

}Tree;

Tree T;

typedef struct MatGraph//有向图的邻接矩阵

{

char VNode[MaxVNode];

int ENode[MaxVNode][MaxVNode];

int numENode;

int numVNode;

}MatGraph;

typedef struct ENode

{

int AdjV;//这条边的终点顶点对应的下标

int Weight;

struct ENode *Next;//链域,有着同一个起点的下一条边

}ENode;

typedef struct VNode

{

char Data;

ENode* FirstENode;//由该顶点V出发的第一条边

}VNode,AdjList[MaxVNode];

typedef struct ALGraph//有向图的邻接表

{

AdjList adjlist;

int numVNode;

int numENode;

}ALGraph;//ALGraph

1.本系统总计设计了23个函数,每个函数的功能和接口设计如下表所示:

序号函数名函数功能函数参数函数返回值
1Main根据order执行各函数
2InitMatGraph初始化MatMatGraph &GNULL
3InsertVNode前序遍历MatGraph &G,char VNULL
4InsertENode有向图MatG插入边MatGraph &G,char V,char W,int WeightNULL
5CreatMatGraph读入边和顶点建立邻接矩阵MatGraph &GNULL
6Mat_DFSMatGraoh的DFSMatGraph G,int startNULL
7Mat_BFSMatGraoh的BFSMatGraph G,int startNULL
8ShowMatGraph进行展示邻接矩阵MatGraph GNULL
9ShowALGraph进行展示邻接表ALGraph* GNULL
10Mat_DFS_Tree邻接矩阵DFS用树展示MatGraph G,int startNULL
11Mat_DFS_BianHao邻接矩阵DFS用编号展示MatGraph G,int start,int count,int arr[])NULL
12Mat_BFS_Tree邻接矩阵BFS用树展示MatGraph G,int startNULL
13Mat_BFS_BianHao邻接矩阵DFS用编号展示MatGraph G,int start,int count,int arr[]NULL
14AL_DFS_Tree邻接表DFS用树展示ALGraph* G,int vNULL
15AL_DFS_BianHao邻接表DFS用编号展示ALGraph* G,int v,int count,int arr[]NULL
16AL_BFS_Tree邻接表BFS用树展示ALGraph* G,int vNULL
17AL_BFS_BianHao邻接表BFS用编号展示ALGraph* G,int v,int count,int arr[]NULL
18InitialTree初始化树NULLNULL
19ShowTree展示树(MatGraph &G)NULL
20Mat_DFS_FeiDiGui邻接矩阵DFS非递归MatGraph MatG,int start
21AL_DFS_FeiDiGui邻接表DFS非递归ALGraph* ALG,int start
22ListToMat已知邻接表G ,转为邻接矩阵MatGMatGraph &MatG,ALGraph* &ALG
23MatToList已知MatGraph邻接矩阵 有向图 转为 邻接表MatGraph MatG,ALGraph* &ALG

2.逻辑设计

(1)邻接矩阵的建立

​ 1.打开文件,并且初始化InitMatGraph(G);

2.读入顶点个数

2.1 进行循环对应次数读入顶点V,用InsertVNode(G,V);插入顶点

3.读入边个数

3.1 进行循环对应次数读入边V1-V2,权重,利用InsertENode(G,V1,V2,weight);插入边

\4. ShowMatGraph(G)进行展示邻接矩阵

(2)邻接表的建立

1.打开文件

2.读入顶点个数,并且读入边个数

3.for循环依次读入G->adjlist[i].Data,并且将G->adjlist[i].FirstENode=NULL;

4.for循环依次读入边V1-V2以及权重Weight

4.1 新生成一个ENode* E赋值V1,V2,Weight,利用头插法插入邻接表

5.ShowALGraph(G)进行展示邻接表

(3)邻接矩阵的DFS递归

1.访问头元素并且标记为已访问

2.遍历所有的和源元素相关的元素,如果为没有被访问,递归的搜索该顶点;

(4)邻接矩阵的DFS非递归

1.初始化栈

2.将头元素进栈,并且cout,记录已访问

3.循环直到栈为空

3.1 读取栈顶元素

3.2遍历所有能和当前栈顶元素有关的顶点 , 对当前没有访问过的且有边连接的顶点访问和进栈

3.3对与已经遍历完所有能和当前栈顶元素有关的顶点之后,进行出栈

(5)邻接矩阵的BFS

\1. 初始化队列

\2. 对头元素进行进队并且cout和标记已访问

\3. 循环直到队列为空

3.1 v=队列头元素,并且出队

3.2 For循环遍历所有与v相关的顶点,找到有边相连接且没有访问过的顶点进行访问,压栈,并且标记已访问

(6)邻接表的DFS递归

\1. 访问头元素,并且标记为已访问

\2. 遍历所有的和头元素相关的元素,如果为被访问,递归的搜索该顶点;

(7)邻接表的DFS非递归

\1. 初始化栈

\2. 对于头元素进行访问,并且标记已访问,新建立边E,赋值为头元素的FirstENode

\3. While循环直到E为空且栈为空

3.1while循环直到E为空

3.1.1不断对尚未访问的并且可以访问到更深的顶点进行访问

3.1.2对于已经访问过的顶点时候,进行E转为同一个起点顶点的另一条边

3.2当由最初的结点的所有路都遍历完之后,出栈,E等于栈顶元素

(8)邻接表的BFS

\1. 初始化队列

\2. 将头元素结点v进行入队Q,并且访问,且设置为已经访问

\3. While直到Q为空

3.1 temp=队列头元素,进行出队,E等于G->adjlist[temp].FirstENode

3.2 While直到E为空

3.2.1如果边E指向的终点顶点E->AdjV并没有访问过,如果可以访问则进行访问并且对于合适的进入入队

3.2.2 E=E->Next;E更新为同一个出发顶点的下一条边

(9)已知有向图邻接表转为邻接矩阵

\1. 初始化邻接矩阵

\2. 遍历邻接表的每一个顶点,顶点存入邻接矩阵

2.1 E = ALG->adjlist[i].FirstENode;

2.2 while循环将E及其E所有的同一个起点顶点的边都存入邻接矩阵

(10) 有向图邻接矩阵转为邻接表

\1. 初始化邻接表

\2. 遍历邻接矩阵的每一个顶点

2.1 存储顶点进入邻接表

2.2 再次遍历所有顶点,去寻找有无对应的边,并且存储这个顶点所有相关的边进入邻接表

(11) 生成树展示

1.同DFS和BFS遍历框架和大体流程一样

2.但是把访问结点cout改为记录当前Data保存到T.node[i].Data,并且记录对应父节点下标保存至T.node[i].Parent,同时T.numTNode++;

(12) 编号展示

\1. 同DFS和BFS遍历框架和大体流程一样

\2. 多设置了int count记录当前第几个访问,与此同时传入数组int arr[],arr[i]=x代表了下标为i的对应的结点出现的编号是x

3.物理设计

1.生成树Tree用到双亲表示法的顺序存储,Tree内包含了TNode node[MaxVNode]的节点数组,用于记录节点个数的int numTNode;而每一个TNode里面有char型的Data记录值,有int Parent记录当前结点的父节点的下标

2.有向图邻接矩阵MatGraph,有char型的VNode[MaxVNode]顶点结点数组,int型ENode[MaxVNode][MaxVNode]边结点数组;int型numENode记录有多少个边;int型numVNode记录有多少个顶点;

3.有向图邻接表ALGraph,有数据类型为VNode型的数组adjlist;

记录有多少个顶点个数的int型的numVNode;

记录有多少个边个数int型numENode;

而VNode内部,定义了Char型的Data,记录值。定义了ENode* FirstENode,作为该顶点V出发的第一条边

而ENode内部,定义了int型AdjV,记录了这一条边指向的终点顶点,int Weight记录这条边的权值,struct ENode *Next记指向与这一条边有着相同起点顶点的下一条边的地址

4.stack栈用链式存储,栈有指向头节点的指针Node *head指向最初进入的元素(栈底),指向尾结点的Node *p,p指向栈顶最新进入的元素,记录栈元素数量的int length,而每个Node节点有对应数据类型的data,指向下一个结点的Node *next,

5.queue队列用链式存储,有指向队首的指针Node *head,指向队尾的指针Node *rear,记录队列元素多少的int length,而每一个Node结点内部都有,对应数据类型的data,指向下一个结点的Node *next

4主程序流程图及各程序模块之间的调用关系

流程图img

调用关系

img

5.时空复杂度比较分析

(1)有向图邻接矩阵和邻接表存储结构建立算法:

邻接矩阵邻接表
时间复杂度O(n²)O(n+e)
空间复杂度O(n²)O(n+e)
适用范围稠密图稀疏图

(2)搜索算法

邻接矩阵邻接表
深度广度深度广度
时间复杂度imgimgimgimg

**四、**测试结果

测试样例1:

img

imgimgimgimgimgimg

测试样例2:

imgimgimgimgimg

五、经验体会与不足

1.经验体会

1.在图的DFS类似于二叉树的先序遍历算法,因此在非递归时候都需要利用到栈来实现

2.非递归算法就是将递归算法用循环和借助栈或者队列来进行操作实现,递归算法更加简洁易懂,非递归算法有助于进一步理解

3.树可以说是一种特殊的图,树是有向无环的特殊的图

4.对于图的邻接矩阵和邻接表,在作为函数传参时候会根据自己的定义有所区别,比如邻接表传入指针型,传入参数时候(MatGraph &G)可以根据自己的需要选择是否要加入&

2.过程暴露的不足:

1.在实现广搜和深搜的生成树时候,如何利用现有的DFS,BFS序列表示修改没有思路

解决方法:将树的存储模式改为双亲表示法的顺序存储

2.如何利用现有的DFS和BFS序列修改为编号表示

解决方法:新建立数组arr[]表示第几次访问到的,同时插入count计数

六、附录:源代码(带注释)

\

#include<iostream>

\#include<stdlib.h>

\#include<stdio.h>

\#include<cstring>

\#include<assert.h>

using namespace std;

\#define INF -1

\#define MaxVNode 100

int visited[MaxVNode];

 

typedef struct TNode {

​    char Data;    //结点数据

​    int Parent;        //该结点双亲再数组中的下标

}TNode;

 

typedef struct Tree{

​    TNode node[MaxVNode];   //结点数组

​    int numTNode;                    //结点数量

}Tree;

Tree T;

typedef struct MatGraph//先按照有向图做 

{

​    char VNode[MaxVNode];

​    int ENode[MaxVNode][MaxVNode];

​    int numENode;

​    int numVNode;

}MatGraph;

typedef struct ENode

{

​    int AdjV;//这条边的终点顶点对应的下标

​    int Weight;

​    struct ENode *Next;//链域,有着同一个起点的下一条边 

 

}ENode;

typedef struct VNode

{

​    char Data;

​    ENode* FirstENode;//由该顶点V出发的第一条边

}VNode,AdjList[MaxVNode];

typedef struct ALGraph

{

​    AdjList adjlist;

​    int numVNode;

​    int numENode;

}ALGraph;//ALGraph

template<class T>class stack

{

private:

​    struct Node

​    {

​        T data;

​        Node *next;

​    };

​    Node *head;

​    Node *p;

​    int length;

 

public:

​    stack()

​    {

​        head = NULL;

​        length = 0;

​    }

​    void push(T n)//入栈

​    {

​        Node *q = new Node;

​        q->data = n;

​        if (head == NULL)

​        {

​            q->next = head;

​            head = q;

​            p = q;

​        }

​        else

​        {

​            q->next = p;

​            p = q;

​        }

​        length++;

​    }

 

​    void pop()//出栈  不会!!并且不会!!!将出栈的元素返回

​    {

​        if (length <= 0)

​        {

​            abort();

​        }

​        Node *q;

​        T data;

​        q = p;

​        data = p->data;

​        p = p->next;

​        delete(q);

​        length--;

​    }

​    int size()//返回元素个数

​    {

​        return length;

​    }

​    T top()//返回栈顶元素

​    {

​        return p->data;

​    }

​    bool empty()//判断栈是不是空的

​    {

​        if (length == 0)

​        {

​            return true;

​        }

​        else

​        {

​            return false;

​        }

​    }

};

template<class T>class queue

{

private:

​    struct Node

​    {

​        T data;

​        Node *next;

​    };

​    Node *head;//!

​    Node *rear;//!队尾 

​    int length;

 

public:

​    queue()

​    {

​        head = NULL;

​        rear = NULL;//!初始化 

​        length = 0;

​    }

​    void push(T n)//入队

​    {

​        Node *node = new Node;

​        node->data = n;

​        node->next = NULL;//!

​        if (head == NULL)

​        {

​            head = node;

​            rear = node;

​        }

​        else

​        {

​            rear->next = node;

​            rear = node;

​        }

​        length++;

​    }

​    void pop()//出栈  不会!!并且不会!!!将出栈的元素返回

​    {

​        if (length <= 0)

​        {

​            abort();

​        }

​        Node *temp = head;

​        head = head->next;

​        delete (temp);

​        length--;

​    }

​    int size()//返回元素个数

​    {

​        return length;

​    }

​    T front()//!返回队首元素

​    {

​        return head->data;

​    }

​    bool empty()//判断栈是不是空的

​    {

​        if (length == 0)

​        {

​            return true;

​        }

​        else

​        {

​            return false;

​        }

​    }

};

void InitMatGraph(MatGraph &G);//初始化Mat 

void InsertVNode(MatGraph &G,char V);//MatG插入V 

void InsertENode(MatGraph &G,char V,char W,int Weight);//向图MatG插入边 

void CreatMatGraph(MatGraph &G); //读入边和顶点建立邻接矩阵

void Mat_DFS(MatGraph G,int start);//MatGraoh的DFS 

void Mat_BFS(MatGraph G,int start);//MatGraoh的BFS 

void ShowMatGraph(MatGraph G);//进行展示邻接矩阵 

void ShowALGraph(ALGraph* G);//进行展示邻接表 

void Mat_DFS_Tree(MatGraph G,int start);//MatGraoh的DFS 树展示 

void Mat_DFS_BianHao(MatGraph G,int start,int count,int arr[]);//MatGraoh的DFS 

void Mat_BFS_Tree(MatGraph G,int start);

void Mat_BFS_BianHao(MatGraph G,int start,int count,int arr[]);

void AL_DFS_Tree(ALGraph* G,int v);

void AL_DFS_BianHao(ALGraph* G,int v,int count,int arr[]);

void AL_BFS_Tree(ALGraph *G,int v);

void AL_BFS_BianHao(ALGraph *G,int v,int count,int arr[]);

void InitialTree();//初始化树 

 

 

 

void InitMatGraph(MatGraph &G)//初始化Mat 

{

​    memset(G.VNode,'#',sizeof(G.VNode));//全部初始化# 

​    memset(G.ENode,INF,sizeof(G.ENode));

​    G.numENode=0;//当前有效的边 

​    G.numVNode=0;

}

void InsertVNode(MatGraph &G,char V)//MatG插入V 

{

​    G.VNode[G.numVNode++]=V;

}

void InsertENode(MatGraph &G,char V,char W,int Weight)//有向图MatG插入边 

{

​    //有向图

​    int v1,v2;//边VW对应下标v1,v2 

​    for(int i=0;i<G.numVNode;i++)

​    {

​        if(G.VNode[i]==V)

​            v1=i;

​        if(G.VNode[i]==W)

​            v2=i;

​    }

​    G.ENode[v1][v2]=Weight;

​    /*//若是无向图

​    G.ENode[v2][v1]=Weight;

​    */

​    G.numENode++;

}

void Mat_DFS(MatGraph G,int start)//MatGraoh的DFS 

{

​    cout<<G.VNode[start];

​    visited[start]=1;//代表已经访问 

​    for(int i=0;i<G.numVNode;i++)

​    {

​        if(G.ENode[start][i]!=INF&&visited[i]!=1)

​        {

​            Mat_DFS(G,i);

​        }

​    }

}   

void Mat_DFS_Tree(MatGraph G,int start)//MatGraoh的DFS 

{

​    for(int i=0;i<G.numVNode;i++)

​    {

​        if(G.ENode[start][i]!=INF&&visited[i]!=1)

​        {

​            T.node[i].Data = G.VNode[i];

​            T.node[i].Parent = start;

​            T.numTNode++;

​            visited[start]=1;//代表已经访问 

​            Mat_DFS_Tree(G,i);

​        }

​    }

}   

void Mat_DFS_BianHao(MatGraph G,int start,int count,int arr[])//MatGraoh的DFS 

{

​    arr[start]=count;//count最初从1开始

​    visited[start]=1;//代表已经访问 

​    for(int i=0;i<G.numVNode;i++)

​    {

​        if(G.ENode[start][i]!=INF&&visited[i]!=1)

​        {

​            Mat_DFS_BianHao(G,i,++count,arr);

​        }

​    }

}   

void Mat_BFS(MatGraph G,int start)

{

​    queue<int>Q;

​    cout<<G.VNode[start];

​    visited[start]=1;

​    Q.push(start);//进队之前cout 

​    while(!Q.empty())

​    {

​        int v = Q.front();

​        Q.pop();

​        for(int i=0;i<G.numVNode;i++)

​        {

​            if(G.ENode[v][i]!=INF&&visited[i]!=1)

​            {

​                cout<<G.VNode[i];

​                Q.push(i);

​                visited[i]=1;

​            }

​        }

​    }

}

void Mat_BFS_Tree(MatGraph G,int start)

{

​    queue<int>Q;

​    visited[start]=1;

​    Q.push(start);//进队之前cout 

​    while(!Q.empty())

​    {

​        int v = Q.front();

​        Q.pop();

​        for(int i=0;i<G.numVNode;i++)

​        {

​            if(G.ENode[v][i]!=INF&&visited[i]!=1)

​            {

​                //cout<<G.VNode[v]<<"->"<<G.VNode[i]<<" ";

​                T.node[i].Data = G.VNode[i];

​                T.node[i].Parent = v;

​                T.numTNode++;

​                Q.push(i);

​                visited[i]=1;

​            }

​        }

​    }

}

void Mat_BFS_BianHao(MatGraph G,int start,int count,int arr[])

{

​    queue<int>Q;

​    visited[start]=1;

​    arr[start]=count;//首个count=1 

​    Q.push(start);//进队之前cout 

​    while(!Q.empty())

​    {

​        int v = Q.front();

​        Q.pop();

​        for(int i=0;i<G.numVNode;i++)

​        {

​            if(G.ENode[v][i]!=INF&&visited[i]!=1)

​            {

​                arr[i]=++count;

​                Q.push(i);

​                visited[i]=1;

​            }

​        }

​    }

}

void CreatMatGraph(MatGraph &G) //读入边和顶点建立邻接矩阵 

{

​    FILE *p;

​    assert((p=fopen("MatGraph.txt","r"))!=NULL);

​    InitMatGraph(G);

​    int n;

​    fscanf(p,"顶点个数=%d;",&n);

​    for(int i=0;i<n;i++)

​    {

​        char V;

​        fscanf(p,"%c;",&V);

​        InsertVNode(G,V);

​    }

​    int m;

​    fscanf(p,"边个数=%d;",&m);

​    for(int i=0;i<m;i++)

​    {

​        char V1,V2;

​        int weight;

​        fscanf(p,"%c,%c,%d;",&V1,&V2,&weight);

​        InsertENode(G,V1,V2,weight);

​    }

​    fclose(p);

​    ShowMatGraph(G);//进行展示邻接矩阵 

}

void ShowMatGraph(MatGraph G)//进行展示邻接矩阵 

{

​    int n=G.numVNode;

​    int m=G.numENode;

​        //进行展示邻接矩阵 

​    cout<<" ";//保证输入格式

​    for(int i=0;i<n;i++)

​        cout<<G.VNode[i]<<" ";

​    cout<<endl;

​    for(int i=0;i<n;i++)

​    {

​        cout<<G.VNode[i]<<" ";

​        for(int j=0;j<n;j++)

​            {

​                if(G.ENode[i][j]!=INF)

​                    cout<<G.ENode[i][j]<<" ";

​                else

​                    cout<<"oo ";

​             } 

​        cout<<endl;

​    }

}

void CreatALGraph(ALGraph* G)//有向图处理 

{

​    FILE *p;

​    assert((p=fopen("ALGraph.txt","r"))!=NULL);//txt文本必须要ANSI编码模式才可以中文 

​    fscanf(p,"顶点个数=%d;",&(G->numVNode));//最初就给定numVNode 

​    fscanf(p,"边个数=%d;",&(G->numENode));

​    for(int i=0;i<G->numVNode;i++)

​    {

​        fscanf(p,"%c;",&(G->adjlist[i].Data));

​        G->adjlist[i].FirstENode=NULL;

​    }

​    for(int i=0 ;i<G->numENode;i++)

​    {

​        char V1,V2;

​        int V1_i,V2_i;//V1对应的下标是V1_i 

​        int Weight;

​        fscanf(p,"%c,%c,%d;",&V1,&V2,&Weight);

​        ENode* e;

​        e= new ENode;

​        for(int i=0;i<G->numVNode;i++)

​        {

​            if(V1 == G->adjlist[i].Data)

​                {

​                    V1_i=i;  

​                }

​            if(V2 == G->adjlist[i].Data )

​                {

​                    V2_i=i;  

​                }

​        }//找到下标 

​        //边 V1->V2

​        e->AdjV=V2_i;//记录e边,由V1指向V2 

​        e->Weight = Weight;

​        e->Next=G->adjlist[V1_i].FirstENode;//e边的起点顶点在V1所以头插法进入V1 

​        G->adjlist[V1_i].FirstENode=e;//头插法 

​        /*//若是无向图

​        //边V2->V1 

​        e= new ENode;

​        e->AdjV=V1_i;

​        e->Weight = Weight;

​        e->Next=G->adjlist[V2_i].FirstENode;

​        G->adjlist[V2_i].FirstENode = e;

​        */

​    }

​    fclose(p);

​    ShowALGraph(G);

}

void ShowALGraph(ALGraph* G)//进行展示邻接表 

{

​    for(int i=0;i<G->numVNode;i++)

​    {

​        cout<<G->adjlist[i].Data;

​        ENode* E;

​        E = G->adjlist[i].FirstENode;

​        while(E!=NULL)

​            {

​                cout<<"->";

​                cout<<E->Weight<<"->"<<G->adjlist[E->AdjV].Data;

​                E=E->Next;

​            }

​        cout<<"->NULL\n";

​    }

}

void AL_DFS(ALGraph* G,int v)

{

​    cout<<G->adjlist[v].Data;

​    visited[v]=1;//cout后就记录进visited 

​    ENode* p;

​    p=G->adjlist[v].FirstENode;

​    while(p!=NULL)

​    {

​        if(visited[p->AdjV]!=1)

​            AL_DFS(G,p->AdjV);//从下一个点以DFS前进 

​        p=p->Next;//当上一条路结束,开始这最开始同一个起点的下一条 

​    }

}

void AL_DFS_BianHao(ALGraph* G,int v,int count,int arr[])

{

​    arr[v]=count;//首次进入的count=1 

​    visited[v]=1;//cout后就记录进visited 

​    ENode* p;

​    p=G->adjlist[v].FirstENode;

​    while(p!=NULL)

​    {

​        if(visited[p->AdjV]!=1)

​            AL_DFS_BianHao(G,p->AdjV,++count,arr);//从下一个点以DFS前进 

​        p=p->Next;//当上一条路结束,开始这最开始同一个起点的下一条 

​    }

}

void AL_DFS_Tree(ALGraph* G,int v)

{

​        //cout<<G->adjlist[v].Data;

​    visited[v]=1;//cout后就记录进visited 

​    ENode* p;

​    p=G->adjlist[v].FirstENode;

​    while(p!=NULL)

​    {

​        if(visited[p->AdjV]!=1)

​        {

​            //cout<<G->adjlist[v].Data<<"->"<<G->adjlist[p->AdjV].Data<<" ";

​                T.node[p->AdjV].Data =G->adjlist[p->AdjV].Data;

​                T.node[p->AdjV].Parent = v;

​                T.numTNode++;

​            AL_DFS_Tree(G,p->AdjV);//从下一个点以DFS前进 

​        }

​            

​        p=p->Next;//当上一条路结束,开始这最开始同一个起点的下一条 

​    }

}

void AL_BFS(ALGraph *G,int v)

{

​    cout<<G->adjlist[v].Data;

​    queue<int> Q;

​    Q.push(v);//设置为入队前cout 

​    visited[v]=1;

​    while(!Q.empty())// 

​    {

​        int temp;

​        temp=Q.front();

​        Q.pop();

​        ENode* E = G->adjlist[temp].FirstENode;//E为当前顶点的某条边

​        while(E!=NULL)

​        {

​            if(visited[E->AdjV]!=1)//边E指向的终点顶点E->AdjV并没有访问过

​            {

​                cout<<G->adjlist[E->AdjV].Data;

​                visited[E->AdjV]=1;//cout后visited记录 

​             } 

​            if (E->Next!=NULL)//和E同一个起点终点的另一条边,所指向的顶点,没有访问过 ,并且这另一条边存在 

​                if(visited[E->Next->AdjV]!=1)//连用两个if 是因为visited[E->Next->AdjV],当 E->Next=NULL时候,判断语句visit[X]溢出 

​                {

​                    Q.push(E->AdjV);

​                }

​            E = E->Next;//E更新为同一个出发顶点的下一条边 

​        }

​    }

}

void AL_BFS_BianHao(ALGraph *G,int v,int count,int arr[])

{

​    arr[v]=count;

​    queue<int> Q;

​    Q.push(v);//设置为入队前cout 

​    visited[v]=1;

​    while(!Q.empty())// 

​    {

​        int temp;

​        temp=Q.front();

​        Q.pop();

​        ENode* E = G->adjlist[temp].FirstENode;//E为当前顶点的某条边

​        while(E!=NULL)

​        {

​            if(visited[E->AdjV]!=1)//边E指向的终点顶点E->AdjV并没有访问过

​            {

​                arr[E->AdjV]=++count;

​                visited[E->AdjV]=1;//cout后visited记录 

​             } 

​            if (E->Next!=NULL)//和E同一个起点终点的另一条边,所指向的顶点,没有访问过 ,并且这另一条边存在 

​                if(visited[E->Next->AdjV]!=1)//连用两个if 是因为visited[E->Next->AdjV],当 E->Next=NULL时候,判断语句visit[X]溢出 

​                {

​                    Q.push(E->AdjV);

​                }

​            E = E->Next;//E更新为同一个出发顶点的下一条边 

​        }

​    }

}

void AL_BFS_Tree(ALGraph *G,int v)

{

​    queue<int> Q;

​    Q.push(v);//设置为入队前cout 

​    visited[v]=1;

​    while(!Q.empty())// 

​    {

​        int temp;

​        temp=Q.front();

​        Q.pop();

​        ENode* E = G->adjlist[temp].FirstENode;//E为当前顶点的某条边

​        while(E!=NULL)

​        {

​            if(visited[E->AdjV]!=1)//边E指向的终点顶点E->AdjV并没有访问过

​            {

​                //cout<<G->adjlist[temp].Data<<"->"<<G->adjlist[E->AdjV].Data<<" ";

​                    T.node[E->AdjV].Data =G->adjlist[E->AdjV].Data;

​                    T.node[E->AdjV].Parent = temp;

​                    T.numTNode++;

​                visited[E->AdjV]=1;//cout后visited记录 

​             } 

​            if (E->Next!=NULL)//和E同一个起点终点的另一条边,所指向的顶点,没有访问过 ,并且这另一条边存在 

​                if(visited[E->Next->AdjV]!=1)//连用两个if 是因为visited[E->Next->AdjV],当 E->Next=NULL时候,判断语句visit[X]溢出 

​                {

​                    Q.push(E->AdjV);

​                }

​            E = E->Next;//E更新为同一个出发顶点的下一条边 

​        }

​    }

}

void MatToList(MatGraph MatG,ALGraph* &ALG)//同样是做有向图

{//已知MatGraph邻接矩阵  有向图 转为 邻接表 

​    ALG = new ALGraph;

​    ALG->numVNode = MatG.numVNode;

​    ALG->numENode = MatG.numENode;

​    for(int i=0;i<MatG.numVNode;i++)   

​        ALG->adjlist[i].FirstENode =NULL;//将初始化 

​    for(int i=0;i<MatG.numVNode;i++)

​    {

​        int j =0;

​        ALG->adjlist[i].Data = MatG.VNode[i];//顶点转换 

​        for(;j<MatG.numVNode;j++)//将这个顶点所有相关的边转换 

​        {

​            if(INF!=MatG.ENode[i][j])//发现有对应的边从i到j 

​            {

​                ENode* E = new ENode;

​                E->AdjV=j;

​                E->Weight = MatG.ENode[i][j];

​                E->Next = ALG->adjlist[i].FirstENode;

​                ALG->adjlist[i].FirstENode=E;//头插法 

​            }

​        }

​    }

​    cout<<"已知的邻接矩阵\n";

​    ShowMatGraph(MatG); 

​    cout<<"转换后变成\n";

​    ShowALGraph(ALG);

}

void ListToMat(MatGraph &MatG,ALGraph* &ALG)//这里是!做有向图的 ! 

{//已知邻接表G ,转为邻接矩阵MatG 

​    ENode* E;

​    memset(MatG.VNode,'#',sizeof(MatG.VNode));

​    memset(MatG.ENode,INF,sizeof(MatG.ENode));

​    MatG.numENode=ALG->numENode;

​    MatG.numVNode=ALG->numVNode;

​    for(int i=0;i<ALG->numVNode;i++)

​    {

​        E = ALG->adjlist[i].FirstENode;

​        MatG.VNode[i] = ALG->adjlist[i].Data;//转换顶点 

​        while(E!=NULL)

​        {//转换边 

​            MatG.ENode[i][E->AdjV]=E->Weight;

​            E=E->Next;

​        }

​    }

​    cout<<"已知的邻接表\n";

​    ShowALGraph(ALG);

​    cout<<"转换后变成\n";

​    ShowMatGraph(MatG);

}

void AL_DFS_FeiDiGui(ALGraph* ALG,int start)

{

​    stack<ENode*> S;

​    memset(visited,0,sizeof(visited));

​    cout<<ALG->adjlist[start].Data;

​    visited[start]=1;//访问之后立刻visited等于1

​    ENode* E = ALG->adjlist[start].FirstENode;

​    while(E||!S.empty())

​    {

​        while(E)

​        {

​            //1.更深

​            if(visited[E->AdjV]==0)//如果更深的终点顶点没有访问过

​                {

​                    S.push(E);//visited之前入队,留下标记可以返回

​                    cout<<ALG->adjlist[E->AdjV].Data;

​                    visited[E->AdjV]=1;//cout之后立刻visited

 

​                    E = ALG->adjlist[E->AdjV].FirstENode;//进入更深的终点顶点

​                }

​            //2.转向

​            else//visited[E->Adjv]==1

​                {

​                    E = E->Next;

​                }//转为同一个起点的另一条边

​        }

​        if(!S.empty())//3.这条路全验证不通之后返回

​        {

​            E = S.top();

​            S.pop();

​        }

​    }

}

void Mat_DFS_FeiDiGui(MatGraph MatG,int start)

{

​    stack<int> S;

​    cout<<MatG.VNode[start];

​    visited[start]=1;

​    S.push(start);//visited之后就立刻入栈

​    //这里选择对首元素进行while之前就入栈

  int v1_i;

  int v2_i;

​        while(!S.empty())

​        {   

​            v1_i = S.top();

​            for(v2_i=0;v2_i<MatG.numVNode;v2_i++)

​            {//1.深入

​                if(visited[v2_i]!=1&&MatG.ENode[v1_i][v2_i]!=INF)//v1->v2有边且从来没有访问过 

​                    {

​                        cout<<MatG.VNode[v2_i];

​                        visited[v2_i]=1;//

​                        S.push(v2_i);//cout和visited后,入栈方便返回 

​                        //并且会由v2_i充当新的v1_i准备继续深入

​                        break;//准备继续深入

​                    }

​                //2.转向,通过for循环已经做到

​                

​            }//3.返回上一级

​            if(v2_i==MatG.numVNode && !S.empty())

​            {//证明由v1_i已经不可能再深入了

​                S.pop();

​            }

​        }

}

void InitialTree()//初始化树 

{

​        for(int i=0;i<MaxVNode;i++) 

​        {

​            T.node[i].Data = '#';

​            T.node[i].Parent = -1; 

​        }

​        T.numTNode=0;

}

void ShowTree()

{

​    for(int i=0;i<MaxVNode;i++)

​    {

​        if(T.node[i].Data!='#')

​            cout<<"T.node["<<i<<"].Data ="<<T.node[i].Data<<" ,Parent="<<T.node[i].Parent<<endl;

​    }

}

int main()

{

​    cout<<"            -------------------------------------------------------------------\n";

  cout<<"            |==================    图的相关操作    =================|\n";

  cout<<"            -------------------------------------------------------------------\n\n";

  cout<<"            |==================      1.根据txt建立邻接矩阵     =================|\n";

  cout<<"            |==================     2.邻接矩阵DFS     =================|\n";

  cout<<"            |==================     3.邻接矩阵BFS     =================|\n";

  cout<<"            |==================     4.根据txt建立邻接表    =================|\n";

  cout<<"            |==================     5.邻接表DFS  =================|\n";

  cout<<"            |==================     6.邻接表BFS =================|\n";

  cout<<"            |==================     7.邻接矩阵转邻接表 =================|\n";

​    cout<<"            |==================     8.邻接表转邻接矩阵 =================|\n";

  cout<<"             |==================     9.邻接表非递归DFS     =================|\n";

  cout<<"            |==================     10.邻接矩阵非递归DFS     =================|\n";

​    while(1)

​    {

​    int n;

​    cout<<"请输入";

​    cin>>n; 

​    int start;

​    int arr[MaxVNode];

 

​    switch(n)

​    {

​        case 1:

​            MatGraph MatG;

​            CreatMatGraph(MatG);

​            cout<<endl;

​            break;

​        case 2:

​            cout<<"请输入从哪个下标开始进行:";

​            cin>>start;

​            //

​            memset(visited,0,sizeof(visited));//初始化visited 

​            cout<<"序列展示\n" ;

​            Mat_DFS(MatG,start);

​            cout<<endl;

​            //

​            memset(visited,0,sizeof(visited));//初始化visited 

​            InitialTree();

​            cout<<"生成树展示\n";

​            Mat_DFS_Tree(MatG,start);

​            //补充特例头结点进入

​            T.node[start].Data= MatG.VNode[start];

​            T.node[start].Parent = -1;

​            T.numTNode++;

​            ShowTree();

​            cout<<endl;

​            //

​            memset(visited,0,sizeof(visited));//初始化visited 

​            memset(arr,-1,sizeof(arr));//初始化arr

​            cout<<"编号展示\n";

​            Mat_DFS_BianHao(MatG,start,1,arr);//MatGraoh的DFS 

​            for(int i=0;i<MatG.numVNode;i++)

​                cout<<MatG.VNode[i]<<":"<<arr[i]<<" ";

​            cout<<endl;

​            break;

​        case 3:

​            cout<<"请输入从哪个下标开始进行:";

​            cin>>start;

​            

​            cout<<"序号展示";

​            memset(visited,0,sizeof(visited));//初始化visited 

​            Mat_BFS(MatG,start);

​            cout<<endl;

​            

​            memset(visited,0,sizeof(visited));//初始化visited 

​            InitialTree();

​            cout<<"生成树展示\n";

​            Mat_BFS_Tree(MatG,start);

​            //补充特例头结点进入

​            T.node[start].Data= MatG.VNode[start];

​            T.node[start].Parent = -1;

​            T.numTNode++;

​            ShowTree();

​            cout<<endl;

​            

​            memset(visited,0,sizeof(visited));//初始化visited 

​            cout<<"编号展示\n";

​            Mat_BFS_BianHao(MatG,start,1,arr);//MatGraoh的DFS 

​            for(int i=0;i<MatG.numVNode;i++)

​                cout<<MatG.VNode[i]<<":"<<arr[i]<<" ";

​            cout<<endl;

​            break;

​        case 4:

​            ALGraph* ALG;

​            ALG = new ALGraph;

​            CreatALGraph(ALG);

​            cout<<endl;

​            break;

​        case 5:

​            

​            cout<<"请输入从哪个下标开始进行:";

​            cin>>start;

​            

​            cout<<"序号展示\n";

​            memset(visited,0,sizeof(visited));//初始化visited 

​            AL_DFS(ALG,start);

​            cout<<endl;

​            

​            memset(visited,0,sizeof(visited));//初始化visited 

​            InitialTree();

​            cout<<"生成树展示\n";

​            AL_DFS_Tree(ALG,start);

​            //补充特例头结点进入

​            T.node[start].Data= ALG->adjlist[start].Data;

​            T.node[start].Parent = -1;

​            T.numTNode++;

​            ShowTree();

​            cout<<endl;

​            

​            memset(visited,0,sizeof(visited));//初始化visited 

​            memset(arr,-1,sizeof(arr));//初始化arr

​            cout<<"编号展示\n";

​            AL_DFS_BianHao(ALG,start,1,arr);//MatGraoh的DFS ,count=1所以直接传值1 

​            for(int i=0;i<ALG->numVNode;i++)

​                cout<<ALG->adjlist[i].Data<<":"<<arr[i]<<" ";

​            cout<<endl;

​            break;

​        case 6:

​            cout<<"请输入从哪个下标开始进行:";

​            cin>>start;

​            

​            cout<<"序号展示\n";

​            memset(visited,0,sizeof(visited));//初始化visited

​            AL_BFS(ALG,start);

​            cout<<endl;

​            

​            memset(visited,0,sizeof(visited));//初始化visited 

​            InitialTree();

​            cout<<"生成树展示\n";

​            AL_BFS_Tree(ALG,start);

​            //补充特例头结点进入

​            T.node[start].Data= ALG->adjlist[start].Data;

​            T.node[start].Parent = -1;

​            T.numTNode++;

​            ShowTree();

​            cout<<endl;

​            

​            memset(visited,0,sizeof(visited));//初始化visited 

​            memset(arr,-1,sizeof(arr));//初始化arr

​            cout<<"编号展示\n";

​            AL_BFS_BianHao(ALG,start,1,arr);//MatGraoh的DFS ,count=1所以直接传值1 

​            for(int i=0;i<ALG->numVNode;i++)

​                cout<<ALG->adjlist[i].Data<<":"<<arr[i]<<" ";

​            cout<<endl;

​            break;

​            

​        case 7:

​            memset(visited,0,sizeof(visited));//初始化visited 

​            MatToList(MatG,ALG);

​            cout<<endl;

​            break;

​        case 8:

​            memset(visited,0,sizeof(visited));//初始化visited 

​            ListToMat(MatG,ALG);

​            cout<<endl;

​            break;

​        case 9:

​            memset(visited,0,sizeof(visited));//初始化visited 

​            cout<<"请输入从哪个下标开始进行:";

​            cin>>start;

​            AL_DFS_FeiDiGui(ALG,start);

​            cout<<endl;

​            break;

​        case 10:

​            memset(visited,0,sizeof(visited));//初始化visited 

​            cout<<"请输入从哪个下标开始进行:";

​            cin>>start;

​            Mat_DFS_FeiDiGui(MatG,start);

​            cout<<endl;

​            break;

​            

​    }

​    

​    }

​    

} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/531548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于html+css的图展示72

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

【K8s】openEuler23操作系统安装Docker和Kubernetes

openEuler23操作系统安装 服务器搭建环境随手记 文章目录 openEuler23操作系统安装前言&#xff1a;一、前期准备&#xff08;所有节点&#xff09;1.1所有节点&#xff0c;关闭防火墙规则&#xff0c;关闭selinux&#xff0c;关闭swap交换&#xff0c;打通所有服务器网络&am…

Java 工程师不同阶段的发展路线

Java作为一种广泛应用于企业级应用程序的编程语言&#xff0c;已成为全球最流行的编程语言之一。在Java领域&#xff0c;Java高级工程师是一个非常有前途的职业&#xff0c;随着互联网和移动应用的不断发展&#xff0c;Java高级工程师的需求量也在不断增加。在这篇文章中&#…

Node.js 学习系列(二) —— 创建一个应用

Node.js 应用由三部分组成&#xff1a; &#xff08;一&#xff09;require 指令&#xff1a; 在 Node.js 中&#xff0c;使用 require 指令来加载和引入模块&#xff0c;引入的模块可以是内置模块&#xff0c;也可以是第三方模块或自定义模块。 语法格式&#xff1a; cons…

Qt+QtWebApp开发笔记(一):QtWebApp介绍、下载和搭建基础封装http轻量级服务器Demo

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/130631547 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

MySQL学习---16、触发器

1、触发器 MySQL从5.0.2版本开始支持触发器。MySQL的触发器和存储过程一样&#xff0c;都是嵌入到MySQL服务器的一段程序。 触发器是由某个事件来触发某个操作&#xff0c;这些事件包括Insert、Update、Delete事件。所谓事件就是指用户的动作或者触发某项行为。如过定义了触发…

杂记——24.HTML中空格的写法

前几天写项目时&#xff0c;突然对HTML中空格的写法感兴趣&#xff0c;于是搜了一下&#xff0c;现在对其进行总结 HTML不是一种编程语言&#xff0c;而是一种超文本标记语言 (markup language)&#xff0c;是网页制作所必备的。超文本”就是指页面内可以包含图片、链接&#…

PDF文件转换工具Solid Converter PDF 10.1版本在Win10系统的下载与安装配置教程

目录 前言一、Solid Converter PDF安装二、使用配置总结 前言 Solid Converter PDF是一种PDF文件转换工具&#xff0c;可以将PDF文件转换为Microsoft Word、Excel、PowerPoint等格式。它还支持批量转换和OCR&#xff08;光学字符识别&#xff09;功能。 Solid Converter PDF的…

NIO基础

NIO 在学习Netty之前&#xff0c;我们需要先了解一下NIO&#xff0c;以便更好的学习Netty NIO是non-blocking io&#xff0c;也就是非阻塞IO 1.三大组件 1.1 channel & Buffer channel 有一点类似于 stream&#xff0c;它就是读写数据的双向通道&#xff0c;可以从 ch…

【YOLO系列】YOLO v3(网络结构图+代码)

文章目录 网络结构YOLO v3YOLOv3-SPP 多尺度预测损失函数参考 最近在研究YOLO系列&#xff0c;打算写一系列的YOLO博文。在YOLO的发展史中&#xff0c;v1到v3算法思想逐渐完备&#xff0c;后续的系列也都以v3为基石&#xff0c;在v3的基础上进行改进&#xff0c;所以很有必要单…

KD600A变频抗干扰精密介质损耗测量仪

一、产品概述 KD600A变压器介质损耗测试仪是发电厂、变电站等现场自动测量各种高压电力设备介损正切值及电容量的高精度仪器。由于采用了变频技术能保证在强电场干扰下准确测量。仪器采用中文菜单操作&#xff0c;微机自动完成测量。 该仪器同样适用于车间、试验室、科研单位测…

映射及有关概念

映射的概念:有两个集合A,B&#xff0c;若A的任何元素都有唯一的B中元素与之对应&#xff0c;B中元素与之对应的称为像&#xff0c;A中对应的元素称为原像 一个集合也有像&#xff0c;定义为各自像的集合 B中集合也有原像&#xff0c;定义为各自原像的集合 虽然采用了f-1的符号&…

端口隔离、MAC地址表项、MAC地址漂移防止与检测

目录 前言 端口隔离 MAC地址表项 端口安全 MAC地址漂移检测 前言 目前网络中以太网技术的应用非常广泛。然而&#xff0c;各种网络攻击的存在&#xff08;例如针对ARP、DHCP等协议的攻击&#xff09;&#xff0c;不仅造成了网络合法用户无法正常访问网络资源&#xff0c;…

【案例教程】山洪径流过程模拟及洪水危险性评价技术

GIS水文分析&#xff08;ArcHydro、Spatial Anlysist等模块&#xff09;是流域水文模拟建模的重要工具&#xff0c;能够自动提取及计算流域边界、河网水系、流向、汇流时间和其它流域特征参数。美国陆军工程兵团开发的开源、免费Hec-RAS软件具有强大的空间数据分析与整合功能、…

每日学术速递5.13

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.VideoChat: Chat-Centric Video Understanding 标题&#xff1a;VideoChat&#xff1a;以聊天为中心的视频理解 作者&#xff1a;KunChang Li, Yinan He, Yi Wang, Yizhuo Li, Wen…

计算机网络基础知识(五)——什么是TCPUDP协议?图文并茂的方式对两大传输层协议进行从头到尾的讲解

文章目录 01 | &#x1f4d5; 什么是 T C P &#xff1f; \color{red}{什么是TCP&#xff1f;} 什么是TCP&#xff1f;&#x1f4d5;特点三次握手 && 四次挥手超时重传滑动窗口 02 | &#x1f4d9; 什么是 U D P &#xff1f; \color{orange}{什么是UDP&#xff1f;} 什…

1. 链表

b站懒猫数据结构课程笔记&#xff1a;https://www.bilibili.com/read/cv8013121?spm_id_from333.999.0.0 一、链表的概念 单链表&#xff1a;线性表的链接存储结构 单链表存储特点&#xff1a; 逻辑次序和物理次序不一定相同 元素之间的逻辑关系用指针表示 举例&#xff1a…

PASCAL VOC数据集

一、前言 之前寒假好像就学了&#xff0c;但是没有记笔记&#xff0c;现在看来还是得记笔记&#xff0c;都忘得差不多了啊。 二、数据集的介绍 2.1数据集背景 分类类别 2.2数据集文件结构&#xff1a; 2.3文件夹 2.3.1Annotations文件夹 对于标注文件Annotations&#xff1a;里…

基于SpringBoot框架的程序开发步骤

SpringBoot简介 1. 入门案例问题导入1.1 入门案例开发步骤1.2 基于SpringBoot官网创建项目1.3 SpringBoot项目快速启动 2. SpringBoot概述问题导入2.1 起步依赖2.2 辅助功能 1. 入门案例 问题导入 SpringMVC的HelloWord程序怎么写&#xff1f; SpringBoot是由Pivotal团队提供…

死锁、生产者和消费者问题

目录 生产者和消费者问题 死锁的概念 内存的基础知识 内存管理的概念 覆盖与交换 介绍一下PCB 连续分配管理方式​编辑 生产者和消费者问题 死锁的概念 什么是死锁 进程死锁、饥饿、死循环的区别 死锁产生的必要条件 什么时候会发生死锁 死锁的处理策略 内存的基础知识 内存…