西农数据结构第四次实习题目参考

大家催更也是赶出来了,大家做个参考哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈!!!

T1

以邻接矩阵给出一张以整数编号为顶点的图,其中0表示不相连,1表示相连。按深度和广度优先进行遍历,输出全部结果。要求,遍历时优先较小的顶点。如,若顶点0与顶点2,顶点3,顶点4相连,则优先遍历顶点2

输入描述
顶点个数
邻接矩阵
输出描述
DFS
深度遍历输出
WFS
广度遍历输出
输入
3
0 1 1
1 0 1
1 1 0
输出
DFS
0 1 2
1 0 2
2 0 1
WFS
0 1 2
1 0 2
2 0 1

cpp 复制代码
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

// DFS递归函数
void dfs(int v, const vector<vector<int>>& graph, vector<bool>& visited, vector<int>& result) {
    visited[v] = true;
    result.push_back(v); 
    
    // 获取邻接顶点并排序
    vector<int> neighbors;
    for (int i = 0; i < graph[v].size(); ++i) {
        if (graph[v][i] == 1 && !visited[i]) {
            neighbors.push_back(i); 
        }
    }
    sort(neighbors.begin(),  neighbors.end()); 
    
    for (int u : neighbors) {
        if (!visited[u]) {
            dfs(u, graph, visited, result);
        }
    }
}

// BFS函数
vector<int> bfs(int start, const vector<vector<int>>& graph) {
    int n = graph.size(); 
    vector<bool> visited(n, false);
    queue<int> q;
    vector<int> result;
    
    q.push(start); 
    visited[start] = true;
    
    while (!q.empty())  {
        int v = q.front(); 
        q.pop(); 
        result.push_back(v); 
        
        // 获取邻接顶点并排序
        vector<int> neighbors;
        for (int i = 0; i < n; ++i) {
            if (graph[v][i] == 1 && !visited[i]) {
                neighbors.push_back(i); 
            }
        }
        sort(neighbors.begin(),  neighbors.end()); 
        
        for (int u : neighbors) {
            visited[u] = true;
            q.push(u); 
        }
    }
    
    return result;
}

int main() {
    int n;
    cin >> n;
    
    // 读取邻接矩阵
    vector<vector<int>> graph(n, vector<int>(n));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> graph[i][j];
        }
    }
    
    // 输出DFS结果
    cout << "DFS" << endl;
    for (int start = 0; start < n; ++start) {
        vector<bool> visited(n, false);
        vector<int> result;
        dfs(start, graph, visited, result);
        
        for (int i = 0; i < result.size();  ++i) {
            cout << result[i];
            if (i != result.size()  - 1) cout << " ";
        }
        cout << endl;
    }
    
    // 输出WFS结果
    cout << "WFS" << endl;
    for (int start = 0; start < n; ++start) {
        vector<int> result = bfs(start, graph);
        
        for (int i = 0; i < result.size();  ++i) {
            cout << result[i];
            if (i != result.size()  - 1) cout << " ";
        }
        cout << endl;
    }
    
    return 0;
}

T2

给出一个矩阵,要求以矩阵方式单步输出最小生成树生成过程。要求先输出Prim生成过程(以点0作为起始点),再输出Kruskal,每个矩阵输出后换行。注意,题中矩阵表示无向图
输入描述
结点数
矩阵
输出描述
Prim:
矩阵输出
Kruskal:
矩阵输出
输入
3
0 1 3
1 0 2
3 2 0
输出
Prim:
0 0 0
0 0 0
0 0 0

0 1 0
1 0 0
0 0 0

0 1 0
1 0 2
0 2 0

Kruskal:
0 0 0
0 0 0
0 0 0

0 1 0
1 0 0
0 0 0

0 1 0
1 0 2
0 2 0

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;

struct Edge {
    int u, v, weight;
    Edge(int u_, int v_, int w_) : u(u_), v(v_), weight(w_) {}
    bool operator<(const Edge& other) const {
        return weight < other.weight; 
    }
};

struct UnionFind {
    vector<int> parent;
    UnionFind(int n) {
        parent.resize(n); 
        for (int i = 0; i < n; ++i)
            parent[i] = i;
    }
    
    int find(int x) {
        if (parent[x] != x)
            parent[x] = find(parent[x]);
        return parent[x];
    }
    
    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) return false;
        parent[y] = x;
        return true;
    }
};

void printMatrix(const vector<vector<int>>& mat) {
    int n = mat.size(); 
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cout << mat[i][j];
            if (j != n - 1) cout << " ";
        }
        cout << endl;
    }
    cout << endl; // 每个矩阵后换行
}

