考研——图算法大题整理(一)

一、图的存储结构

1. 邻接表

// 边表
typedef struct ArcNode{
    int adjvex; // 邻接点下标
    int info;   // 边权
    struct ArcNode* nextarc;    // 邻接边
}ArcNode;
// 顶点表
typedef struct VNode{
    char data;
    ArcNode* firstarc;
}VNode;
// 邻接表
typedef struct{
    VNode adjlist[MaxSize];
    int edgenum, vexnum;
}AGraph;

2. 邻接矩阵

typedef struct{
    int no; // 顶点编号,也可以是char
    char info;  // 顶点的其他信息,不做特殊要求可以不写
}VexType;
typedef struct
{
    VexType vex[MaxSize];
    int edges[MaxSize][MaxSize];
    int edgenum, vexnum;
}MGraph;

二、图的深度优先遍历(DFS)

1. 邻接表

(1) DFS递归方式
 bool visited[MaxSize];
 void DfsTraverse(AGraph* G)	// 用的指针
 {
     memset(visited, false, sizeof visited);
     for (int i = 0; i < G->vexnum; i ++)
        if (!visited[i]) dfs(G, i);
 }
 // 图的dfs类似树的preorder
 void dfs(AGraph* G, int u)
 {
     visited[u] = true;
     visit(u);
     auto p = G->adjlist[u].firstarc;
     while (p)
     {
         auto v = p->adjvex;
         if (!visited[v]) dfs(G, v);
         p = p->nextarc;
     }
 }
(2) DFS非递归方式
bool visited[MaxSize];
void DfsTraverse(AGraph* G)	// 用的指针
 {
     memset(visited, false, sizeof visited);
     for (int i = 0; i < G->vexnum; i ++)
        if (!visited[i]) dfs(G, i);
 }
 // 图的dfs类似树的preorder
 void dfs(AGraph* G, int u)
 {
     stack<int> s;
     s.push(u);
     visited[u] = true;
     while (s.size())
     {
         auto t = s.top();
         s.pop();
         visit(t);
         auto p = G->adjlist[t].firstarc;
         while (p)
         {
             auto v = p->adjvex;
             if (!visited[v])
             {
                 s.push(v);
                 visited[v] = true;
             }
             p = p->nextarc;
         }
     }
 }

2. 邻接矩阵

bool visited[MaxSize];
void DfsTraverse(MGraph G)	// 没用指针
{
    memset(visited, false, sizeof visited);
    for (int i = 0; i < G.vexnum; i ++)
        if (!visited[i]) dfs(G, i);
}
void dfs(MGraph G, int u)
{
    visited[u] = true;
    visit(u);
    for (int i = 0; i < G.vexnum; i ++)
        if (!visited[i] && G.edges[u][i] != 0) dfs(G, i);
}

三、图的广度优先遍历(BFS)

1. 邻接表

bool visited[MaxSize];
void BfsTraverse(AGraph* G)	// 用的指针
{
    memset(visited, false, sizeof visited);
    for (int i = 0; i < G->vexnum; i ++)
        if (!visited[i]) bfs(G, i);
}
void bfs(AGraph* G, int u)
{
    queue<int> q;
    q.push(u);
    visited[u] = true;
    visit(u);
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        auto p = G->adjlist[t].firstarc;
        while (p)
        {
            auto v= p->adjvex;
            if (!visited[v])
            {
                q.push(v);
                visited[v] = true;
                visit(v);
            }
            p = p=>nextarc;
        }
    }
}

2. 邻接矩阵

bool visited[MaxSize];
void BfsTraverse(MGraph G)	// 没用指针
{
    memset(visited, false, sizeof visited);
    for (int i = 0; i < G.vexnum; i ++)
        if (!visited[i]) bfs(G, i);
}
void bfs(MGraph G, int u)
{
    queue<int> q;
    q.push(u);
    visited[u] = true;
    visit(u);
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        for (int i = 0; i < G.vexnum; i ++)
            if (!visit[i] && G.edges[t][i] != 0)
            {
                q.push(i);
                visited[i] = true;
                visit(i);
            }
    }
}

四、图的拓扑排序算法

1. 邻接表

方法1(对邻接表的存储结构进行改造 )

首先,对邻接表表头结点定义进行修改,加入一个统计结点入度的计数器
假设图的邻接表已经生成,并且各个顶点的入度已经统计在了count中
而后进行程序编写

