下图中所使用的数据结构是( )。图示依次执行“压入 A、压入 B、弹出 B、压入 C”。
A:栈。「压入 A、压入 B、弹出 B、压入 C」是后进先出(LIFO),是栈的典型操作序列;队列是先进先出(FIFO),不符合。
对于入栈顺序为 a, b, c, d, e 的序列,下列( )不是合法的出栈序列。
D:c, d, a, e, b。a,b,c,d,e 入栈后栈底→顶为 a,b,c,d,e;出 c,d 后栈顶为 b,要出 a 需 b 已出,但序列中 b 还没出,所以 c,d,a,e,b 不合法;A/B/C 均合法。
表达式 a*(b+c)*d 的后缀表达式为( ),其中 * 和 + 是运算符。
B:abc+d。中缀转后缀:运算顺序等价于先算 (b+c) 再乘 a 再乘 d。压 a、压 b、压 c、+→(b+c)、→a(b+c)、压 d、*→最终 abc+d。
有 个元素,按照 、、、、、 的顺序进入栈 S,请问下列哪个出栈序列是非法的( )。
C:3 4 6 5 2 1。6,5,4,3,2,1 入栈后顶为 1;要 6 先出栈则需先出 5,4,3,2,1,但 6 在 5 之后入栈,不可能在 5 之前出,故非法;A/B/D 均合法。
对表达式 a+(b-c)*d 的前缀表达式为( ),其中 +、-、* 是运算符。
B:+a*-bcd。先 (b-c)→-bcd;再 →-bcd;最后 +a→+a*-bcd。
以下对数据结构的表述不恰当的一项为:( )。
D:栈与队列存在本质不同,无法用栈实现队列——错误。双栈(输入栈+输出栈)可模拟队列,所有队列操作均可用双栈实现。
后缀表达式 6 2 3 + - 3 8 2 / + * 2 ^ 3 + 对应的中缀表达式是( )。
A:((6-(2+3))*(3+8/2))^2+3。后缀转中缀:2 3 + = 2+3;6 ... - = 6-(2+3);8 2 / = 8/2;3 ... + = 3+8/2;… * = ...^2;+3 = 最后 +3。
给定一个空栈,支持入栈和出栈操作。若入栈操作的元素依次是 1 2 3 4 5 6,其中 1 最先入栈、6 最后入栈,下面哪种出栈顺序是不可能的?( )
D:1,3,5,2,4,6。1 入出 → 2,3 入出栈(栈 3,2,1→3,2,1+4,5,6→出 6,5,4,3,2,1 可,但 1,3,5,2,4,6: 1 出栈后栈 2,3,4,5,6,要 3 在 2 前出需 2 已出但 2 在 1 后入栈不可能,故非法)。
对假设栈 S 和队列 Q 的初始状态为空。存在 e1~e6 六个互不相同的数据,每个数据按照进栈 S、出栈 S、进队列 Q、出队列 Q 的顺序操作,不同数据间的操作可能会交错。已知栈 S 中依次有数据 e1、e2、e3、e4、e5 和 e6 进栈,队列 Q 依次有数据 e2、e4、e3、e6、e5 和 e1 出队列。则栈 S 的容量至少是( )个数据。
B:3。操作序列:e1,e2 入栈(2)→e2 出队→e3 入栈(2)→e4 入栈(3)→e4 出队→e3 出队→e5,e6 入栈(3)→e6,e5,e1 出队;栈深最大 3。
给定一个初始为空的整数栈 和一个空的队列 。我们按顺序处理输入的整数队列 。对于队列 中的每一个数,执行以下规则:如果该数是奇数,则将其压入栈 ;如果该数是偶数,且栈 非空,则弹出一个栈顶元素,并加入到队列 的末尾;如果该数是偶数,且栈 为空,则不进行任何操作。当队列 中的所有数都处理完毕后,队列 的内容是什么?( )
D:分治。归并是分治典型(分→治→合)。
在程序运行过程中,如果递归调用的层数过多,会因为( )引发错误。
A:每次函数调用都会在系统栈压入栈帧保存参数、局部变量和返回地址,递归层数过多会耗尽栈空间造成栈溢出;堆、队列、链表空间与递归调用层数无关。
有关下面 C++ 代码的说法,正确的是( )。
01#include <iostream> 02using namespace std; 03 04class ManyData { 05 int * __data; 06 int head, tail, capacity; 07public: 08 ManyData(int cap) { 09 capacity = cap; 10 __data = new int[capacity]; 11 head = tail = 0; 12 } 13 void push(int val) { 14 __data[tail++] = val; 15 } 16 int pop() { 17 return __data[--tail]; 18 } 19 int size() { 20 return tail - head; 21 } 22}; 23int main() { 24 auto myData = ManyData(100); 25 myData.push(1); 26 myData.push(2); 27 myData.push(3); 28 myData.push(100); 29 cout << myData.size() << endl; 30 cout << myData.pop() << endl; 31 return 0; 32}
D:正确。push/pop 未做容量与越界检查,装满后继续 push 会越界写、空时 pop 读到未初始化数据,增加异常处理可避免运行或逻辑错误;pop 从尾部取,是栈不是队列;__data 私有,类外访问报错,A、B、C 均错。
给定一个空栈,执行以下操作序列:
操作序列:push(1), push(2), push(3), pop(), pop(), push(4), push(5), pop()
最终栈中的元素是( )。
D:模拟栈:压入 1、2、3 后弹出两次(3、2)剩 [1],压入 4、5 再弹一次(5)剩 [1,4],最终栈中元素为 1,4。
栈的基本操作包括入栈(push)和出栈(pop)。
A:正确。栈是后进先出(LIFO)结构,push 在栈顶压入元素、pop 弹出栈顶元素,入栈与出栈是栈的两个基本操作,其余如取栈顶都是辅助操作。
向一个栈顶为 hs 的链式栈中插入一个指针为 s 的结点时,应执行( )。
B:头插法入栈:新结点 s 的 next 指向原栈顶 hs,再把栈顶指针更新为 s,即 s->next=hs; hs=s。
在栈数据结构中,元素的添加和删除是按照什么原则进行的?
B:先进后出。栈只允许在栈顶进行插入和删除,后压入的元素先被弹出,即 LIFO 原则;先进先出是队列的原则,与栈相反,故不能选 A。
采用如下代码实现检查输入的字符串括号是否匹配,横线上应填入的代码为( )。
01#include <iostream> 02#include <stack> 03#include <string> 04 05using namespace std; 06 07bool is_valid(string s) { 08 stack<char> st; 09 char top; 10 11 for (char& ch : s) { 12 if (ch == '(' || ch == '{' || ch == '[') { 13 st.push(ch); // 左括号入栈 14 } 15 else 16 { 17 if (st.empty()) 18 return false; 19 ____________ // 在此处填入代码 20 if ((ch == ')' && top != '(') || 21 (ch == '}' && top != '{') || 22 (ch == ']' && top != '[')) { 23 return false; 24 } 25 } 26 } 27 28 return st.empty(); // 栈为空则说明所有括号匹配成功 29}
A:遇到右括号先取栈顶 top=st.top() 再 st.pop() 弹出,随后与当前右括号配对比较;B 先 pop 再取 top 会取到下一个元素,C、D 用 front 对栈无效。
栈是一种线性结构,可通过数组或链表来实现。二者相比,数组实现占用的内存较少,链表实现的入队和出队操作的时间复杂度较低。
B:错误。数组实现与链表实现的入栈出栈都是 O(1),操作复杂度相同;数组可能预分配较多空间,链表每结点还多存指针,内存也未必更省。
阅读以下代码,下面哪一项是正确的?
01void processData() { 02 stack<int> s; 03 queue<int> q; 04 for (int i = 1; i <= 5; ++i) { 05 s.push(i); 06 q.push(i); 07 } 08 while (!s.empty()) { 09 cout << "Stack pop: " << s.top() << endl; 10 s.pop(); 11 } 12 while (!q.empty()) { 13 cout << "Queue pop: " << q.front() << endl; 14 q.pop(); 15 } 16}
B:栈是后进先出,1~5 依次压入后弹出顺序为 5 4 3 2 1;队列是先进先出,弹出顺序为 1 2 3 4 5,二者输出顺序相反。
栈中元素的插入和删除操作都在栈的顶端进行,所以方便用单向链表实现。
A:正确。栈的插入与删除都发生在栈顶,单向链表在表头做头插、头删都是 O(1),无需前驱指针,实现简单方便,故用单向链表合适。
栈中元素的插入和删除操作都在栈的顶端进行,所以方便用双向链表比单向链表更合适实现。
B:错误。栈的操作只在栈顶一端进行,单向链表头插头删已是 O(1);双向链表多余的 prev 指针毫无用处,不能说更合适。
以下代码判断括号是否匹配,请在横线处填入代码。
01bool isBalanced(string s) { 02 stack<char> st; 03 for (char c : s) { 04 if (c == '(' || c == '[' || c == '{') { 05 st.push(c); 06 } else { 07 if (st.empty()) return false; // 无括号匹配 08 char top = st.top(); 09 st.pop(); 10 if ((c == ')' && top != '(') || 11 (c == ']' && top != '[') || 12 (c == '}' && top != '{')) { 13 return false; 14 } 15 } 16 } 17 return ____________; // 在此处填入代码 18}
C:全部字符处理完后,若栈空说明每个右括号都配到了左括号、且没有多余左括号,故返回 st.empty();返回 true/false 固定值无法反映栈中剩余括号。
以下关于栈和队列的代码,执行后输出是()。
01stack<int> s; 02queue<int> q; 03 04for (int i = 1; i <= 3; ++i) { 05 s.push(i); 06 q.push(i); 07} 08cout << s.top() << " " << q.front() << endl;
B:3 1。栈后进先出,压入 1,2,3 后栈顶是 3,s.top() 输出 3;队列先进先出,队首是 1,q.front() 输出 1。
栈的操作特点是()。
B:先进后出。栈只在栈顶插入删除,后进栈的元素先出栈,即 LIFO;先进先出是队列、随机访问是数组、双端进出是双端队列。
在 C++ STL 中,栈(std::stack)的 pop 操作返回栈顶元素并移除它。
B:错误。STL 的 stack::pop() 只移除栈顶元素,返回类型是 void 不返回值;要取栈顶元素必须先调用 top()。
某文本编辑器把用户输入的字符依次压入栈 S。用户依次输入 A、B、C、D 后,用户按了两次撤销(每次撤销,弹出栈顶一个字符)。此时栈从栈底到栈顶的内容是()。
A:栈底到栈顶依次压入 A、B、C、D,两次撤销各弹出一个栈顶元素:先弹 D 再弹 C,剩余 A、B,故栈底到栈顶为 A B。
函数调用管理可用栈来管理。
A:正确。函数调用用调用栈(call stack)管理:后调用的函数先返回,嵌套调用与返回顺序符合栈的后进先出特性。,符合 LIFO 特性。
在以下计算机系统应用场景中,最适合使用循环队列的是()。
D:生产者和消费者问题中的共享缓冲区用循环队列实现数据缓冲最合适;函数调用、表达式求值用栈,优先级调度用优先队列。,各选最合适结构。
某文本编辑器把用户输入的字符依次压入栈 S 。用户依次输入 X, Y, Z, W 后,连续执行两次撤销操作。每次撤销都会弹出栈顶一个字符。此时栈从栈底到栈顶的内容是( )。
A:栈底到栈顶依次为 X、Y、Z、W,两次撤销各弹栈顶一次:先弹 W 再弹 Z,剩余 X、Y,故栈底到栈顶为 X Y。,即为 X Y。
在 C++ STL 中, stack 的 pop() 函数会返回栈顶元素并将其删除。
B:错误。STL 中 stack::pop() 只删除栈顶元素,返回类型为 void 不返回元素;需先用 top() 获取栈顶值。
递归调用在运行时会由于层数过多导致程序崩溃,可以通过循环配合栈缓解这一问题。
对。递归层数过深会耗尽系统调用栈导致程序崩溃;改用显式栈加循环来模拟递归过程,可把栈放到堆上(空间更大),避免栈溢出,做法可行,故对。
个不同元素依次入栈的出栈序列数与将 个不同元素划分成若干非空子集的方案数相等。
B:错误。n 个元素出栈序列数是卡特兰数 Cₙ,划分成非空子集数是贝尔数 Bₙ;n=4 时 C₄=14 而 B₄=15,仅在 n≤3 时巧合相等。
将个元素按 1,2,3,4的顺序入栈,在该过程中可随时插入出栈操作。下列序列中不可能作为出栈序列的是( )。
D:3 出栈时 1、2 必已入栈且 2 在 1 上方,3 出栈后栈顶是 2,下一出栈只能是 2 或先入 4 再出 4,不可能先出 1;其余三项均可实现。