华三面试
发布日期:2021-05-19 20:28:46 浏览次数:19 分类:精选文章

本文共 4530 字,大约阅读时间需要 15 分钟。

问题 1: 死锁及其解决方案

死锁是多个进程因竞争资源而未能进一步推进的状态。在多线程或多进程环境中,当资源竞争导致进程无法继续操作时,可能会发生死锁。死锁的产生有以下几个必要条件:

  • 互斥条件:只有一个进程能访问特定的资源。
  • 请求和保持条件:进程必须在某些资源的使用上获得特定顺序。
  • 不会剥夺条件:其余进程无法获得资源估计。
  • 等待条件:其中一个进程被阻塞,等待其他进程完成操作。
  • 为了避免死锁,可以采取以下措施:采用并发事务的统一顺序,避免用户交互操作,并将事务限制在一个批处理中进行。


    问题 2: 大端与小端字节序

    大端字节序:高地址存放低字节,低地址存放高字节。

    小端字节序:低地址存放低字节,高地址存放高字节。

    在网络环境中,通常使用大端字节序,因为它是互联网通信中的标准。


    问题3: 哈希表的原理与实现

    哈希表是一种通过键值对应的数据结构,允许O(1)时间复杂的数据存取。其核心是有效的散列函数,确保关键码最小化冲突。常见散列方法包括:

  • 直接定址法:直接将键值映射到数组位置。
  • 平方取中法:通过位操作将可能冲突的键值分布到表中。
  • 折叠法:将高位和低位交换位置。
  • 随机数法:利用随机数生成散列地址。
  • 除留余数法:通过一定数学规则生成散列位。

  • 问题4: 函数memset的实现

    void *memset(void *src, int c, size_t count) {
    assert(src != NULL);
    char *tmpsrc = (char *)src;
    while (count--) {
    *tmpsrc++ = (char)c;
    }
    return src;
    }

    This function copies the character c to the first count bytes of the memory region pointed to by src.


    问题5: 双链表插入节点

    以下是插入节点的函数实现:

    TYPE * insert(TYPE * head, TYPE * pi) {
    TYPE * pb = head, * pf;
    if (head == NULL) {
    head = pi;
    pi->prior = head;
    pi->next = head;
    } else {
    while (pi->num > pb->num && pb->next != head) {
    pf = pb;
    pb = pb->next;
    }
    if (pi->num <= pb->num) {
    if (head == pb) {
    pi->next = pb;
    pi->prior = head->prior;
    pb->prior->next = pi;
    head = pi;
    } else {
    pf->next = pi;
    pi->prior = pf;
    pb->prior = pi;
    pi->next = pb;
    }
    } else {
    pb->next = pi;
    pi->next = head;
    pi->prior = pb;
    head->prior = pi;
    }
    }
    return head;
    }

    问题6: 排序算法概述

  • 冒泡法

    • 从数组头开始,每次交换相邻元素直至无需交换。
    void bubble(int *a, int n) {
    int i, j, temp;
    for (i = 0; i < n - 1; i++) {
    for (j = i + 1; j < n; j++) {
    if (a[i] > a[j]) {
    temp = a[i];
    a[i] = a[j];
    a[j] = temp;
    }
    }
    }
    }
  • 选择法

    • 在数组中选择最小值,将其交换至当前位置。
    void choise(int *a, int n) {
    int i, j, min, temp;
    for (i = 0; i < n - 1; i++) {
    min = i;
    for (j = i + 1; j < n; j++) {
    if (a[min] > a[j]) {
    min = j;
    }
    }
    if (i != min) {
    temp = a[i];
    a[i] = a[min];
    a[min] = temp;
    }
    }
    }
  • 插入法

    • 将数组头两个元素排好序,再依次将后续元素插入适当位置。
    void insert(int *a, int n) {
    for (i = 1; i < n; i++) {
    temp = a[i];
    j = i - 1;
    while (j >= 0 && temp < a[j]) {
    a[j + 1] = a[j];
    j--;
    }
    a[j + 1] = temp;
    }
    }
  • 快速法

    • 以分治策略分割数组,每次选一个中间元素作为基准,分左右调小,直到数组有序。
    void quick(int a, int i, int j) {
    int m, low, high, k;
    m = i;
    n = j;
    k = a[(i + j) / 2];
    do {
    while (a[m] < k && m < j) m++;
    while (a[n] > k && n > i) n--;
    if (m < n) {
    temp = a[m];
    a[m] = a[n];
    a[n] = temp;
    m++;
    n--;
    }
    } while (m < n);
    if (m < j) quick(a, m, j);
    if (n > i) quick(a, i, n);
    }
  • 二分查找

    • 递归策略,分割查找目标值的位置。
    int binary_search(int array[], int value, int size) {
    int low = 0, high = size - 1, mid;
    while (low <= high) {
    mid = (low + high) / 2;
    if (value == array[mid]) return mid;
    else if (value > array[mid]) low = mid + 1;
    else high = mid - 1;
    }
    return -1;
    }

  • 问题7: 字符串反转

    char * reverse(const char *str) {
    int len = strlen(str);
    char *ptr = (char *)str; // 实现为const char*,由于安全考虑将ptr改为char *则需要复制
    for (int i = 0; i < len / 2; i++) {
    char c = ptr[i];
    ptr[len - i - 1] = c;
    ptr[i] = ptr[len - i - 1];
    }
    return (char *)str; // 或者返回新分配的字符串
    }

    问题8: Static关键字作用

  • 静态变量在函数体内:在一个函数中,静态变量在函数调用过程中保留不变。
  • 静态变量在模块内:仅限当前模块使用,属于本地全局变量。
  • 静态函数:只在定义模块内可用,不可外部访问。

  • 问题9: 函数Strcat实现

    void strcat(char *str1, const char *str2) {
    size_t i, j;
    size_t len1 = strlen(str1);
    size_t len2 = strlen(str2);
    for (i = 0; i < len1; i++) {
    for (j = 0; j < len2; j++) {
    if (str1[i] == '\0' || str2[j] == '\0') {
    break;
    }
    str1[i + j] = str2[j];
    }
    i++;
    break;
    }
    }

    问题10: 进程与线程区别

    • 进程:系统资源分配和调度的独立单位。
    • 线程:进程的一个执行单元,更小且能独立运行。
    • 主要区别:地址空间(进程独立,线程共享),资源占用(线程更轻量)。

    问题11: 数组与链表的区别

    • 数组:元素连续存储,可通过下标快速访问,适合读大写小增删。
    • 链表:元素通过指针连接,插入删除高效,但逐次访问速度较慢。

    问题12: TCP与UDP的区别

  • 连接方式:TCP是面向连接的,无连接即UDP。
  • 可靠性:TCP可靠传输,UDP不可靠。
  • 数据传输:TCP有序传输,UDP不分顺序。

  • 问题13: epoll优点与区别

    • 优点:提高多任务处理效率,减少IO等待。
    • 区别:与poll不同,epoll复用描述符集,仅处理活跃端口。

    希望以上内容对您有所帮助!

    上一篇:25岁毕业,拿一万块月薪
    下一篇:《三十分钟掌握STL》(STL迭代器高级应用)

    发表评论

    最新留言

    关注你微信了!
    [***.104.42.241]2025年05月10日 12时18分16秒

    关于作者

        喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
    -- 愿君每日到此一游!

    推荐文章