栈和队列
题目1
回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法判断给定字符序列是否是回文(提示:将一半字符入栈)
【算法思想】
- 初始化一个空栈。
- 将字符串前半部分的字符依次入栈。
- 确定后半部分的起始位置,若字符串长度为奇数,则跳过中间字符。
- 从后半部分的起始位置开始,依次将字符与栈顶字符比较:
- 如果所有字符都匹配,则字符串是回文;
- 如果有任意一个字符不匹配,则字符串不是回文。
- 输出判断结果。
// 判断字符串是否是回文
int isPalindrome(const char *str) {
int len = strlen(str);
Stack stack;
initStack(&stack);
// 将前半部分字符入栈
for (int i = 0; i < len / 2; i++) {
push(&stack, str[i]);
}
// 如果字符串长度为奇数,跳过中间字符
int startIndex = (len % 2 == 0) ? len / 2 : len / 2 + 1;
// 比较后半部分字符与栈顶字符
for (int i = startIndex; i < len; i++) {
char topChar = pop(&stack);
if (topChar != str[i]) {
return 0; // 不是回文
}
}
return 1; // 是回文
}
题目2
假设以数组 Q[m] 存放循环队列的元素,同时设置一个标志域名 tag,以 tag == 0 和 tag == 1 来区别头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“满”。试编写与此结构相应的插入(EnQueue)和删除(DeQueue)算法。
算法思想: 在循环队列中,增设一个 tag 类型的整型变量,进队时置 tag 为 1,出队时置 tag 为 0(因为入队操作可能导致队满,只有出队操作可能会导致队空)。队列 Q 初始化时,置 tag == 0,front == rear == 0。这样队列的 4 要素如下:
队空条件:Q.front == Q.rear && Q.tag == 0 队满条件:Q.front == Q.rear && Q.tag == 1 进队操作:Q.data[Q.rear] = x; Q.rear = (Q.rear + 1) % MaxSize; Q.tag = 1; 出队操作:x = Q.data[Q.front]; Q.front = (Q.front + 1) % MaxSize; Q.tag = 0;
// 进队操作
int EnQueue(Queue *Q, int x) {
if (IsFull(*Q)) {
printf("Queue is full!\n");
return 0;
}
Q->data[Q->rear] = x;
Q->rear = (Q->rear + 1) % MaxSize;
Q->tag = 1;
return 1;
}
// 出队操作
int DeQueue(Queue *Q, int *x) {
if (IsEmpty(*Q)) {
printf("Queue is empty!\n");
return 0;
}
*x = Q->data[Q->front];
Q->front = (Q->front + 1) % MaxSize;
Q->tag = 0;
return 1;
}
题目3
设计一个算法判断输入的表达式中括号是否配对(假设只含有左右圆括号)
算法思想
判断一个表达式中的括号是否配对是一个典型的栈应用问题。栈是一种后进先出的数据结构,非常适合处理这种配对问题。算法思想如下:
创建一个空栈。
遍历输入的表达式:
如果遇到左括号 ‘(’,将其压入栈中。
如果遇到右括号 ‘)’
,检查栈是否为空:
- 如果栈为空,说明没有相应的左括号与之配对,表达式不配对,返回 false。
- 如果栈不为空,从栈顶弹出一个左括号与之配对。
遍历结束后,检查栈是否为空:
- 如果栈为空,说明所有的左括号都有相应的右括号配对,返回 true。
- 如果栈不为空,说明有多余的左括号没有配对,返回 false。
// 检查表达式中的括号是否配对
bool areParenthesesBalanced(char* expr) {
int length = 0;
while (expr[length] != '\0') {
length++;
}
Stack* stack = createStack(length);
for (int i = 0; i < length; i++) {
if (expr[i] == '(') {
push(stack, expr[i]);
} else if (expr[i] == ')') {
if (isEmpty(stack)) {
return false; // 栈为空,没有与之配对的左括号
}
pop(stack);
}
}
bool balanced = isEmpty(stack);
free(stack->array);
free(stack);
return balanced;
}
题目4
假设表达式中允许包含三种括号:圆括号,方括号,大括号。试着编写一个算法判断表达式中的括号是否正确匹配
为了处理包含三种括号(圆括号、方括号、大括号)的表达式配对问题,可以对每种括号类型分别进行处理。总体的算法思想与之前的类似,但需要进行更复杂的匹配检查:
创建一个空栈。
遍历输入的表达式:
如果遇到左括号
'('
,'['
,'{'
,将其压入栈中。如果遇到右括号
')'
,']'
,'}'
检查栈是否为空:
- 如果栈为空,说明没有相应的左括号与之配对,表达式不配对,返回 false。
- 如果栈不为空,从栈顶弹出一个左括号并检查是否与当前右括号配对。如果不匹配,返回 false。
遍历结束后,检查栈是否为空:
- 如果栈为空,说明所有的左括号都有相应的右括号配对,返回 true。
- 如果栈不为空,说明有多余的左括号没有配对,返回 false。
// 检查括号是否匹配
bool isMatchingPair(char character1, char character2) {
return (character1 == '(' && character2 == ')') ||
(character1 == '[' && character2 == ']') ||
(character1 == '{' && character2 == '}');
}
// 检查表达式中的括号是否配对
bool areParenthesesBalanced(char* expr) {
int length = 0;
while (expr[length] != '\0') {
length++;
}
Stack* stack = createStack(length);
for (int i = 0; i < length; i++) {
if (expr[i] == '(' || expr[i] == '[' || expr[i] == '{') {
push(stack, expr[i]);
} else if (expr[i] == ')' || expr[i] == ']' || expr[i] == '}') {
if (isEmpty(stack)) {
return false; // 栈为空,没有与之配对的左括号
} else if (!isMatchingPair(pop(stack), expr[i])) {
return false; // 栈顶左括号与当前右括号不匹配
}
}
}
bool balanced = isEmpty(stack);
free(stack->array);
free(stack);
return balanced;
}