设计一个算法计算邻接表表示的图的各个顶点的出度

c
//Analyse:由于邻接表中,表头就是尾节点,几个邻接点就是几个出度.
void out_degree(LGraph lg)
{
	int i;
	ENode *p;
	printf("--- 各节点出度统计 ---\n");
	for(i = 0;i < lg.n;i++)
	{
		int count = 0;
		for(p = lg.a[i];p;p = p->nextArc)
			count++;
		printf("节点 [%d]:%d\n",i,count);
	}
}

设计一个算法计算邻接表表示的图的各个顶点的入度

c
//Analyse:就是箭头指向各个顶点的数目一共多少个
void in_degree(LGraph lg)
{
	int i;
	ENode *p;
	int *count = (int*)calloc(lg.n,sizeof(int));
	if(count == NULL) return;
	printf("--- 各节点入度统计 ---\n");
	for(i = 0;i < lg.n;i++)
	{
		for(p = lg.a[i];p;p = p->nextArc)
			count[p->adjVex]++;
	}
	//遍历结束之后 所有情况考虑 运算完成
	for(i = 0;i < lg.n;i++)
		printf("节点 [%d]:%d\n",i,count[i]);
	
	//结束之后 释放内存
	free(count);
}

设计算法计算任意节点u的入度:

c
与第五题思路一致
但是直接选中,遍历所有非u节点 即i < lg.n && i != u
然后当 p -> adjVex == u时
入度加1,然后输出,这里无需添加count计数数组,只需要保存数值输出即可

设计算法任意顶点u的出度:

c
第四题时计算每个顶点的入度
稍加修改即可输出任意节点u的入度!
比如在printf执行时添加条件:i == u 时打印
这样就返回顶点u的入度

G是由邻接矩阵表示的图,设计算法由邻接矩阵转化为邻接表

c
//Analyse:邻接矩阵->邻接表 如果mg.a[i][j] 存在就在lg->a[i]后面加边、点
LGraph* mg2lg(MGraph mg)
{
	//转化后的邻接表表示的图存储
	LGraph *lg = (LGraph*)malloc(sizeof(LGraph));
	if(lg == NULL) return;
	lg->a = (ENode**)malloc(sizeof(ENode*) * mg.n);
	if(lg->a == NULL)
	{
		free(lg)
		return;
	}
	
	//然后开始 加入表 先创建节点 加如当前位置后面 然后置null
	for(int i=0;i<mg.n;i++)
	{
		//初始化为NULL防止出问题
		lg->a[i] = NULL;
		
		for(int j=0;j<mg.n;j++)
		{
			//从i为尾开始 开始创建邻接表
			if(mg.a[i][j] != noEdge && i != j)
			{
				ENode *p = (ENode*)malloc(sizeof(ENode));
				if(p == NULL) return;
				p->adjVex = j;
				p->w = mg.a[i][j];
				p->nextArc = lg->a[i]; 
				lg->a[i] = p;
			}
		
		}
	}
	return lg;
}

G是由邻接表表示的图,设计算法由邻接表转化为邻接矩阵表示的图

c
//Analyse:lg->a[i] 然后访问nextArc(j) 以及w 对应mg->a[i][j] == w

MGraph* lg2mg(LGraph lg)
{
    int n = lg.n;
    MGraph *mg = (MGraph*)malloc(sizeof(MGraph));
    if (mg == NULL) return NULL;
    mg->n = n;
    
    // 2. 分配 NxN 矩阵的空间并初始化
    mg->a = (ElemType**)malloc(sizeof(ElemType*) * n);
    if (mg->a == NULL) { free(mg); return NULL; }

    // 2.1 循环分配每一行空间并进行初始化
    for (int i = 0; i < n; i++) {
        mg->a[i] = (ElemType*)malloc(sizeof(ElemType) * n);
        if (mg->a[i] == NULL) {
            // 实际项目中需要清理已分配的内存,这里简化
            return NULL; 
        }

        for (int j = 0; j < n; j++) {
            if (i == j) {
                mg->a[i][j] = 0;      // 对角线设为 0
            } else {
                mg->a[i][j] = noEdge; // 其余设为无穷大/不连通
            }
        }
    }
    
    // 3. 遍历邻接表,填充矩阵 (核心逻辑)
    for (int i = 0; i < n; i++) {
        ENode *p = lg.a[i]; // 从顶点 i 的链表头开始遍历
        // 遍历 i 的所有出边
        while (p != NULL) {
            int j = p->adjVex; // 终点 j
            // 将链表中的权值 p->w 填入矩阵的 mg.a[i][j] 位置
            mg->a[i][j] = p->w;
            p = p->nextArc; // 移动到下一条边
        }
    }
    return mg;
}

根据前面9.23画出顶点为c的宽度优先遍历顶点序列与生成森林(或生成树)

