[C++]一些list,stack和queue选择题和编程题

这时我们学完后的应用

一、选择题

1.下面有关vector和list的区别,描述错误的是( )

A.vector拥有一段连续的内存空间,因此支持随机存取,如果需要高效的随机存取,应该使用vector

B.list拥有一段不连续的内存空间,如果需要大量的插入和删除,应该使用list

C.vector<int>::iterator支持"+"、"+="、"<"等操作符

D.list<int>::iterator则不支持"+"、"+="、"<"等操作符运算,但是支持了[ ]运算符

这里我们之前见过了list不支持[]进行下标的随机访问

解析:

A.如果想大量随机读取数据操作,vector是首选的容器

B.如果想大量的插入和删除数据,list效率较高,是首选

C.由于vector底层是连续空间,其迭代器就是相应类型的指针,所以支持对应的操作

D.list迭代器不支持[]运算符

2.以下代码实现了从表中删除重复项的功能,请选择其中空白行应填入的正确代码( )

cpp 复制代码
template<typename T>
void removeDuplicates(list<T> &aList)
{
    T curValue;
    list<T>::iterator cur, p;
    cur = aList.begin();
    while (cur != aList.end())
    {
        curValue = *cur;
        _____________//空白行
        while (p != aList.end())
        {
            if (*p == curValue)
            {
               ___________________ //空白行
            }
            else
            {
                p++;
            }
        }
    }
}

A. p=cur+1;aList.erase(p++);
B.p=++cur; p == cur ? cur = p = aList.erase(p) : p = aList.erase(p);
C.p=cur+1;aList.erase(p);
D.p=++cur;aList.erase(p);

这题很简单吧,选择B

这题考到了我们之前说过的一个重点------迭代器失效

我们说过

当使用一个容器的insert或者erase函数通过迭代器插入或删除元素"可能"会导致迭代器失效

iterator失效主要有两种情况:

1、iterator变量已经变成了"野指针",对它进行*,++,--都会引起程序内存操作异常;

2、iterator所指向的变量已经不是你所以为的那个变量了。
解析:

迭代p需要迭代不重复节点的下一节点,重要的是cur迭代器需要往下迭代,因此cur需要往前移动,二答案A C的cur都不会改变,空白行2是当需要找到重复值时进行节点删除,当删除时当前迭代器会失效,因此需要将迭代器p往后迭代,所以答案为 B

3.以下程序输出结果为( )

cpp 复制代码
int main()
{
	int ar[] = { 0,1, 2, 3, 4,  5, 6, 7, 8, 9 };
	int n = sizeof(ar) / sizeof(int);
	list<int> mylist(ar, ar+n); 
	list<int>::iterator pos = find(mylist.begin(), mylist.end(), 5);
	reverse(mylist.begin(), pos);
	reverse(pos, mylist.end());
	list<int>::const_reverse_iterator crit = mylist.crbegin();
	while(crit != mylist.crend())
	{
		cout<<*crit<<" ";
		++crit;
	}
	cout<<endl;
}

A.4 3 2 1 0 5 6 7 8 9

B.0 1 2 3 4 9 8 7 6 5

C.5 6 7 8 9 0 1 2 3 4

D.5 6 7 8 9 4 3 2 1 0

这题很简单,我们只需要理清楚对应的函数的应用即可

解析:list<int>::iterator pos = find(mylist.begin(), mylist.end(), 5); //找到5的位置

reverse(mylist.begin(), pos);//逆置0 1 2 3 4 为 4 3 2 1 0

reverse(pos, mylist.end()); //逆置5 6 7 8 9 为 9 8 7 6 5

逆置完成之后其数据为:4 3 2 1 0 9 8 7 6 5

list<int>::const_reverse_iterator crit = mylist.crbegin(); //反向迭代器进行反向访问

while(crit != mylist.crend()){}

所以答案为:5 6 7 8 9 0 1 2 3 4

C答案

4.下面程序的输出结果正确的是( )

