zoukankan      html  css  js  c++  java
  • 16年面试提问

    2016-2-23面试提问:

    1.什么是句柄?

    句柄是一个32位的证书,是windows在内存中维护的一个对象(窗口等)内存物理地址列表的整数索引。

    句柄是指使用的一个唯一的整数值,用来标识应用程序中的不同对象和同类中的不同的实例。

    2.什么是哈希表,哈希表原理是什么,哈希表的提出主要用来解决什么问题?

    >哈希表最大的优点:把数据的存储和查找消耗的时间大大降低,几乎可以看成是常数时间,而代价仅仅是消耗比较多的内存。

    >什么时候适合应用哈希表?

    某个元素是否在已知集合中,也就是需要高效得数据存储和查找。

    设计一个好的哈希函数很关键,而好的标准就是较低的冲突率和易于实现。

    >基本原理:

    使用一个下标范围都比较大的数组来存储元素,可以设计一个函数,使得每个元素的关键字都与一个函数值(即数组下标)相对应。但不能保证每个元素的关键字与函数值一一对应,不同的元素却计算出相同的函数值,这就产生了冲突。

    3.常用的排序算法。6种,时间复杂度,空间复杂度,稳定度。

    1>冒泡排序。(从后往前比)

    #define MAX_SIZE 10
    typedef struct { int data[MAX_SIZE]; int nLen; }SqList; // 交换SqList中下标为i和j元素。 void swap(SqList *L, int i, int j) { int temp = L->data[i]; L->data[i] = L->data[j]; L->data[j] = temp; } void BubbleSort(SqList *array) { for(int i=0; i<array->nLen-1; ++i) // 比较的次数。下标从0开始算。 { for(int j=array->nLen-2; j>=i; j--) // 从尾部开始往前比较。 { if( array->data[j] > array->data[j+1] ) // 若前者大于后者 { swap(array, j, j+1); } } } } 改进的冒泡排序:添加一个标志位,假如标志位为假,则不进入循环内比较 void BubbleSort2(SqList *array) { bool flag = true; for(int i=0; i<array->nLen-1 && flag; ++i) // 假如flag为0,说明没有变动,不再往下循环比较。 { flag = false; // 初始化为false for(int j=array->nLen-2; j>=i; j--) { if( array->data[j] > array->data[j+1] ) { swap(array, j, j+1); flag = true; // 有改变则置1 } } } }

    2>选择排序。 (从前往后比)

    关键点:从前往后逐个比较,查找最小的小标,再将最小下标的元素与当前位置交换。

    在待排序的n个记录中选择一个最小的记录需要比较n-1次。

    void SelectSort(SqList *array)
    {
        int min;
        for(int i=0; i<array->nLen-1; ++i) // 比较的次数
        {
            min = i;
            for(int j=i+1; j<array->nLen; j++)
            {
                if( array->data[min] > array->data[j] )
                {
                    min = j; // 获取最小值下标
                }
            }
            if(min != i)  // min不等于i,说明找到最小值下标了。
                swap(array, i, min);
        }
    }

    3>直接插入排序。(从2开始,与前一个比较)

    直接插入排序:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。
    // 数组第0位 作为 哨兵

    void InsertSort(SqList *array)
    {
        int i, j;
        for(i=2; i<array->nLen; ++i) // a[0] 哨兵, 也算进 nLen长度里。这里是i<nLen,没有=,否则5个元素,会出现a[5]越界了。
        {
            if( array->data[i] < array->data[i-1] ) // 从2开始比较,跟前一个比较
            {
                array->data[0] = array->data[i]; // 把 较小值 存进 哨兵
                for(j=i-1; array->data[j] > array->data[0]; --j ) // 与哨兵逐一比较, j是自减
                {
                    array->data[j+1] = array->data[j]; // 往后移位 
                }
                array->data[j+1] = array->data[0]; // 赋值给j+1, 将哨兵插入到正确的位置
            }
        }
    }

    4>希尔排序: 将相距某个"增量"的记录组成一个子序列。

    关键不是随便分组后各自排序,而是将相隔某个"增量"的记录组成一个子序列,实现跳跃式的移动,使得排序的效率提高。
    ☆增量的选取非常关键。

    基本排序:小的在前面,大的在后边,不大不小的在中间。

    // 存在 a[0] 作为哨兵
    void ShellSort(SqList *array)
    {
        int i, j;
        int add = array->nLen; // 增量初始化 为 SqList元素个数
        do
        {
            add = add/3 + 1; // 设置增量. 这个值很关键,后续直接影响到排序的效率。
            for(i=add+1; i<array->nLen; ++i)
            {
                if( array->data[i] < array->data[i-add] )
                {
                    array->data[0] = array->data[i]; // 暂存进哨兵
                
                    for(j=i-add; j>0 && array->data[0] < array->data[j]; j -= add) // 哨兵元素 比较小,则互换位置
                    {
                        array->data[j+add] = array->data[j]; // 记录后移
                    }
                    array->data[j+add] = array->data[0]; // 把哨兵值 存入。
                }
            }        
        } while(add > 1);
    }

    5>堆排序。

    6>归并排序。

    7>快速排序

    4.http协议。

    >超文本协议。

    >超文本传输协议URL= “http:” “//” 主机名【":"端口号(可选)】【绝对路径【"?"查询】】。

    >通常使用TCP/IP连接,缺省是80端口。

    http协议请求:包括请求行,消息报头,请求正文。

    http响应:状态行,消息报头,响应正文。

    请求:数据长度,字符集,接受html文本,编码格式,语言,授权,主机host,

    响应:Location重定向,Server服务器类型,

    GET与POST区别?

    ?GET用于获取数据,POST用户发送数据

    ?POST比GET安全。

    ?GET对URL长度有限制,1024,POST没有。

    5.DNS与ARP分别指什么?

     >DNS(Domain Name System):域名系统。使用户不用去记IP数串。每个IP地址都可以有一个主机名。

    通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析。

    >主机名到IP地址的映射有2种方式:

    静态映射:每台设备上都配置主机到IP地址的映射。

    动态映射:建立一套域名解析系统,使用主机名通信的设备时,先到DNS服务器查找对应的IP地址。

    >ARP(Address Resolution Protocol):地址解析协议。是根据IP地址获取物理地址的一个TCP/IP协议。

    6.Socket的类型。

    1>SOCK_STREAM流套接字:读取TCP协议的数据,提供面向连接的、可靠的数据传输服务。该服务能保证数据能够实现无差错无重复发送,并按顺序接收。

    2>SOCK_DGRAM数据报套接字:读取UDP协议的数据,提供一种无连接的服务。不保证数据传输的可靠性。

    3>SOCK_RAW原始套接字:可以读取内核没有处理的IP数据包。

    7.select与epoll的实现,他们的共同点与区别。

    >select几大缺点:相关函数(FD_ZERO,FD_SET,FD_CLR,FD_ISSET)

    1>每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时很大。

    2>每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大。 

    3>select支持的文件描述符数量太小了,默认为1024.

    >epoll

    1>epoll是在每次注册新的事件到epoll句柄中时(EPOLL_CTL_ADD),会把所有的fd拷贝进内核,而不是在epoll_wait时重复拷贝。epoll保证了每个fd在整个过程只会拷贝一次。

    2>epoll只用维护一个队列,看队列是否为空就可以了。epoll只会对活跃的socket进行操作,只有活跃的fd才会主动去调用对应的callback函数。

    3>epoll没有文件描述符的限制。

    区别:

    >select的句柄数目受限(最多同时监听1024个fd,因为内核代码的限制)。epoll则没有,它的限制是最大的打开文件句柄数。

    >select采用的是轮询处理,其中的数据结构类似以个数组的数据结构,而epoll是维护一个队列,直接看队列是否为空就可以。

    8.进程与线程。

    >进程是系统进行资源分配和调度的一个独立单位,线程是进程的一个实体,是CPU调度和分派的基本单位。

    >进程有独立的地址空间。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,线程共享进程的地址空间。

    >一个线程死掉就等于整个进程死掉,所以多进程的程序比多线程的程序健壮,但在进程切换时,耗费资源较大,效率差一点。

    >线程执行开销小,但不利于资源的管理和保护,进程则相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

    SMP:一组处理器(多CPU)之间共享内存子系统以及总线结构。

    9.抓包软件。

     WireShark,HttpWatch。

    10.linux下查看网络流量的命令。

    >nload: (不是系统自带)快速查看总带宽使用情况,无需每个进程的详细情况。

    查看系统端口使用情况

    >netstat 

    netstat -tln 用来查看linux的端口使用情况

    11.如何处理TCP黏包问题。

    >现在主流且有效的做法就是加包头,不要考虑这些不实用的方式了。

    >在发送每个数据包加上一个自定义的数据头,所以都没出现过黏包现象。

    push的作用:对方的包源源不断的发过来,接收方的内核未必收到一个包就通知上层一次,如果包足够频繁,它可以积累一些一块通知上层。push标识就是告诉接收者,这个包尽快上报,最好不要缓存了。接收方看到这个标识,会酌情处理(看协议实现者的心情了)。

    因此,所有的包都加了push,也不能保证不会粘包。

    ===========================

    1.OSI参考模型:物理层,数据链路层,网络层(IP),传输层(TCP,UXP),会话层,表示层,应用层(HTTP,DNS,SMTP)。

    TCP/IP五层模型:物理层,数据链路层,网络层,传输层,应用层。

    2.串口通信(RS232):按位(bit)发送和接收。

    >分为:单工(只能A->B,),半双(A->B,B->A,只能一个方向),全双工(允许双向传输)。

    >将接受的串行数据转换为并行的数据字符传输给CPU器件。

    串口通信最重要的参数是:

    >波特率:衡量符号传输速率的参数。1个起始位,一个停止位,剩下数据位。

    >数据位

    >停止位

    >奇偶校验:四种校错方式:奇,偶,高,低。

    窗口通信编程:串口初始化,打开串口,发送读取数据命令,等待接受数据,数据处理与显示,关闭串口。

    3.JTAG技术

    ========================================

    2016-2-24面试提问:

    1.String的4种构造函数。

    // 构造函数

    String::String(const char * ptr)

    {

      if(ptr == NULL)

      {

        m_pData = new char[1];

        m_pData[0] = '';

      }

      else

      {

        int n = strlen(ptr);

        m_pData = new char[n+1];

        strcpy(m_pData, ptr);

      }

    }

    // 析构函数

    String::~String()

    {

      if(m_pData)

      {

        delete [] m_pData;

        m_pData = NULL;

      }

    }

    // 拷贝构造函数

    String::String(const String & s1)

    {

      int n = strlen(s1.m_pData);

      m_pData = new char[n+1];

      strcpy(m_pData, s1.m_pData);

    }

    // 赋值构造函数

    String & String::operator =(const String & s1)

    {

      if( this  == &s1) // 检查自赋值

        return *this;

      delete [] m_pData;

      int n = strlen(s1.m_pData);

      m_pData = new char[n+1];

      strcpy(m_pData, s1.m_pData);

      return *this;

    }

    2.单链表的插入删除。

    struct Node 

    {

      int data;

      Node * pNext; 

    };

    3.什么是网络字节序、主机字节序?如何转换?

    网络字节序是TCP/IP中规定好的一种数据表示格式,采用大端排序方式。

    主机字节序是指整数在内存中保存的顺序。

    高地址在低字节 大端。

    高地址在高字节 小端。

    如: 0x01020304

            4000   4001   4002  4003

    小      04        03      02       01

    大      01        02      03       04

    htons htonl ntohs ntohl

    h 主机序

    n 网络字节序

    s 短整形

    l 长整形

    4.什么是虚拟内存?

    虚拟内存是计算机系统内存管理的一种技术。当内存消耗完时,系统匀出一部分硬盘空间来充当内存使用,系统将数据移入分页文件来释放RAM。

    5.MFC,API,STL,SSL等等分别代表什么。

    MFC:Microsoft Foundation Classes 微软基础类库。

    API:Application Programming Interface 应用程序编程接口。

    STL:Standard Template Library 标准模板库。分为容器,迭代器,空间配置器,配接器,算法,仿函数。

    SSL:Secure Sockets Layer 安全套接层。利用加密技术,确保数据在网络传输过程中不会被截取及窃听。

    6.memcpy与memmove的区别?

    memcpy是memmove的一个子集。

    唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果正确。memmove内部定义了一个局部数组来作为中间的存储。所以memcpy效率高一点。

    区别是它们处理内存区域重叠(overlapping)的方式不同。

    7.12种常用的设计模式,分别用在什么情景下?

    >简单工厂模式

    >抽象工厂模式

    >工厂模式

    >策略模式

    >装饰模式

    >单例模式

    >代理模式

    >

    x.数据结构查找方法

    1>顺序表查找算法。复杂度O(n)

    // a为数组,n为要查找的数组个数,key为要查找的关键字
    for(int i=0; i<n; ++i)
    {
      if( a[i] == key )
        return i; // 从0开始计数。
    }
    return -1; // 失败返回-1
    
    // 改良的顺序查找算法,添加哨兵。可在数组头部或者尾部添加哨兵。复杂度比上面的有所降低。
    // a为数组,n为要查找的数组个数,key为要查找的关键字
    a[0] = key;
    i = n; // 从尾部开始查找
    while( a[i] != key ) // 因为添加了a[0],所以数组从1开始计数。
    {
      i--;
    }
    return i;

    2>有序表查找。复杂度O(logn)

    >折半查找/二分法查找:前提是记录是有序的。一般是从小到大。

    //
    int binarysearch(int *a, int len, int key)
    {
      int high,low;
      high = len - 1;
      low = 0;
      while(low <= high)
      {
        mid = (low+high)/2;
        if ( key < a[mid] )
          high = mid-1;
        else if ( key > a[mid] )
          low = mid + 1;
        else
          return mid; // 相等,则说明mid为要查找的位置
      }
      return -1; // 失败返回-1
    }

    升级版:

    >插值查找:关键字分布比较平均时适用。极度不平均的分布则不适用。

    关键>>>mid = (low + high )/2 改为 mid = low + (key-a[low])/(a[high]-a[low])*(high-low);

    关键计算公式: (key-a[low])/(a[high]-a[low])

    >斐波那契查找。利用黄金分割原理

    ========================================

    2016-2-25面试提问:

    1.Windows下注册表有什么用?

    2.写一个函数将字符串转换为数字。如"1234"-->1234

    3.数据库的建表,插入,删除,查询语句。

    4.二分法链表的查找。

    5.Windows下进程间通信的方法,共享内存的原理是什么?Linux下进程通信的方法又有什么?

    6.static在3种情况下的作用。

    >在函数内声明

    >在模块内声明

    >在模块内,但不在函数内

    7.继承有什么好处?多态的作用是什么?

    8.int const a 与 const int a; const int *a; int * const a;

    9.

  • 相关阅读:
    LINUX安装NGINX
    CentOS 设置mysql的远程访问
    centos6 mysql 安装与配置
    php读取用友u8采购入库单列表及详细
    php读取用友u8客户档案
    深度linux没有ll等命令的解决办法
    CentOS7下FTP的安装与配置
    虚拟机CentOS6.5搭建samba服务器实现文件共享
    linux 查找php.ini在那个文件夹
    CBE引擎概览
  • 原文地址:https://www.cnblogs.com/sylar-liang/p/5211290.html
Copyright © 2011-2022 走看看