// 修正后的Prim算法实现
void prim(int n, const vector<vector<int>>& graph) {
    cout << "Prim:" << endl;
    
    vector<vector<int>> mst(n, vector<int>(n, 0));
    printMatrix(mst); // 初始状态:全0矩阵
    
    vector<bool> inMST(n, false);
    vector<int> key(n, INT_MAX);
    vector<int> parent(n, -1);
    
    key[0] = 0; // 从顶点0开始
    
    for (int count = 0; count < n; ++count) {
        // 找到未在MST中且key值最小的顶点u
        int u = -1;
        int minKey = INT_MAX;
        for (int v = 0; v < n; ++v) {
            if (!inMST[v] && key[v] < minKey) {
                minKey = key[v];
                u = v;
            }
        }
        
        if (u == -1) break; // 图不连通(按题意输入为连通图,此句可省略)
        
        inMST[u] = true;
        
        // 添加边到MST(仅当不是起始顶点0时)
        if (parent[u] != -1) {
            mst[u][parent[u]] = minKey;
            mst[parent[u]][u] = minKey;
            printMatrix(mst); // 输出添加边后的矩阵
        }
        
        // 更新与u相邻的顶点的key值
        for (int v = 0; v < n; ++v) {
            // 确保graph[u][v]是有效边(权值>0),且v未在MST中
            if (graph[u][v] > 0 && !inMST[v] && graph[u][v] < key[v]) {
                key[v] = graph[u][v];
                parent[v] = u;
            }
        }
    }
}

void kruskal(int n, const vector<vector<int>>& graph) {
    cout << "Kruskal:" << endl;
    
    vector<vector<int>> mst(n, vector<int>(n, 0));
    printMatrix(mst);
    
    vector<Edge> edges;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            if (graph[i][j] > 0) {
                edges.emplace_back(i,  j, graph[i][j]);
            }
        }
    }
    
    sort(edges.begin(),  edges.end()); 
    
    UnionFind uf(n);
    int edgesAdded = 0;
    
    for (const Edge& e : edges) {
        if (uf.unite(e.u,  e.v)) {
            mst[e.u][e.v] = e.weight; 
            mst[e.v][e.u] = e.weight; 
            printMatrix(mst);
            edgesAdded++;
            if (edgesAdded == n - 1) break;
        }
    }
}

int main() {
    int n;
    cin >> n;
    
    vector<vector<int>> graph(n, vector<int>(n));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> graph[i][j];
        }
    }
    
    prim(n, graph);
    kruskal(n, graph);
    
    return 0;
}

T3

迷宫是一个二维矩阵,其中0为墙不能通过,1为路可以通过,3为入口,4为出口.要求从入口开始,每个位置上下左右探测,到出口结束,用迪杰斯特拉算法求得最短路径并输出。
输入描述
迷宫高度h 迷官宽度w
迷宫第一行
迷宫第二行
...
迷宫第h 行
输出描述
入口行号1 入口列号1
行号2列号2
行号3列号3
行号4列号4
...
行号n-1 列号n-1
出口行号n 出口列号n
输入
5 6
0 0 0 0 0 0
0 3 1 1 1 0
0 1 1 0 1 0
0 1 1 0 4 0
0 0 0 0 0 0
输出
1 1
1 2
1 3
1 4
2 4
3 4

cpp 复制代码
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
using namespace std;

struct Node {
    int row, col, dist;
    Node(int r, int c, int d) : row(r), col(c), dist(d) {}
    bool operator>(const Node& other) const {
        return dist > other.dist; 
    }
};

