Files
2026-01-22 21:43:03 +08:00

123 lines
7.8 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
功能描述
同时用邻接矩阵与邻接表描述图的存储结构,读取n,m,dir和m条边,构建两种表示并打印结果。
支持无向和有向图:dir=0无向,dir=1有向。
数据结构
邻接矩阵:GraphMat { int n; int directed; int **mat; }mat[i][j]为0/1(是否存在边)。
邻接表:GraphList { int n; int directed; Edge **head; }Edge { int to; Edge* next;}。
辅助函数
创建矩阵:GraphMatCreate(int n, int directed)分配n×n二维数组并清零。
加边到矩阵:GraphMatAddEdge写mat[u-1][v-1]=1,无向图对称写入。
释放矩阵:GraphMatFree逐行释放再释放行指针数组。
创建邻接表:GraphListCreate分配头指针数组。
加边到邻接表:GraphListAddEdge头插法建立链表;无向图对称插入。
释放邻接表:GraphListFree逐链释放每个顶点的边链。
打印矩阵:PrintMatrix行输出。
打印邻接表:PrintList每顶点输出邻居列表。
核心算法
邻接矩阵初始化与加边:O(n²)清零,边更新为O(1)。
邻接表插入:每条边O(1)头插。
初始化与交互
Windows控制台设置为UTF-8,避免中文乱码。
读取n,m,dir,随后读取m条边并同时写入两种结构。
打印两种表示并释放内存。
输入与输出
输入:第一行n m dir;接下来m行每行u v。
输出:先打印邻接矩阵(0/1),再打印邻接表的每个顶点的邻居列表。
代码特点
二维数组int**行指针+行内存独立分配;可读性好,访问用mat[i][j]。
邻接表使用链式前插,简单高效。
函数分层清晰,构建、打印与释放职责分明。
边界与异常处理
输入校验:n>0m≥0dir∈{0,1},边索引必须在[1..n]。
内存管理:分配失败未显式处理,但所有已分配资源均在退出前释放。
时间与空间复杂度
邻接矩阵:初始化O(n²),加边O(m),打印O(n²);空间O(n²)。
邻接表:创建O(n),加边O(m),打印O(n+m);空间O(n+m)。
可能扩展
邻接矩阵采用单块连续内存并行指针映射,提升局部性。
支持权值图(矩阵存权、表结点包含权)。
输入格式扩展支持 0 基顶点编号与批量文件读取。
exercise/44.c 实验分析
功能描述
读取有向图n、m以及m条边x,y,z(正权),用邻接矩阵存储并运行Dijkstra,计算1号点到n号点的最短距离;程序按人机交互提示读入并以中文提示输出结果。
数据结构
图结构:AMGraphStruct { int vexnum; int **arcs; },以int**邻接矩阵存储;AMGraph为指针别名。
辅助数组:S[]标记已确定最短路的顶点;D[]为源点到各顶点的当前最短距离;Path[]记录前驱。
常量:MaxInt为不可达哨值,MAXN为数组容量上限。
辅助函数
ShortestPath_DIJ(AMGraph G, int v0):初始化S、D、Path;每轮从未确定集合中选取当前距离最小顶点v,加入S并对其所有邻接点w进行松弛更新。
核心算法
Dijkstra(邻接矩阵实现):每轮选择最小未访问顶点并进行全邻接松弛,复杂度O(n²)。
初始化与交互
Windows控制台设置为UTF-8;提示输入n、m与每条边x、y、z;运行后以中文提示输出从源点(内部索引0)到目标点(内部索引n-1)的最短距离或不可达信息。
输入与输出
输入:第一行n m;其后m行x y z,顶点编号为1基,边权均为正值。
输出:若可达,输出“从顶点0到顶点n-1的最短路径长度为:D[n-1]”;不可达,输出“从顶点0到顶点n-1不存在路径”。
代码特点
使用指针形式的邻接矩阵,初始化对角为0、其余为MaxInt;重边保留较小权值以确保Dijkstra正确性;全局辅助数组简化函数签名。
边界与异常处理
基本输入失败时直接返回;未显式校验n与边权范围;不可达场景需要在选点阶段考虑无候选的情况以避免未赋值索引的使用(建议在未选出顶点时终止循环)。
时间与空间复杂度
时间:O(n²) 选择与松弛;空间:邻接矩阵O(n²),辅助数组O(n)。
可能扩展
改为邻接表+最小堆实现,将复杂度优化为O(m log n);统一输出为OJ格式仅输出数值或-1;增加输入范围校验与路径重建输出。
exercise/查找.c 实验分析
功能描述
读取整数个数n与n个整数,复制为sortedArr并用带索引的冒泡排序Bubble_Sort_With_Index排序,同时维护indexArr将排序后位置映射到原数组索引。打印排序结果。随后循环交互读取要查找的整数target与查找方法choice,支持:线性查找、二分查找(在有序数组上)、分块查找(在有序数组上)以及二叉搜索树查找。所有方法统一返回原数组中的索引;二分与分块通过indexArr映射,二叉树通过节点的idx返回。提供“退出程序”选项。
数据结构
数组:nums[n]原始数据;sortedArr[n]排序副本;indexArr[n]排序位置到原索引的映射。
二叉搜索树:TreeNode { int val; int idx; TreeNode* left; TreeNode* right; }。
常量:MAX为输入规模上限(100000)。
辅助函数
Linear_Search(arr, size, target):顺序扫描比较。
Binary_Search(arr, size, target):在有序数组中二分定位并返回位置。
Block_Search(arr, size, target):按块大小sqrt(size)定位块,块内线性扫描。
Bubble_Sort_With_Index(arr, index, size):冒泡排序,交换元素同时交换index,实现稳定排序与原索引映射。
BST_new/BST_insert/BST_free/BST_Search:构建与查找二叉搜索树,查找返回节点idx(原数组索引)。
核心算法
线性查找:从左到右逐项比较。
二分查找:每轮折半选中点,比较后缩小区间。
分块查找:按块扫描,先用块尾与目标比较确定块,再在块内线性查找。
二叉搜索树查找:按值大小关系在树上左/右移动查找。
预排序:稳定冒泡排序,为二分/分块提供有序数据并维护indexArr以统一索引语义。
初始化与交互
Windows控制台设置为UTF-8。
读取n与n个整数,完成排序并打印有序数组。
循环读取target与choice,按菜单执行查找并输出结果;选择5退出程序。
输入与输出
输入:第一行n;随后读入n个整数;之后循环读入查询值与方法选择。
输出:先打印排序后的数组;每次查询输出“找到了,目标元素的索引为:X”或“未找到目标元素。”。
代码特点
统一索引语义:二分与分块通过indexArr映射回原索引;BST节点直接保存idx。
稳定排序:仅在arr[j] > arr[j+1]时交换,保持相等元素相对次序。
使用C99变长数组,简化输入规模驱动的存储。
BST内存释放完整,避免泄漏;菜单交互支持多次查询与退出。
边界与异常处理
校验n在[1..MAX]范围内。
二分与分块依赖有序数组,程序已在进入查找前完成排序。
BST不平衡,最坏情况下退化为链表;重复值只插入第一次出现的节点,查找返回该值的首次出现索引。
基本输入未做范围与非法字符的深度校验。
时间与空间复杂度
预处理排序:Bubble_Sort_With_Index时间O(n²),额外空间O(n)用于indexArr。
线性查找:时间O(n),空间O(1)。
二分查找:时间O(log n),空间O(1);返回某一匹配位置的原索引(不保证最左)。
分块查找:时间O(√n)(定位块O(√n)+块内线性扫描O(√n)),空间O(1);通常返回该块内第一个匹配的原索引。
二叉搜索树查找:平均时间O(log n),最坏O(n);空间O(n)(节点)。
整体空间:数组O(n)BST O(n)。
可能扩展
将预排序替换为快速排序或qsort,将预处理复杂度优化为O(n log n)。
使用平衡BST或哈希表提高查找性能与一致性;二分查找改为返回最左/最右匹配以满足特定需求。
增加输入范围校验、异常处理与批量查询支持。