cpp 复制代码
int main(
{
int array[] = { 1, 2, 3, 4, 0, 5, 6, 7, 8, 9 };
int n = sizeof(array) / sizeof(int);
list<int> mylist(array, array+n);
auto it = mylist.begin();
while (it != mylist.end())
{
if(* it != 0)
cout<<* it<<" ";
else
it = mylist.erase(it);
++it;
}
return 0;
}

A.1 2 3 4 5 6 7 8 9

B. 1 2 3 4 6 7 8 9

C.程序运行崩溃

D.1 2 3 4 0 5 6 7 8

这个就是对当前程序分析没什么好说的,选B

解析:程序在使用迭代器取值时,如果不等于0就进行打印,为0时不打印并删除当前节点,注意erase()函数删除后,迭代器it向后移动一位,指向下一个元素。所以答案为 B

5.对于list有迭代器it, 当erase(it)后,说法错误的是( )

A.当前迭代器it失效

B.it前面的迭代器仍然有效

C.it后面的迭代器失效

D.it后面的迭代器仍然有效

还是对于迭代器失效的概念的考察,选C

解析:删除节点后,只有指向当前节点的迭代器失效了,其前后的迭代器仍然有效,因为底层为不连续空间,只有被删除的 节点才会失效, 所以答案为 C

6.下面有关vector和list的区别,描述错误的是( )

A.vector拥有一段连续的内存空间,因此支持随机存取,如果需要高效的随机读取,应该使用vector

B.list拥有一段不连续的内存空间,如果需要大量的插入和删除,应该使用list

C.vector<int>::iterator支持"+"、"+="、"<"等操作符

D.list<int>::iterator则不支持"+"、"+="、"<"等操作符运算,但是支持了[]运算符

解析:

A.如果想大量随机读取数据操作,vector是首选的容器

B.如果想大量的插入和删除数据,list效率较高,是首选

C.由于vector底层是连续空间,其迭代器就是相应类型的指针,所以支持对应的操作

D.list迭代器不支持[]运算符

7.下面有关vector和list的区别,描述正确的是( )

A.两者在尾部插入的效率一样高

B.两者在头部插入的效率一样高

C.两者都提供了push_back和push_front方法

D.两者都提供了迭代器,且迭代器都支持随机访问

解析:

A.vector在尾部插入数据不需要移动数据,list为双向循环链表也很容易找到尾部,因此两者在尾部插入数据效率相同

B.vector头部插入效率极其低,需要移动大量数据

C.vector由于在头部插入数据效率很低,所以没有提供push_front方法

D.list不支持随机访问

8.下列代码的运行结果是( )

cpp 复制代码
void main()
{
    stack<char> S;
    char x,y;
    x='n';y='g';
    S.push(x);S.push('i');S.push(y);
    S.pop();S.push('r');S.push('t');S.push(x);
    S.pop();S.push('s');
    while(!S.empty())
	{
		x = S.top();
		S.pop();
		cout<<x;
	};
	cout<<y;
}

A.gstrin

B.string

C.srting

D.stirng
解析:

S.push(x);S.push('i');S.push(y); 入栈了字母"nig" 左边栈底 右边栈顶S.pop();S.push('r');S.push('t');S.push(x); 字母g出栈,然后入栈字母"rtn",此时栈数据为"nirtn"

S.pop();S.push('s');字母n出栈,s入栈,最终的栈数据为nirts

while(!S.empty()){} 栈不空出栈打印,按相反顺讯出栈,所以打印结果为:strin

cout<<y;最后还打印了字母g

所以答案为B

9.下列代码的运行结果是( )

cpp 复制代码
void main()
{
    queue<char> Q;
    char x,y;
    x='n';y='g';
    Q.push(x);Q.push('i');Q.push(y);
    Q.pop();Q.push('r');Q.push('t');Q.push(x);
    Q.pop();Q.push('s');
    while(!Q.empty())
	{
		x = Q.front();
		Q.pop();
		cout<<x;
	};
	cout<<y;
}

A.gstrin

B.grtnsg

C.srting

D.stirng

解析:

Q.push(x);Q.push('i');Q.push(y); 入队数据为:nig 左边对头,右边队尾

Q.pop();Q.push('r');Q.push('t');Q.push(x); n出队,rtn入队,队里数据为:igrtn

Q.pop();Q.push('s'); i出队,s入队,队里数据为:grtns

while(!Q.empty()){} 队不空,在出队打印为:grtns

cout<<y; 最后在打印一个g

故答案为:B

以下是一个二叉树的遍历算法,queue是FIFO队列,请参考下面的二叉树,根节点是root,正确的输出是( )

1

2 3

4 5 6 7

cpp 复制代码
queue.push(root);
while(!queue.empty())
{
    node = queue.top();
    queue.pop();                             
    output(node->value)    //输出节点对应数字

     if(node->left)
         queue.push(node->left);
     if(node->right)
         queue.push(node->right);   
}

A.1376254

B.1245367

C.1234567

D.1327654

这题很简单,此题是一个层次遍历的伪代码,能够看出是层次遍历,其结果就迎刃而解,答案 C

二、编程题

1.最小栈

本题主要是要理解理解栈结构先进后出的性质。

思路:

  • 我们只需要设计一个数据结构,使得每个元素 a 与其相应的最小值 m 时刻保持一一对应。因此我们可以使用一个辅助栈,与元素栈同步插入与删除,用于存储与每个元素对应的最小值。
  • 当一个元素要入栈时,我们取当前辅助栈的栈顶存储的最小值,与当前元素比较得出最小值,将这个最小值插入辅助栈中;
  • 当一个元素要出栈时,我们把辅助栈的栈顶元素也一并弹出;
  • 在任意一个时刻,栈内元素的最小值就存储在辅助栈的栈顶元素中。
cpp 复制代码
class MinStack {
    stack<int> x_stack;
    stack<int> min_stack;
public:
    MinStack() {
        min_stack.push(INT_MAX);
    }
    
    void push(int x) {
        x_stack.push(x);
        min_stack.push(min(min_stack.top(), x));
    }
    
    void pop() {
        x_stack.pop();
        min_stack.pop();
    }
    
    int top() {
        return x_stack.top();
    }
    
    int getMin() {
        return min_stack.top();
    }
};

思路来源:力扣官方题解

2.栈的弹出压入序列

这题我们也是使用辅助栈

思路:

题目要我们判断两个序列是否符合入栈出栈的次序,我们就可以用一个栈来模拟。对于入栈序列,只要栈为空,序列肯定要依次入栈。那什么时候出来呢?自然是遇到一个元素等于当前的出栈序列的元素,那我们就放弃入栈,让它先出来。

cpp 复制代码
class Solution {
public:
    bool IsPopOrder(vector<int> pushV,vector<int> popV) {
        int n = pushV.size();
        //辅助栈
        stack<int> s;
        //遍历入栈的下标
        int j = 0;
        //遍历出栈的数组
        for(int i = 0; i < n; i++){
            //入栈:栈为空或者栈顶不等于出栈数组
            while(j < n && (s.empty() || s.top() != popV[i])){
                s.push(pushV[j]);
                j++;
            }
            //栈顶等于出栈数组
            if(s.top() == popV[i])
                s.pop();
            //不匹配序列
            else
                return false;
        }
        return true;
    }
};

思路来源:牛客官方题解

相关推荐
数据小爬虫@2 分钟前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
ZJ_.4 分钟前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps
Narutolxy9 分钟前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin
XiaoLeisj15 分钟前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
Hello.Reader16 分钟前
全面解析 Golang Gin 框架
开发语言·golang·gin
禁默27 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
yuyanjingtao30 分钟前
CCF-GESP 等级考试 2023年9月认证C++四级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
Code哈哈笑37 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
程序猿进阶40 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
qq_4336184442 分钟前
shell 编程(二)
开发语言·bash·shell