int main() {
    int h, w;
    cin >> h >> w;
    
    vector<vector<int>> maze(h, vector<int>(w));
    int start_r = -1, start_c = -1, end_r = -1, end_c = -1;
    
    // 读取迷宫并定位入口和出口
    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            cin >> maze[i][j];
            if (maze[i][j] == 3) {
                start_r = i;
                start_c = j;
            } else if (maze[i][j] == 4) {
                end_r = i;
                end_c = j;
            }
        }
    }
    
    // 初始化距离矩阵和前驱节点矩阵
    vector<vector<int>> dist(h, vector<int>(w, INT_MAX));
    vector<vector<pair<int, int>>> prev(h, vector<pair<int, int>>(w, {-1, -1}));
    
    // 优先队列(小顶堆)
    priority_queue<Node, vector<Node>, greater<Node>> pq;
    
    // 起点初始化
    dist[start_r][start_c] = 0;
    pq.emplace(start_r,  start_c, 0);
    
    // 方向数组:上、右、下、左(按此顺序探测)
    int dr[] = {-1, 0, 1, 0};
    int dc[] = {0, 1, 0, -1};
    
    // 执行迪杰斯特拉算法
    while (!pq.empty())  {
        Node curr = pq.top(); 
        pq.pop(); 
        
        // 到达出口,提前退出
        if (curr.row  == end_r && curr.col  == end_c) {
            break;
        }
        
        // 如果当前距离大于已知最短距离,跳过
        if (curr.dist  > dist[curr.row][curr.col]) {
            continue;
        }
        
        // 按上下左右顺序探测四个方向
        for (int i = 0; i < 4; ++i) {
            int nr = curr.row  + dr[i];
            int nc = curr.col  + dc[i];
            
            // 检查边界和可通行性(0是墙,不能通过)
            if (nr >= 0 && nr < h && nc >= 0 && nc < w && maze[nr][nc] != 0) {
                int new_dist = curr.dist  + 1;
                
                // 如果找到更短路径或相同距离但字典序更小的路径
                if (new_dist < dist[nr][nc] || 
                    (new_dist == dist[nr][nc] && (nr < prev[nr][nc].first || 
                    (nr == prev[nr][nc].first && nc < prev[nr][nc].second)))) {
                    dist[nr][nc] = new_dist;
                    prev[nr][nc] = {curr.row,  curr.col}; 
                    pq.emplace(nr,  nc, new_dist);
                }
            }
        }
    }
    
    // 回溯路径(从出口到入口)
    vector<pair<int, int>> path;
    for (pair<int, int> at = {end_r, end_c}; at.first  != -1; at = prev[at.first][at.second]) {
        path.push_back(at); 
    }
    
    // 反转路径,得到从入口到出口的顺序
    reverse(path.begin(),  path.end()); 
    
    // 输出路径(严格按照示例格式:行号 列号 后接空格和换行)
    for (size_t i = 0; i < path.size();  ++i) {
        // 行号和列号从1开始计数
        cout << path[i].first  << " " << path[i].second ;
        // 每个坐标后添加空格和换行(与示例格式完全一致)
        cout << " " << endl;
    }
    
    return 0;
}

T4

以邻接矩阵给出一张以整数为结点的有向图,其中0表示不是相邻结点,1表示两个结点相连且由当前结点为初始点。利用拓扑排序判断图中是否有环,若有输出YES没有输出NO,
输入描述
结点数邻接矩阵
输出描述
YES/NO
输入
3
0 1 0
1 0 1
1 0 0
输出
YES

cpp 复制代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    // 读取邻接矩阵
    vector<vector<int>> graph(n, vector<int>(n));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> graph[i][j];
        }
    }
    
    // 计算每个节点的入度
    vector<int> inDegree(n, 0);
    for (int j = 0; j < n; ++j) {  // 列代表入边
        for (int i = 0; i < n; ++i) {  // 行代表出边
            if (graph[i][j] == 1) {  // i -> j 有边,j的入度+1
                inDegree[j]++;
            }
        }
    }
    
    // 初始化队列,加入所有入度为0的节点
    queue<int> q;
    for (int i = 0; i < n; ++i) {
        if (inDegree[i] == 0) {
            q.push(i); 
        }
    }
    
    int count = 0;  // 记录已移除的节点数
    while (!q.empty())  {
        int u = q.front(); 
        q.pop(); 
        count++;
        
        // 移除u的所有出边,对应节点入度-1
        for (int v = 0; v < n; ++v) {
            if (graph[u][v] == 1) {  // u -> v 有边
                inDegree[v]--;
                if (inDegree[v] == 0) {
                    q.push(v); 
                }
            }
        }
    }
    
    // 若所有节点都被移除,则无环;否则有环
    if (count == n) {
        cout << "NO" << endl;
    } else {
        cout << "YES" << endl;
    }
    
    return 0;
}

文章最后祝大家数据结构都能考到自己想要的好成绩!!!

相关推荐
kyle~38 分钟前
排序---堆排序(Heap Sort)
数据结构·c++·算法
yesyesido44 分钟前
3D在线魔方模拟器
科技·算法·3d·生活·业界资讯·交友·帅哥
是苏浙1 小时前
蓝桥杯备战day1
算法
汉克老师1 小时前
CCF-NOI2025第一试题目与解析(第二题、序列变换(sequence))
c++·算法·动态规划·noi
hweiyu001 小时前
数据结构:字典
数据结构
断剑zou天涯1 小时前
【算法笔记】KMP算法
java·笔记·算法
程序员东岸1 小时前
《数据结构——排序(下)》分治与超越:快排、归并与计数排序的终极对决
数据结构·c++·经验分享·笔记·学习·算法·排序算法
某林2121 小时前
在slam建图中为何坐标base_link,laser,imu_link是始终在一起的,但是odom 会与这位三个坐标在运行中产生偏差
人工智能·算法
想看一次满天星1 小时前
阿里140-n值纯算
爬虫·python·算法·网络爬虫·阿里140