笔者按去年实际考试内容,回忆并编写本博客。建议大家收藏,如对考试有帮助,记得回来丢个赞。如果对部分内容有疑问可以直接留言。
去年第一题、第二题为顺序表,第三题为排序,第四题主要考dfs。第五题为压轴题考了三叉霍夫曼树
数据结构期末机考大致有5道题,难度由浅入深,根据去年实际体验,大致人均AC2~3题。前三题的难度会相对比较简单,主要需要重点复习下顺序表,链表等线性结构,排序算法(选择,插入,冒泡…),哈希查找。第四题一般会相对难一些,需要重点复习一下图的dfs,bfs。最短路径的Dijkstra算法以及最小生成树Prim和Kruskal算法。最后一题会比较难,可能会遇到比较复杂的数据结构,机考过程中前四题全部AC后可以试一下。
这部分的两道题大概是去年机考的第四第五题(前面题记不清了),凭着回忆把题目重新写了下,又做了一遍,自己敲了标程。
按输入顺序输出无向图的所有割点。(割点:在一个无向图中,如果删除某个顶点以及与该顶点相关联的所有边后,图的连通分量增多,就称这个点为割点。)
输入
第一行为测试数据数。对于每组测试数据,第一个整数 n n n表示该无向图的大小。接下来 n n n个字符串为每个顶点的名称。接下来输入一个 n ∗ n n*n n∗n的方阵作为无向图,0表示两个顶点之间不存在边,1表示两个顶点之间存在边。
输出
输出各个割点的名称。每组测试数据的输出占一行。如果没有割点,则输出No!
样例输入
4
8
0 1 2 3 4 5 6 7
0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0
0 0 0 1 1 1 1 0
0 1 1 0 0 0 0 0
0 1 1 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 1 0 0 0 0 1
0 0 0 0 0 0 1 0
3
A B C
0 1 0
1 0 1
0 1 0
5
a b c d e
0 1 0 0 1
1 0 1 1 0
0 1 0 0 0
0 1 0 0 0
1 0 0 0 0
6
v1 v2 v3 v4 v5 v6
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
样例输出
2 6
B
a b
No!
参考代码
#include
#include
using namespace std;
bool *isVisited;
int **matrix;
int n = 0;
//node:当前深搜点 cur:当前判断的割点
void dfs(int node, int cur) {
isVisited[node] = true;
for (int i = 0; i < n; i++) {
if ((!isVisited[i]) && i != cur && node != cur && (matrix[node][i] || matrix[i][node])) {
dfs(i, cur);
}
}
}
int main() {
int t;
cin >> t;
while (t--) {
cin >> n;
vector<string> vertex;
vector<string> res;
isVisited = new bool[n];
matrix = new int *[n];
for (int i = 0; i < n; i++) {
string temp;
cin >> temp;
vertex.push_back(temp);
matrix[i] = new int[n];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> matrix[i][j];
}
}
int cc = 0;
for (int i = 0; i < n; i++) {
if (!isVisited[i]) {
cc++;
dfs(i, -1);
}
}
for (int i = 0; i < n; i++) {
int temp = 0;
for (int ii = 0; ii < n; ii++) {
isVisited[ii] = false;
}
for (int j = 0; j < n; j++) {
if (!isVisited[j]) {
temp++;
dfs(j, i);
}
}
if (temp > cc + 1) {
res.push_back(vertex[i]);
}
}
if (res.empty()) {
cout << "No!" << endl;
} else {
for (int i = 0; i < res.size(); i++) {
cout << res[i] << " ";
}
cout << endl;
}
}
return 0;
}
给定n个权值,根据这些权值构造三叉霍夫曼树,并进行三叉霍夫曼编码。
输入
第一行输入 t t t,表示有 t 个 t个 t个测试实例
第二行先输入 n n n,表示第1个实例有 n n n个权值,接着输入 n n n个权值,权值全是小于1万的正整数
依此类推
输出:
逐行输出每个权值对应的编码,格式如下:权值-编码
即每行先输出1个权值,再输出一个短划线,再输出对应编码,接着下一行输出下一个权值和编码。
以此类推
样例输入
2
8
1 5 3 4 9 2 6 10
10
1 5 9 6 3 4 7 8 11 12
样例输出
1-100
5-01
3-102
4-00
9-11
2-101
6-02
10-12
1-010
5-120
9-02
6-121
3-011
4-012
7-122
8-00
11-10
12-11
样例代码
#include
#include
#include
#include
using namespace std;
struct Node {
int value;
int father = -1;
int son[3];
string code;
Node(int value, int father) {
this->value = value;
this->father = father;
for (int i = 0; i < 3; i++) {
this->son[i] = -1;
}
}
};
bool cmp(const Node &a, const Node &b) {
return (a.father == -1 ? a.value : (9999 + a.value)) < (b.father == -1 ? b.value : (9999 + b.value));
}
int getNode(int num, vector<Node> nodeList) {
for (int i = 0; i < nodeList.size(); i++) {
if (nodeList[i].value == num && nodeList[i].father == -1) {
return i;
}
}
return -1;
}
void dfs(int index, vector<Node> &nodeList) {
if (index == -1) {
return;
}
for (int i = 0; i < 3; i++) {
if (nodeList[index].son[i] == -1) {
continue;
}
nodeList[nodeList[index].son[i]].code += (nodeList[index].code + to_string(i));
dfs(nodeList[index].son[i], nodeList);
}
}
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<Node> nodeList;
for (int i = 0; i < n; i++) {
int temp;
cin >> temp;
nodeList.push_back(Node(temp, -1));
}
while (true) {
vector<Node> temp(nodeList);
sort(temp.begin(), temp.end(), cmp);
if (temp[2].father == -1) {
nodeList.push_back(Node(0, -1));
for (int i = 0; i < 3; i++) {
nodeList[nodeList.size() - 1].value += temp[i].value;
nodeList[nodeList.size() - 1].son[i] = getNode(temp[i].value, nodeList);
nodeList[getNode(temp[i].value, nodeList)].father = nodeList.size() - 1;
}
continue;
} else if (temp[1].father == -1) {
nodeList.push_back(Node(0, -1));
for (int i = 0; i < 2; i++) {
nodeList[nodeList.size() - 1].value += temp[i].value;
nodeList[nodeList.size() - 1].son[i] = getNode(temp[i].value, nodeList);
nodeList[getNode(temp[i].value, nodeList)].father = nodeList.size() - 1;
}
break;
} else {
break;
}
}
dfs(nodeList.size() - 1, nodeList);
for (int i = 0; i < n; i++) {
cout << nodeList[i].value << "-" << nodeList[i].code << endl;
}
}
return 0;
}
笔试篇按上课讲课顺序,以章节为单位进行组织
j j j | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
模式串 | a | b | a | c | a | b | a | a | a | d |
n e x t [ j ] next[j] next[j] | 0 | 1 | 1 | 2 | 1 | 2 | 3 | 4 | 2 | 2 |
n e x t v a l [ j ] nextval[j] nextval[j] | 0 | 1 | 0 | 2 | 0 | 1 | 0 | 4 | 2 | 2 |
无向图:邻接点,度,关联
无向完全图: 1 2 n ( n − 1 ) \frac{1}{2}n(n-1) 21n(n−1)条边
有向图:邻接点,入度,出度,关联
有向完全图: n ( n − 1 ) n(n-1) n(n−1)条边
稀疏图,稠密图
连通,连通图,连通分量
强连通,强连通图,强连通分量
图的表示:邻接矩阵,邻接表(逆邻接表)
稠密图用邻接矩阵存储,稀疏图用邻接表存储
图的遍历:dfs,bfs
dfs:栈实现,先根遍历推广 邻接矩阵 O ( n 2 ) O(n^2) O(n2) 邻接表 O ( n + e ) O(n+e) O(n+e)
bfs:队列实现,数层次遍历 邻接矩阵 O ( n 2 ) O(n^2) O(n2) 邻接表 O ( n + e ) O(n+e) O(n+e)
连通分量
生成树(bfs生成树,dfs生成树)=》生成森林
最小生成树
AOV网
最短路径
查找表:静态查找表,动态查找表
关键字:主关键字(唯一),次关键字(不唯一)
静态表:顺序表,有序表(折半查找,插值查找),索引顺序表,斐波那契查找
动态表:二叉排序树,平衡二叉树,B树,散列表
评价标准:平均查找长度:ASL
顺序表与链表:遍历逐个找
索引查找表:先根据索引找到记录所在的块,再从块中找
哨兵法:省略对下标越界的检查,提高算法执行速度
折半查找(二分查找)
索引顺序表
二叉排序树
平衡二叉树(AVL树)
B树(多路平衡查找树)
B+树
哈希
排序
笔试题记不清了,只记得去年笔试附加题考了十字链表
记得去年考数据结构时候焦头烂额,笔试前一天晚上通宵一晚整理复习了一本书。当时困得要死,好在后来结果差强人意。现在把当时笔记重新整理下分享出来,方便大家复习。大家加油嗷!!!