某外企c++面试题目

  1. 重建二叉树。
#include 
#include 
#include 
using namespace std;

struct TreeNode_t
{
     
    int val;
    struct TreeNode_t *left;
    struct TreeNode_t *right;
    TreeNode_t(int val):val(val),left(nullptr),
    right(nullptr){
     }
};

TreeNode_t *Reconstruct(vector<int> preOrder,vector<int> inOrder)
{
     
    //寻找头结点
    if(preOrder.size() == 0)
        return nullptr;
    int index = 0;
    int gen = preOrder[0];
    TreeNode_t *root = new TreeNode_t(gen);
    for (int i = 0; i < preOrder.size(); i++)
    {
     
        if (gen == inOrder[i]){
     
            index = i;
            break;
        }
    }
    vector<int> left_inOrder;
    vector<int> left_preOrder;
    vector<int> right_inOrder;
    vector<int> right_preOrder;
    for (int i = 0; i < index; i++)
    {
     
        left_preOrder.push_back(preOrder[i+1]);
        left_inOrder.push_back(inOrder[i]);
    }

    for (int i = index + 1; i < preOrder.size(); i++)
    {
     
        right_preOrder.push_back(preOrder[i]);
        right_inOrder.push_back(inOrder[i]);
    }
    root->left = Reconstruct(left_preOrder,left_inOrder);
    root->right = Reconstruct(right_preOrder,right_inOrder);
    return root;
}
void preOrderPrintf(TreeNode_t *root)
{
     
    if (root == nullptr)
        return;
    printf("%d ",root->val);
    if (root->left != nullptr)
        preOrderPrintf(root->left);
    
    if (root->right != nullptr)
        preOrderPrintf(root->right);
}

void inOrderPrintf(TreeNode_t *root)
{
     
    if (root == nullptr)
            return;
    if (root->left != nullptr)
        inOrderPrintf(root->left);
    printf("%d ",root->val);
    if (root->right != nullptr)
        inOrderPrintf(root->right);
}
//重建二叉树
int main(int argc,char **argv)
{
     
    vector<int> pre = {
     1,2,4,7,3,5,6,8};
    vector<int> in =  {
     4,7,2,1,5,3,8,6};

    TreeNode_t *root = Reconstruct(pre,in);
    preOrderPrintf(root);
    printf("\n");
    inOrderPrintf(root);
    printf("\n");
}

编译命令行g++ -o Reconstruct Reconstruct.cpp -std=c++11。

  1. 判断一个链表是否有环。
bool HasCycle(List*head)
{
     
    if(!head)
        return false;
    List *fast = head;
    List *slow = head;
    while (fast != nullptr && slow != nullptr)
    {
     
        if(slow == fast)
            return true;
        slow = slow->next;
        if(fast->next != nullptr)
            fast = fast->next->next;
    }
    return false;
}
  1. socket编程中Listen中第二个参数的含义。
    首先Tcp建立连接需要三次挥手:
    某外企c++面试题目_第1张图片
    在服务器监听过程中,系统维持了两个队列:
    (1). 未完成队列:当有TCP请求到来时,即3次握手中的syn分节发送来时,会在未完成队列中增加一项。
    (2). 已完成队列:当三次握手建立起来后,未完成队列里的项会移动到已完成的队列中,accept()会从已连接的队列中取走已完成的连接。
    listen中的第二个参数backlog就是未完成队列的长度,可以控制一段时间内系统接受连接的数量,及时拒绝掉一部分处理不过来的请求。防止盲等待。类似有点雪崩处理的感觉。listen的第二个参数。跟系统的连接数量没有任何关系。相当于设置一个瞬间能够处理的阈值。一般情况下都会去开启 syncookie。所以其实现在已经可以不太关系listen的第二个值了。
  2. 介绍一下多线程编程中的条件变量。
    条件变量是利用线程间共享的全局变量进行同步的一种机制, 主要包括两个动作: 一个线程等待"条件变量的条件成立"而挂起; 另一个线程使"条件成立"(给出条件成立信号). 为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。相关函数如下:
    int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);//初始化函数
    int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);//等待目标变量
    int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
    int pthread_cond_destroy(pthread_cond_t *cond);//销毁条件变量
    int pthread_cond_signal(pthread_cond_t *cond);
    int pthread_cond_broadcast(pthread_cond_t *cond); //以广播的方式唤醒所有等待目标条件变量的线程
  3. Linux的虚拟内存。
    虚拟内存是现代操作系统为了扩大内存的寻址空间而出现的技术。在现代的操作系统中,进程之间的内存空间是相互独立的,所以可以使每一个进程独享整个的虚拟内存空间。程序每次访问的实际都是虚拟空间的地址,这个时候就需要把虚拟地址翻译为真正的物理地址。所有的进程都共享一个物理空间,但是每个进程只是把自己需要的虚拟空间映射到物理内存中。操作系统通过页表来管理物理内存和虚拟内存之间的映射关系。当程序需要申请一块内存空间,实际上分配的是虚拟内存空间,只有当程序真正需要访问物理内存的时候,产生缺页异常,把需要的数据从实际的物理空间拷贝到内存空间。这个过程就是内存页的换入换出。同时当内存空间满了,则需要将一部分最近最少被使用的内存页换出到磁盘。
    优点:既然每个进程的内存空间都是一致而且固定的,所以链接器在链接可执行文件时,可以设定内存地址,而不用去管这些数据最终实际的内存地址,这是有独立内存空间的好处; 当不同的进程使用同样的代码时,比如库文件中的代码,物理内存中可以只存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了,节省内存;在程序需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用碎片。
  4. 动态链接和静态链接。
  5. 生产者消费者模型编程实现。

#include 
#include 
#include 
#include 

typedef struct msg_s
{
     
    int num;
    struct msg_s *next;
}msg_t;

msg_t *head = NULL;
msg_t *mp = NULL;

pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thread_producer(void *arg)
{
     
    printf("producer start\n");
    while (1)
    {
     
        printf("start produce\n");
        mp = (msg_t*)malloc(sizeof(msg_t));
        mp->num = rand()%1000;

        pthread_mutex_lock(&mutex);
        mp->next = head;
        head = mp;
        pthread_cond_signal(&has_product);
        pthread_mutex_unlock(&mutex);
        printf("finish produce\n");
        sleep(5);
    }
}

void *thread_comsumer(void *arg)
{
     
    while (1)
    {
     
        
        pthread_mutex_lock(&mutex);
        while (head == NULL)
        {
     
            printf("comsumer wait....\n");
            pthread_cond_wait(&has_product,&mutex);
        }
        printf("comsumer start\n");
        mp = head;
        head = head->next;
        pthread_mutex_unlock(&mutex);
        free(mp);
        mp = NULL;
        sleep(1);
    }
    return NULL;
}
int main()
{
     
    pthread_t pid,cid;
    srand(time(NULL));

    pthread_create(&pid,NULL,thread_producer,NULL);
    pthread_create(&cid,NULL,thread_comsumer,NULL);

    pthread_join(pid,NULL);
    pthread_join(pid,NULL);
    return 0;
}

参考链接:
10. https://www.cnblogs.com/ztteng/p/5147156.html。
11. https://blog.csdn.net/kongxian2007/article/details/49153801。
12. https://www.cnblogs.com/panchanggui/p/9288389.html。
13. https://blog.csdn.net/qq_38410730/article/details/81036768
14. https://www.cnblogs.com/biyeymyhjob/archive/2012/07/20/2601204.html。

你可能感兴趣的:(面试)