2005年解析
一、填空题解析
顺序表插入移动元素数 n-i+1(在第i个位置前插入需要移动后面所有元素)
循环队列队头指针指向 队头元素的前一个位置(通常实现方式)
双向链表指针域 前驱结点(prior),后继结点(next)
下三角矩阵存储位置 i*(i-1)/2 + j(行序为主存储,i≥j)
二叉树结点总数 89(30叶结点+30单孩子结点+29双孩子结点)
无向连通图最少边数 n-1(树的情况)
邻接表结点总数 2e(无向图每条边存储两次)
插入排序最佳比较次数 n-1(已有序时只需比较n-1次)
装填因子影响 冲突概率越小(装填因子=元素数/表长)
二、判断题解析
| 题号 | 答案 | 解析 |
|---|---|---|
| 1 | × | 线性表也可用链表存储 |
| 2 | × | 链式存储逻辑顺序与物理顺序可能不一致 |
| 3 | √ | 二维数组可视为元素为线性表的线性表 |
| 4 | × | 不是所有结构都支持这三种操作 |
| 5 | × | 删除后重新插入可能改变树结构 |
| 6 | √ | 中序最后结点也是前序最后结点 |
| 7 | √ | 无向图邻接矩阵对称 |
| 8 | × | 仅连通图才能一次遍历访问所有结点 |
| 9 | √ | 快排每趟确定一个元素最终位置 |
| 10 | √ | 理想散列表查找O(1) |
三、单选题解析
| 题号 | 答案 | 解析 |
|---|---|---|
| 1 | C | 算法分析主要目的是分析效率 |
| 2 | C | dceab不可能是栈的输出序列 |
| 3 | A | 最少比较n-1次(一个表全小于另一个) |
| 4 | B | 二叉排序树中序遍历有序 |
| 5 | D | 前序后序相反⇒高度等于结点数 |
| 6 | A | 最小生成树可能不唯一 |
| 7 | D | 归并排序需要O(n)辅助空间 |
| 8 | D | 基本有序时插入排序最有效 |
| 9 | B | 二分查找平均比较次数37/12 |
| 10 | C | 分块查找适合动态变化且较快 |
四、解析题解析
1. 树与二叉树转换
原始树结构:
A
/ | \
B C D
/ \ / \
E F G H
/ / \
K I J
/ \
L M
/
N
/
O
对应的二叉树:
A
/
B
/ \
E C
\ \
F D
/ /
K G
/ \
I H
/ \
L J
/
M
/
N
/
O
2. Huffman树与编码
Huffman树构建过程:
1. 合并A(2),B(3)→5
2. 合并5,C(5)→10
3. 合并D(7),E(11)→18
4. 合并F(13),G(17)→30
5. 合并H(19),I(23)→42
6. 合并J(31),K(37)→68
7. 合并L(41),68→109
8. 合并10,18→28
9. 合并28,30→58
10. 合并42,58→100
11. 合并100,109→209
Huffman编码:
A: 11110
B: 11111
C: 1110
D: 100
E: 101
F: 110
G: 111
H: 00
I: 01
J: 011
K: 010
L: 10
3. Prim算法最小生成树
邻接矩阵表示的图:
0 1 2 3 4 5
0 ∞ 7 ∞ 9 ∞ ∞
1 7 ∞ 5 ∞ ∞ 6
2 ∞ 5 ∞ 1 ∞ 2
3 9 ∞ 1 ∞ ∞ 1
4 ∞ ∞ ∞ ∞ ∞ ∞
5 ∞ 6 2 1 ∞ ∞
Prim算法步骤(从顶点0开始):
1. 选择边(0,1,7)
2. 选择边(1,2,5)
3. 选择边(2,3,1)
4. 选择边(3,5,1)
5. 选择边(5,4,∞) - 无连接,无法继续
实际最小生成树总权值:7+5+1+1=14
4. 部分排序算法选择
最佳方法: 堆排序 原因: 只需建立大小为k的小根堆,时间复杂度O(nlogk) 比较次数分析: 对序列{57,40,38,11,13,34,48,75,25,6,19,9,7}
- 建堆(前4个):11,13,38,40 → 3次比较
- 调整堆:
- 34>11,不调整
- 48>11,不调整
- 75>11,不调整
- 25>11,不调整
- 6<11,替换并调整:6,13,38,40 → 2次比较
- 19>6,不调整
- 9>6,不调整
- 7>6,不调整 总比较次数≈15次
五、算法设计题
1. 双向链表频度排序算法
typedef struct DuLNode {
ElemType data;
int freq;
struct DuLNode *prior, *next;
} DuLNode, *DuLinkList;
void Locate(DuLinkList L, ElemType x) {
DuLNode *p = L->next, *q;
while(p && p->data != x) p = p->next;
if(!p) return; // 未找到
p->freq++;
// 从当前位置向前查找插入位置
q = p->prior;
while(q != L && q->freq < p->freq) q = q->prior;
// 将p结点移动到q之后
if(p->prior != q) {
// 先删除p
p->prior->next = p->next;
if(p->next) p->next->prior = p->prior;
// 再插入到q之后
p->next = q->next;
if(q->next) q->next->prior = p;
q->next = p;
p->prior = q;
}
}
2. 无向图中通过给定顶点的简单回路
int visited[MAX_VERTEX_NUM]; // 访问标记数组
int path[MAX_VERTEX_NUM]; // 路径记录
int path_index = 0; // 路径索引
void DFSCircuit(ALGraph G, int v, int start) {
visited[v] = 1;
path[path_index++] = v;
ArcNode *p = G.vertices[v].firstarc;
while(p != NULL) {
int w = p->adjvex;
if(!visited[w]) {
DFSCircuit(G, w, start);
}
else if(w == start && path_index > 2) {
// 找到回路,输出路径
printf("回路: ");
for(int i=0; i<path_index; i++)
printf("%d ", path[i]);
printf("%d\n", start);
}
p = p->nextarc;
}
// 回溯
visited[v] = 0;
path_index--;
}
void FindCircuit(ALGraph G, int v) {
for(int i=0; i<G.vexnum; i++)
visited[i] = 0;
path_index = 0;
DFSCircuit(G, v, v);
}
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 AuraX
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果