c
答案:CEBFAD

生成森林:如图

![[a73ba5fcd96e8b46ad2109d73fe94534.jpg]] G以邻接表表示,设计一个算法实现对图G的深度优先遍历的算法

c
bool *visited; 
// DFS 递归核心函数
void DFS_Visit(LGraph lg, int v) {
    visited[v] = true;
    printf("访问: %d\n", v); 

    ENode *p = lg.a[v];
    while (p != NULL) {
        int w = p->adjVex;
        
        // 遇到未访问的邻居,递归进入
        if (!visited[w]) {
            DFS_Visit(lg, w);
        }
        
        p = p->nextArc;
    }
}
// 主函数
void DFS(LGraph lg) {
    visited = (bool*)calloc(lg.n, sizeof(bool));
    if (visited == NULL) return;

    // 遍历所有顶点,处理不连通分量
    for (int i = 0; i < lg.n; i++) {
        if (!visited[i]) {
            DFS_Visit(lg, i);
        }
    }
    
    free(visited);
}

G以邻接表表示,设计一个算法实现对图G的广度优先遍历的算法

c
#include <stdbool.h>
#include <stdlib.h>
// 假设队列 Queue 已经实现

// 辅助结构:简化队列实现
typedef struct {
    int *data;
    int front, rear;
    int capacity;
} SimpleQueue;

// [队列基本操作代码省略...]

void BFS(LGraph lg) {
    bool *visited = (bool*)calloc(lg.n, sizeof(bool));
    SimpleQueue q;
    InitQueue(&q, lg.n); // 队列初始化

    for (int i = 0; i < lg.n; i++) {
        if (!visited[i]) {
            visited[i] = true;
            printf("访问: %d\n", i);
            EnQueue(&q, i); // 起点入队

            while (q.front != q.rear) {
                int v = DeQueue(&q); // 队首出队
                ENode *p = lg.a[v];

                // 遍历 v 的所有邻居
                while (p != NULL) {
                    int w = p->adjVex;
                    if (!visited[w]) {
                        visited[w] = true;
                        printf("访问: %d\n", w);
                        EnQueue(&q, w); // 邻居入队
                    }
                    p = p->nextArc;
                }
            }
        }
    }

    free(q.data);
    free(visited);
}

在第三题基础上构建的邻接表上执行拓扑排序算法,给出最终拓扑排序的顶点序列

c
拓扑排序顺序:3502416

无向图G以邻接矩阵表示,设计算法实现普利姆算法prim

c
void Prim(MGraph mg, int u) { // u 为起始顶点
    int n = mg.n;
    // lowcost[i] 存储:已选顶点集 U 到 顶点 i 的最短边的权值
    int *lowcost = (int*)malloc(sizeof(int) * n);
    // closest[i] 存储:lowcost[i] 对应的边在 U 中的哪个顶点
    int *closest = (int*)malloc(sizeof(int) * n); 
    bool *s = (bool*)calloc(n, sizeof(bool)); // 标记顶点是否已加入最小生成树 (集合 S)

    // 1. 初始化:以起始点 u 为中心
    for (int i = 0; i < n; i++) {
        lowcost[i] = mg.a[u][i]; // 顶点 i 到 u 的距离
        closest[i] = u;          // 顶点 i 都是连接到 u
    }

    s[u] = true; // 起点 u 加入集合 S
    
    // 2. 循环 n-1 次,每次找到一条新的最小边
    for (int i = 1; i < n; i++) {
        int min = INFTY;
        int k = -1; // 记录找到的下一个顶点

        // 步骤 A: 贪心选择:在 (V-S) 中找到 lowcost 最小的顶点 k
        for (int j = 0; j < n; j++) {
            if (!s[j] && lowcost[j] < min) {
                min = lowcost[j];
                k = j;
            }
        }

        if (k == -1) break; // 图不连通,无法继续

        // 步骤 B: 打印新边,将 k 加入集合 S
        s[k] = true;
        printf("选择边 (%d, %d), 权值: %d\n", closest[k], k, min); 

        // 步骤 C: 松弛更新:用新加入的顶点 k 更新 lowcost 数组
        for (int j = 0; j < n; j++) {
            // 检查:如果 j 未被选中,且 (k -> j) 边的权值比 lowcost[j] 更小
            if (!s[j] && mg.a[k][j] < lowcost[j]) {
                lowcost[j] = mg.a[k][j]; // 更新最短连接权值
                closest[j] = k;          // 更新最短连接的顶点是 k
            }
        }
    }
    free(lowcost);
    free(closest);
    free(s);
}

AOE网求各个事件最早发生时间、允许最迟发生时间、 各个活动允许发生的最早时间与最迟时间,关键活动、关键路径、以及关键路径长度 ![[94c1280fafda36ad2b00b2b9ea29ee3a_720.jpg]]