Z字形扫描
源码与注释
初始化一维数组和二维数组的指针,使用全局变量的指针,就懒得传参了
1 2
| int *twoDimensionArray = NULL; int *oneDimensionArray = NULL;
|
确认已经遍历过的数据
1 2 3 4 5 6 7
| int add(int n) { int result = 0; for (int i = 1; i <= n; i++) result += i; return result; }
|
进行扫描的具体过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| void zigzagScan(int n) { int temp = 0;
for (int i = 0; i < n; i++) { if (!i) *oneDimensionArray = *twoDimensionArray; else if (i % 2) { temp = add(i); for (int j = 0; j <= i; j++) *(oneDimensionArray + temp + j) = *(twoDimensionArray + j * n + (i - j)); } else { temp = add(i); for (int j = 0; j <= i; j++) *(oneDimensionArray + temp + j) = *(twoDimensionArray + (i - j) * n + j); } }
for (int i = n; i <= (n - 1) * 2; i++) { if (i == (n - 1) * 2) { temp = add(n) + add(n - 1) - 1; *(oneDimensionArray + temp) = *(twoDimensionArray + (n - 1) * n + n - 1); } else if (!(i % 2)) { temp = add(n) + add(n - 1) - add(2 * n - i - 1); for (int j = 0; j <= 2 * n - i - 2; j++) *(oneDimensionArray + temp + j) = *(twoDimensionArray + (n - 1 - j) * n + (i - (n - 1 - j))); } else { temp = add(n) + add(n - 1) - add(2 * n - i - 1); for (int j = 0; j <= 2 * n - i - 2; j++) *(oneDimensionArray + temp + j) = *(twoDimensionArray + (i - (n - 1 - j)) * n + (n - 1 - j)); } } }
|
main函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| int main() { int n = 0; scanf("%d", &n);
oneDimensionArray = (int *)malloc(n * n * sizeof(int)); twoDimensionArray = (int *)malloc(n * n * sizeof(int));
for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) scanf("%d", twoDimensionArray + i * n + j);
zigzagScan(n);
for (int i = 0; i < n * n; i++) printf("%d ", *(oneDimensionArray + i));
free(oneDimensionArray); free(twoDimensionArray); return 0; }
|
迷宫问题
输入样例
8 8
1 1
8 8
0 0 1 0 0 0 1 0
0 0 1 1 0 0 1 0
0 0 0 0 1 1 0 0
0 1 1 1 0 0 0 0
0 0 0 1 1 0 0 0
0 1 0 0 0 1 0 0
0 1 1 1 0 1 1 0
1 1 0 0 0 0 0 0
输出样例
(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),(4,1,2),(5,1,1),(5,2,1),(5,3,2),(6,3,1),(6,4,1),(6,5,2),(7,5,2),(8,5,1),(8,6,1),(8,7,1),(8,8,1)
个人写法
设置方向与地图状况常量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| enum direction { failed, right, down, left, up }; enum surroundings { uncover, blocked, covered }; surroundings map[105][105] = {uncover}; int m, n;
|
小人的初始化和方向判断
1 2 3 4 5 6 7 8 9 10 11
| typedef struct Axis { int x; int y; surroundings is_right; surroundings is_left; surroundings is_up; surroundings is_down; direction dir; } axis;
|
主函数的输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| axis begin, end, temp; int num; std::stack<axis> track;
std::cin >> m >> n >> begin.x >> begin.y >> end.x >> end.y; begin.x--, begin.y--, end.x--, end.y--;
for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) { std::cin >> num; switch (num) { case 0: map[i][j] = uncover; break; case 1: map[i][j] = blocked; } } temp = begin;
|
进行操作的具体流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| while (true) { temp.dir = right; if (temp.x == end.x && temp.y == end.y) { track.push(temp); break; } temp = judge(temp); temp = direction_confirmed(temp, true); if (temp.dir) { track.push(temp); temp = step_forwards(temp); } else { if (temp.x == begin.x && temp.y == begin.y) break; else { map[temp.x][temp.y] = blocked; temp = track.top(); temp = direction_confirmed(temp, false); track.pop(); } } }
|
由于足迹中的栈弹出来是倒序的,因此需要再来一个栈把它弹成正常顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| if (!track.empty() && track.top().x == end.x && track.top().y == end.y) { std::stack<axis> temp; std::string s; while (!track.empty()) { temp.push(track.top()); track.pop(); } while (!temp.empty()) { s.append("(").append(std::to_string(temp.top().x + 1)).append(",").append(std::to_string(temp.top().y + 1)).append(",").append(std::to_string(temp.top().dir)).append("),"); temp.pop(); } s.pop_back(); std::cout << s << std::endl; } else std::cout << "no" << std::endl;
|
judge函数,用于判断小人周遭情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| axis judge(axis target) {
if (target.y == n - 1) target.is_right = blocked; else target.is_right = map[target.x][target.y + 1];
if (!target.y) target.is_left = blocked; else target.is_left = map[target.x][target.y - 1];
if (!target.x) target.is_up = blocked; else target.is_up = map[target.x - 1][target.y];
if (target.x == m - 1) target.is_down = blocked; else target.is_down = map[target.x + 1][target.y];
return target; }
|
direction_confirm函数,用于判断方向,分向前和回溯两种功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| axis direction_confirmed(axis target, bool is_forward) { surroundings status; if (is_forward) status = uncover; else status = covered;
if (target.is_right == status) target.dir = right; else if (target.is_down == status) target.dir = down; else if (target.is_left == status) target.dir = left; else if (target.is_up == status) target.dir = up; else target.dir = failed; return target; }
|
step_forwards函数,用于向前迈出一步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| axis step_forwards(axis target) { if (target.dir == right) { map[target.x][target.y] = covered; target.y++; } else if (target.dir == down) { map[target.x][target.y] = covered; target.x++; } else if (target.dir == left) { map[target.x][target.y] = covered; target.y--; } else if (target.dir == up) { map[target.x][target.y] = covered; target.x--; } return target; }
|
二叉树的遍历
样例输入
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
样例输出
4 1 6 3 5 7 2
个人写法
以样例为例,解释如何由两种遍历得到唯一指定的树
- 后序遍历的最后一位是根节点为4。
- 在中序遍历中找到4,其左侧是左子树,右侧是右子树。
- 在左子树中,其后序遍历是[2,3,1],中序遍历为[1,2,3]。循环以上操作继续。
但该思路中节省了不少细节,比如如何匹配到对应的字串,如何在子树为空是跳过,等等
首先定义树的节点
1 2 3 4 5 6
| typedef struct TREE { int value; struct TREE *left; struct TREE *right; } node, *tree;
|
进行模糊匹配,只要两个vector
数字相同即可匹配成功,为中序遍历的子树遍历寻找合适的后序遍历。但该匹配方法应该不是最优的。
1 2 3 4 5 6 7 8 9 10
| bool unclear_match(vector<int> v1, vector<int> v2) {
for(auto it = v1.begin(); it != v1.end(); ++it) if(find(v2.begin(), v2.end(), *it) == v2.end()) return false; if(v1.size() != v2.size()) return false; return true; }
|
生成树的主体函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| tree make_tree(vector<int> after, vector<int> middle) { int root_node = after.back(); after.pop_back(); auto index_root_node = find(middle.begin(), middle.end(), root_node); vector<int> left_middle, right_middle, left_after, right_after;
left_middle.assign(middle.begin(), index_root_node); right_middle.assign(index_root_node + 1, middle.end());
auto index_after_node = after.begin(); for(int i = 0; i != left_middle.size() && index_after_node != after.end(); ++index_after_node, ++i); left_after.assign(after.begin(), index_after_node); if(unclear_match(left_middle, left_after)) right_after.assign(index_after_node, after.end()); else { index_after_node = after.begin(); for(int i = 0; i != right_middle.size() && index_after_node != after.end(); ++index_after_node, ++i); left_after.assign(after.begin(), index_after_node); right_after.assign(index_after_node + 1, after.end()); }
tree new_node = (tree)malloc(sizeof(node)); new_node->value = root_node;
if(!left_middle.empty() && !left_after.empty()) new_node->left = make_tree(left_after, left_middle); else new_node->left = nullptr;
if(!right_middle.empty() && !right_after.empty()) new_node->right = make_tree(right_after, right_middle); else new_node->right = nullptr; return new_node; }
|
进行层序遍历。步骤如下
- 指定队列
q
,开始时先往里面弹入根节点。
- 若节点中有子树,则弹入。
- 每次固定弹出一位,直到队列为空为止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| vector<int> print_queue(tree certain_tree) { queue<tree> q; vector<int> v; if(certain_tree) q.push(certain_tree); while(!q.empty()) { tree temp = q.front(); v.push_back(temp->value); if(temp->left) q.push(temp->left); if(temp->right) q.push(temp->right); q.pop(); } return v; }
|
main函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| int main() { vector<int> after, middle, result; int quantity, temp; cin >> quantity; for(int i = 0; i < quantity; i++) { cin >> temp; after.push_back(temp); } for(int i = 0; i < quantity; i++) { cin >> temp; middle.push_back(temp); } tree certain_tree = make_tree(after, middle); result = print_queue(certain_tree); for(auto it = result.begin(); it != result.end(); ++it) cout << *it << " "; return 0; }
|