// 顶点表
typedef struct VNode{
    char data;
    int count;	// count统计顶点当前入度是多少
    ArcNode* firstarc;
}VNode;
// 拓扑排序
bool TopSort(AGraph* G)
{
    stack<int> s;
    vector<int> res;    // 用来盛放topsort的结果
    for (int i = 0; i < G->vexnum; i ++)
        if (G.adjlist[i].count == 0)
            s.push(i);
    while (s.size())
    {
        auto t = s.top();
        s.pop();
        res.push_back(t);
        auto p = G->adjlist[t].firstarc;
        while (p)
        {
            auto v = p->adjvex;
            if (-- (G->adjlist[v].count) == 0) s.push(v);
            p = p->nextarc;
        }
    }
    if (res.size() == G->vexnum)
    {
        for (auto r : res) cout << r << ' ';
        puts("");
        return true;
    }
    return false;
}
方法2(不对邻接表的存储结构进行改造 )
int dist[MaxSize];
bool TopSort(AGraph* G)
{
    memset(dist, 0, sizeof dist);
    // 统计图中各结点的入度
    for (int i = 0; i < G->vexnum; i ++)
    {
        auto p = G->adjlist[i].firstarc;
        while (p)
        {
            int v = p->adjvex;
            dist[v] ++;
            p = p->nextarc;
        }
    }
    // 将入度为0的结点入栈
    stack<int> s;
    vector<int> res;
    for (int i = 0; i < G->vexnum; i ++)
        if (dist[i] == 0) s.push(i);
    // TopSort正式开始
    while (s.size())
    {
        auto t = s.top();
        s.pop();
        res.push_back(t);
        auto p = G->adjlist[t].firstarc;
        while (p)
        {
            auto v = p->adjvex;
            if (-- dist[v] == 0) s.push(v);
            p = p->nextarc;
        }
    }
    if (res.size() == G->vexnum)
    {
        for (auto r : res) cout << r << ' ';
        puts("");
        return true;
    }
    return false;
}

2. 邻接矩阵

int dist[MaxSize];
bool TopSort(MGraph G)
{
    memset(dist, 0, sizeof dist);
    for (int i = 0; i < G.vexnum; i ++)
        for (int j = 0; j < G.vexnum; j ++)
            if (G.edges[i][j] != 0) dist[j] ++;
    stack<int> s;
    vector<int> res;
    for (int i = 0; i < G.vexnum; i ++)
        if (dist[i] == 0) s.push(i);
    while (s.size())
    {
        auto t = s.top();
        s.pop();
        res.push_back(t);
        for (int i = 0; i < G.vexnum; i ++)
            if (-- dist[i] == 0) s.push(i);
    }
    if (res.size() == G.vexnum)
    {
        for (auto r : res) cout << r << ' ';
        puts("");
        return true;
    }
    return false;
}

五、图的度数问题

1. 邻接表

(1) 有向图
// 计算所有结点的入度
int dist[MaxSize];
void in_degree(AGraph* G)
{
    memset(dist, 0, sizeof dist);
    for (int i = 0; i < G->vexnum; i ++)
    {
        auto p = G->adjlist[i].firstarc;
        while (p)
        {
            auto v = p->adjvex;
            dist[v] ++;
            p = p->nextarc;
        }
    }
}
// 计算所有结点的出度
int dist[MaxSize];
void out_degree(AGraph* G)
{
    memset(dist, 0, sizeof dist);
    for (int i = 0; i < G->vexnum; i ++)
    {
        auto p = G->adjlist[i].firstarc;
        while (p)
        {
            dist[i] ++;
            p = p->nextarc;
        }
    }
}
(2) 无向图
int dist[MaxSize];  // 记录无向图中各顶点的度数
void degree(MGraph G)
{
    memset(dist, 0, sizeof dist);
    for (int i = 0; i < G.vexnum; i ++)
    {
        auto p = G.adjlist[i].firstarc;
        while (p)
        {
            dist[i] ++;
            p = p->nextarc;
        }
    }
}

2. 邻接矩阵

(1) 有向图
// 计算所有结点的入度
int dist[MaxSize];
void in_degree(MGraph G)
{
    memset(dist, 0, sizeof dist);
    for (int j = 0; j < G.vexnum; j ++)
        for (int i = 0; i < G.vexnum; i ++)
            dist[j] += G.edges[i][j];
}
// 计算所有结点的出度
int dist[MaxSize];
void out_degree(MGraph G)
{
    memset(dist, 0, sizeof dist);
    for (int i = 0; i < G.vexnum; i ++)
        for (int j = 0; j < G.vexnum; j ++)
            dist[i] += G.edges[i][j];
}
(2) 无向图
int dist[MaxSize];
void degree(MGraph G)
{
    memset(dist, 0, sizeof dist);
    for (int i = 0; i < G.vexnum; i ++)
        for (int j = 0; j < G.vexnum; j ++)
            dist[i] += G.edges[i][j];
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值