2022暑期复习-Day8

选择题

Q1 当一个类的某个函数被说明为 virtual ,则在该类的所有派生类中的同原型函数( )。

A: 只有被重新说明时才识虚函数
B: 只有被重新说明为virtual时才是虚函数
C: 都不是虚函数
D: 都是虚函数

这是多态中的一种特例,虽然在派生类中没有显示说明改函数的virtual的特性,但是派生类会继承基类的成员函数,这样virtual的作用域也被带到了派生类中,所以派生类中的同名函数也具有virtual的特性

答案:D

Q2 关于 C++ 类中 static 成员和对象成员的说法正确的是( )。

A: static 成员变量在对象构造时生成
B: static 成员函数在普通成员函数中无法调用
C: 虚成员函数不可能是static 成员函数
D: static 成员函数不能访问static 成员变量

static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。反过来说,没有在类外初始化的 static 成员变量不能使用。

static成员函数不被对象所独有,所有对象都能调用static函数。

虚函数是不能使用static关键字,主要原因是,虚函数调用需要this指针,而static函数不需要。
从编译的角度来看,static成员函数是在编译时,静态绑定了的,而虚函数是在运行时,动态绑定。

答案:C

Q3 C++ 将父类的析构函数定义为虚函数,下列正确的是( )。

A: 释放父类指针时能正确释放子类对象
B: 释放子类指针时能正确释放父类对象
C: 这样做是错误的
D: 以上全错

主要用途,在释放父类指针时,如果父类指针指向了一个子类对象,那么可以调用子类的析构继而调用父类的析构,删除这个对象,防止内存泄漏问题。

答案:A

Q4 假设 A 为抽象类,下列声明( )是正确的。

A: int fun(A);
B: A Obj;
C: A fun(int);
D: A *p;

有纯虚函数作为成员函数的类叫做抽象类。
抽象类是为了表述一个无法描述事物而留下的接口,这样是也导致未重写纯虚函数的类无法实例化
无法实例化,也意味着不能构造,所以涉及到创建变量的使用都是错误的,而指针不会,指针只是一个指定大小的地址,并不设计资源创建

答案:D

Q5 下面程序的输出结果是()

class A
{
public:
    void foo()
    {
        printf("1");
    } 
    virtual void fun()
    {
        printf("2");
    }
};
class B : public A
{
public:
    void foo()
    {
        printf("3");
    } 
    void fun()
    {
        printf("4");
    }
};
int testmain(void)
{


A a;
B b;
A* p = &a;
p->foo();
p->fun();
p = &b;
p->foo();
p->fun();
A* ptr = (A*)&b;
ptr->foo();
ptr->fun();
return 0;
}

A: 121434
B: 121414
C: 121232
D: 123434

看看指针和函数调用。

基类指针指向基类对象,不涉及多态,调用基类的函数
输出12

基类指针直指向派生类对象,涉及多态,考虑 虚基表
foo函数涉及 隐藏 ,基类指针调用,调用的会是基类的函数,fun函数是多态,调用派生类的函数。输出14

基类指针指向一个派生类强转成基类的对象
强转类型就涉及到切片原理,切片还是切割基类,调用基类的foo函数,同时调用fun函数也涉及到多态的性质。输出14
只有在派生类的作用域中调用foo函数才会输出 3

答案:B

编程题

Q6

在这里插入图片描述
遍历一颗二叉搜索树,最重要的是中序遍历,题目要求头指针指向最小的节点,那就是中序遍历的第一个节点。

同时,中序遍历,将所有节点入栈,使用prev指针和一个cur指针去遍历栈中的元素,建立双向链表。

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;

    Node() {}

    Node(int _val) {
        val = _val;
        left = NULL;
        right = NULL;
    }

    Node(int _val, Node* _left, Node* _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
public:
    Node* treeToDoublyList(Node* root) {
        //中序遍历
        Node* Head=nullptr;
        stack<Node*> st;
        Node* cur = root;
        bool flag = false;
        Node* prev=nullptr;
        while(!st.empty()||cur)
        {
            if(cur)
            {
                st.push(cur);
                cur=cur->left;
            }
            //主要关注栈中的元素
            else
            {
                if(flag==false)
                {
                    flag = true;
                    Head = st.top();
                }
                cur = st.top();
                st.pop();

                cur->left = prev;
                if(prev!=nullptr)
                {
                    prev->right = cur;
                }
                
                if(prev == nullptr)
                    prev = cur;
                else 
                    prev = prev->right;

                cur = cur->right;
                if(cur == nullptr)//处理最后一个节点和头结点
                {
                    prev->right = Head;
                    Head->left = prev;
                }
            }
        }
        return Head;
    }
};

Q7

在这里插入图片描述

最简单的办法就是找到根节点到目标节点的路径,然后两条路径依次遍历,
先保证长度一致,然后再一起遍历节点,最后可以得到一个一样的节点,就算最近公共祖先,最远公共祖先就算整棵树的根节点。

使用后续遍历,完成深度优先搜素,可以找到节点,并记录路径。

class Solution {
public:
    void find_path(stack<TreeNode*>& st,TreeNode* root, TreeNode* p)
    {
        TreeNode* cur = root;
        TreeNode* prev = root;
        st.push(cur);
        while(!st.empty())
        {
            cur = st.top();
            if(cur->left && cur->left!=prev && cur->right!=prev)
            {
                st.push(cur->left);
            }
            else if(cur->right&&cur->right!=prev)
            {
                st.push(cur->right);
            }
            else
            {
                prev = cur;
                if(cur==p)
                {
                    break;
                }
                st.pop();
            }
        }
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> st1;
        stack<TreeNode*> st2;
        //后序遍历完成深度优先搜索路径
        find_path(st1, root, p);
        find_path(st2, root, q);
        while(st1.size()>st2.size())
        {
            st1.pop();
        }
        while(st1.size()<st2.size())
        {
            st2.pop();
        }
        while(st1.top()!=st2.top())
        {
            st1.pop();
            st2.pop();
        }

        return st1.top();
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值