第1题:红与黑
以下是一个使用深度优先搜索算法(DFS)解决该问题的示例C语言程序:
#include <stdio.h>
#define MAX_SIZE 20
int W, H;
char tiles[MAX_SIZE][MAX_SIZE];
int visited[MAX_SIZE][MAX_SIZE];
int dfs(int x, int y) {
if (x < 0 || x >= W || y < 0 || y >= H || tiles[y][x] != '.' || visited[y][x])
return 0;
visited[y][x] = 1;
int count = 1;
count += dfs(x - 1, y); // 左
count += dfs(x + 1, y); // 右
count += dfs(x, y - 1); // 上
count += dfs(x, y + 1); // 下
return count;
}
int main() {
while (1) {
scanf("%d %d", &W, &H);
if (W == 0 && H == 0)
break;
int start_x, start_y;
for (int i = 0; i < H; i++) {
scanf("%s", tiles[i]);
for (int j = 0; j < W; j++) {
if (tiles[i][j] == '@') {
start_x = j;
start_y = i;
}
}
}
// 初始化visited数组
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
visited[i][j] = 0;
}
}
int result = dfs(start_x, start_y);
printf("%d\n", result);
}
return 0;
}
该程序首先读取输入的W和H,然后读取瓷砖颜色信息,并找到你所站立的黑色瓷砖的位置。接下来,使用深度优先搜索算法从起始位置开始遍历与之相邻的黑色瓷砖,并标记已访问过的瓷砖。最后,统计访问过的瓷砖数量并输出结果。
注意:该程序假设输入是正确的,即输入的瓷砖数量不超过20,且起始位置字符’@'在每个数据集合中唯一出现一次。在实际应用中,你可能需要添加一些错误处理代码来处理无效的输入情况。
第2题:重建二叉树
为了解决该问题,我们可以使用递归的方法来重建二叉树,并输出后序遍历结果。下面是一个使用C语言实现的示例程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct TreeNode {
char val;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
TreeNode* buildTree(char* preorder, char* inorder, int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd)
return NULL;
// 创建根节点
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
root->val = preorder[preStart];
root->left = NULL;
root->right = NULL;
// 在中序遍历中找到根节点的索引
int rootIndex;
for (int i = inStart; i <= inEnd; i++) {
if (inorder[i] == root->val) {
rootIndex = i;
break;
}
}
int leftSubtreeSize = rootIndex - inStart;
// 递归构建左子树和右子树
root->left = buildTree(preorder, inorder, preStart + 1, preStart + leftSubtreeSize, inStart, rootIndex - 1);
root->right = buildTree(preorder, inorder, preStart + leftSubtreeSize + 1, preEnd, rootIndex + 1, inEnd);
return root;
}
void postorderTraversal(TreeNode* root) {
if (root == NULL)
return;
// 后序遍历:左子树 -> 右子树 -> 根节点
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%c", root->val);
}
int main() {
char preorder[100];
char inorder[100];
while (scanf("%s %s", preorder, inorder) != EOF) {
int n = strlen(preorder);
TreeNode* root = buildTree(preorder, inorder, 0, n - 1, 0, n - 1);
postorderTraversal(root);
printf("\n");
}
return 0;
}
该程序首先定义了一个树节点的结构体 TreeNode
,其中包含节点的值 val
,以及左子树和右子树的指针。然后,使用递归的方式实现了 buildTree
函数,该函数根据前序遍历和中序遍历的结果构建二叉树。最后,使用递归的方式实现了 postorderTraversal
函数,用于后序遍历输出结果。
在 main
函数中,程序通过循环读取输入的前序遍历和中序遍历字符串,并调用 buildTree
构建二叉树,然后调用 postorderTraversal
函数输出后序遍历结果。
请注意,该程序假设输入的前序遍历和中序遍历结果是合法的,且每个字符在遍历结果中都是唯一的。在实际应用中,你可能需要添加一些错误处理代码来处理无效的输入情况。
第3题:快速堆猪
为了解决该问题,我们可以使用堆数据结构来实现猪的叠放和查询最轻猪的操作。下面是一个使用C语言实现的示例程序:
#include <stdio.h>
#include <stdlib.h>
typedef struct Pig {
int weight;
struct Pig* next;
} Pig;
Pig* top = NULL;
void push(int weight) {
Pig* newPig = (Pig*)malloc(sizeof(Pig));
newPig->weight = weight;
newPig->next = top;
top = newPig;
}
void pop() {
if (top == NULL)
return;
Pig* temp = top;
top = top->next;
free(temp);
}
int min() {
if (top == NULL)
return -1;
int minWeight = top->weight;
Pig* current = top->next;
while (current != NULL) {
if (current->weight < minWeight)
minWeight = current->weight;
current = current->next;
}
return minWeight;
}
int main() {
char operation[10];
int weight;
while (scanf("%s", operation) != EOF) {
if (strcmp(operation, "push") == 0) {
scanf("%d", &weight);
push(weight);
} else if (strcmp(operation, "pop") == 0) {
pop();
} else if (strcmp(operation, "min") == 0) {
int minWeight = min();
if (minWeight != -1)
printf("%d\n", minWeight);
}
}
return 0;
}
该程序定义了一个猪的结构体 Pig
,其中包含猪的重量 weight
和指向堆顶下一头猪的指针 next
。然后,使用链表来实现堆数据结构,使用 top
指针来指示堆顶的猪。
程序实现了 push
函数用于将一头新猪叠放在堆顶, pop
函数用于将堆顶的猪赶走, min
函数用于查询猪堆里最轻的猪的重量。
在 main
函数中,程序通过循环读取输入的操作和猪的重量,并调用相应的函数来执行操作和查询最轻猪的重量。
请注意,该程序假设输入的操作合法且符合要求。在实际应用中,你可能需要添加一些错误处理代码来处理无效的输入情况。
第4题:表达式·表达式树·表达式求值
为了解决这个问题,我们可以使用递归的方式构建表达式树,并且同时输出逆波兰表达式。下面是一个使用C语言实现的示例程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
char data;
struct Node* left;
struct Node* right;
} Node;
Node* createNode(char data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
int isOperator(char c) {
if (c == '+' || c == '-' || c == '*' || c == '/')
return 1;
return 0;
}
int isOperand(char c) {
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
return 1;
return 0;
}
void buildExpressionTree(char* infix, int n, char** variables, int* values, Node** root) {
int i;
Node* stack[n];
int top = -1;
for (i = 0; i < strlen(infix); i++) {
if (isOperand(infix[i])) {
int j;
char variable = infix[i];
int value = 0;
for (j = 0; j < n; j++) {
if (variables[j][0] == variable) {
value = values[j];
break;
}
}
Node* operandNode = createNode(variable);
stack[++top] = operandNode;
} else if (isOperator(infix[i])) {
Node* operatorNode = createNode(infix[i]);
operatorNode->right = stack[top--];
operatorNode->left = stack[top--];
stack[++top] = operatorNode;
}
}
*root = stack[top--];
}
void postOrderTraversal(Node* root) {
if (root != NULL) {
postOrderTraversal(root->left);
postOrderTraversal(root->right);
printf("%c", root->data);
}
}
int evaluateExpressionTree(Node* root) {
if (root != NULL) {
if (isOperand(root->data)) {
return root->data - 'a' + 1;
} else {
int leftValue = evaluateExpressionTree(root->left);
int rightValue = evaluateExpressionTree(root->right);
switch (root->data) {
case '+':
return leftValue + rightValue;
case '-':
return leftValue - rightValue;
case '*':
return leftValue * rightValue;
case '/':
return leftValue / rightValue;
}
}
}
return 0;
}
void printExpressionTree(Node* root, int level) {
int i;
if (root == NULL)
return;
printExpressionTree(root->right, level + 1);
for (i = 0; i < level - 1; i++)
printf(" ");
if (level > 0)
printf("/");
printf("%c\n", root->data);
printExpressionTree(root->left, level + 1);
}
int main() {
char infix[51];
int n;
int i;
scanf("%s", infix);
scanf("%d", &n);
char* variables[n];
int values[n];
for (i = 0; i < n; i++) {
variables[i] = (char*)malloc(2 * sizeof(char));
scanf("%s %d", variables[i], &values[i]);
}
Node* root = NULL;
buildExpressionTree(infix, n, variables, values, &root);
postOrderTraversal(root);
printf("\n");
printExpressionTree(root, 0);
int result = evaluateExpressionTree(root);
printf("%d\n", result);
return 0;
}
程序中定义了一个表示表达式树的结构体 Node
,其中包含数据 data
和指向左子树和右子树的指针 left
和 right
。函数 createNode
用于创建一个新的节点。
程序中使用栈来构建表达式树。在 buildExpressionTree
函数中,我们遍历中缀表达式的每个字符,如果遇到操作数,则创建一个叶子节点,并将其压入栈中;如果遇到操作符,则创建一个新节点,并将栈顶的两个节点分别设置为新节点的左右子树,然后将新节点压入栈中。最后,栈顶即为整个表达式树的根节点。
在 postOrderTraversal
函数中,我们使用后根遍历输出逆波兰表达式。
在 evaluateExpressionTree
函数中,我们使用递归的方式计算表达式树的值。如果节点是操作数,则返回变量对应的值;如果节点是操作符,则递归计算左子树和右子树的值,并根据操作符进行相应的运算。
在 printExpressionTree
函数中,我们使用递归的方式打印表达式树的显示。通过先打印右子树、根节点、再打印左子树的顺序,可以得到正确的显示结果。
在 main
函数中,我们读取输入的中缀表达式、变量数量和变量值,并调用 buildExpressionTree
函数构建表达式树。然后,分别调用 postOrderTraversal
函数输出逆波兰表达式、printExpressionTree
函数输出表达式树的显示,并调用 evaluateExpressionTree
函数计算表达式树的值,并输出结果。
请注意,该程序假设输入的中缀表达式合法且符合要求。在实际应用中,你可能需要添加一些错误处理代码来处理无效的输入情况。