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.

  • 相关阅读:
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1126 Eulerian Path (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1125 Chain the Ropes (25 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1124 Raffle for Weibo Followers (20 分)
    PAT 甲级 1131 Subway Map (30 分)
    PAT 甲级 1131 Subway Map (30 分)
    AcWing 906. 区间分组 区间贪心
    AcWing 907. 区间覆盖 区间贪心
  • 原文地址:https://www.cnblogs.com/sylar-liang/p/5211290.html
Copyright © 2011-2022 走看看