【秋招】嵌入式面试八股文 - 数据结构 链表篇

【秋招】嵌入式面试八股文 - 最全专栏

1. 链表基础概念

Q: 什么是链表?链表有哪些类型?

链表是一种线性数据结构,由一系列节点组成,每个节点包含数据字段和指向下一个节点的引用(指针)。

常见类型:

  • 单向链表:每个节点只有一个指向下一节点的指针
  • 双向链表:每个节点有两个指针,分别指向前一个和后一个节点
  • 循环链表:最后一个节点指向第一个节点,形成环
  • 双向循环链表:结合双向链表和循环链表特性

Q: 链表与数组的区别是什么?各自的优缺点?

区别与优缺点

内存分配

动态分配,不连续

静态分配,连续空间

随机访问

O(n)

O(1)

插入删除

O(1)(已知位置)

O(n)(需要移动元素)

空间开销

需要额外指针空间

无额外开销

缓存局部性

较差

较好

大小调整

灵活,无需重新分配

固定或需要重新分配

2. 链表基本操作

Q: 如何实现单链表的创建、插入、删除和遍历?

// 定义链表节点结构
typedef struct Node {
    int data;
    struct Node* next;
} Node;

// 创建新节点
Node* createNode(int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) {
        printf("内存分配失败\n");
        exit(1);
    }
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 在链表头部插入节点
Node* insertAtBeginning(Node* head, int data) {
    Node* newNode = createNode(data);
    newNode->next = head;
    return newNode;
}

// 在链表尾部插入节点
Node* insertAtEnd(Node* head, int data) {
    Node* newNode = createNode(data);
    
    // 如果链表为空,新节点就是头节点
    if (head == NULL) {
        return newNode;
    }
    
    // 找到最后一个节点
    Node* temp = head;
    while (temp->next != NULL) {
        temp = temp->next;
    }
    
    // 在最后一个节点后添加新节点
    temp->next = newNode;
    return head;
}

// 删除指定值的节点
Node* deleteNode(Node* head, int key) {
    // 如果链表为空,直接返回
    if (head == NULL) {
        return NULL;
    }
    
    // 如果头节点就是要删除的节点
    if (head->data == key) {
        Node* temp = head;
        head = head->next;
        free(temp);
        return head;
    }
    
    // 查找要删除的节点
    Node* current = head;
    Node* prev = NULL;
    
    while (current != NULL && current->data != key) {
        prev = current;
        current = current->next;
    }
    
    // 如果找到了要删除的节点
    if (current != NULL) {
        prev->next = current->next;
        free(current);
    }
    
    return head;
}

// 遍历链表
void traverseList(Node* head) {
    Node* current = head;
    
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

// 释放链表内存
void freeList(Node* head) {
    Node* current = head;
    Node* next;
    
    while (current != NULL) {
        next = current->next;
        free(current);
        current = next;
    }
}


Q: 如何实现双向链表的基本操作?

// 定义双向链表节点结构
typedef struct DNode {
    int data;
    struct DNode* prev;
    struct DNode* next;
} DNode;

// 创建新节点
DNode* createDNode(int data) {
    DNode* newNode = (DNode*)malloc(sizeof(DNode));
    if (newNode == NULL) {
        printf("内存分配失败\n");
        exit(1);
    }
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
}

// 在双向链表头部插入节点
DNode* insertAtBeginningDLL(DNode* head, int data) {
    DNode* newNode = createDNode(data);
    
    if (head == NULL) {
        return newNode;
    }
    
    newNode->next = head;
    head->prev = newNode;
    return newNode;
}

// 在双向链表尾部插入节点
DNode* insertAtEndDLL(DNode* head, int data) {
    DNode* newNode = createDNode(data);
    
    if (head == NULL) {
        return newNode;
    }
    
    DNode* temp = head;
    while (temp->next != NULL) {
        temp = temp->next;
    }
    
    temp->next = newNode;
    newNode->prev = temp;
    return head;
}

// 删除双向链表中的节点
DNode* deleteNodeDLL(DNode* head, int key) {
    if (head == NULL) {
        return NULL;
    }
    
    // 如果头节点是要删除的节点
    if (head->data == key) {
        DNode* temp = head;
        head = head->next;
        
        if (head != NULL) {
            head->prev = NULL;
        }
        
        free(temp);
        return head;
    }
    
    DNode* current = head;
    
    while (current != NULL && current->data != key) {
        current = current->next;
    }
    
    if (current == NULL) {
        return head; // 没找到要删除的节点
    }
    
    // 调整前一个节点的next指针
    if (current->prev != NULL) {
        current->prev->next = current->next;
    }
    
    // 调整后一个节点的prev指针
    if (current->next != NULL) {
        current->next->prev = current->prev;
    }
    
    free(current);
    return head;
}

// 遍历双向链表
void traverseDLL(DNode* head) {
    DNode* current = head;
    
    printf("NULL <-> ");
    while (current != NULL) {
        printf("%d <-> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}


3. 链表经典问题

Q: 如何检测链表中是否有环?

Floyd的龟兔算法(快慢指针法)

bool hasCycle(Node* head) {
    if (head == NULL || head->next == NULL) {
        return false;
    }
    
    Node* slow = head;
    Node* fast = head;
    
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;          // 慢指针每次走一步
        fast = fast->next->next;    // 快指针每次走两步
        
        if (slow == fast) {         // 如果两个指针相遇,说明有环
            return true;
        }
    }
    
    return false;  // 如果fast到达链表尾部,说明没有环
}


Q: 如何找到链表的中间节点?

快慢指针法

Node* findMiddle(Node* head) {
    if (head == NULL) {
        return NULL;
    }
    
    Node* slow = head;
    Node* fast = head;
    
    // 快指针每次走两步,慢指针每次走一步
    // 当快指针到达链表尾部时,慢指针恰好在中间
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    
    return slow;  // 慢指针指向中间节点
}


Q: 如何反转单链表?

迭代方法

Node* reverseList(Node* head) {
    Node* prev = NULL;
    Node* current = head;
    Node* next = NULL;
    
    while (current != NULL) {
        next = current->next;    // 保存下一个节点
        current->next = prev;    // 反转当前节点的指针
        prev = current;          // 移动prev指针
        current = next;          // 移动current指针
    }
    
    return prev;  // 新的头节点
}


递归方法

Node* reverseListRecursive(Node* head) {
    // 基本情况:空链表或只有一个节点
    if (head == NULL || head->next == NULL) {
        return head;
    }
    
    // 递归反转剩余部分
    Node* newHead = reverseListRecursive(head->next);
    
    // 改变指针方向
    head->next->next = head;
    head->next = NULL;
    
    return newHead;
}


Q: 如何合并两个有序链表?

Node* mergeTwoLists(Node* l1, Node* l2) {
    // 创建一个哑节点作为合并链表的头部
    Node dummy;
    Node* tail = &dummy;
    
    while (l1 != NULL && l2 != NULL) {
        if (l1->data <= l2->data) {
            tail->next = l1;
            l1 = l1->next;
        } else {
            tail->next = l2;
            l2 = l2->next;
        }
        tail = tail->next;
    }
    
    // 连接剩余部分
    if (l1 != NULL) {
        tail->next = l1;
    } else {
        tail->next = l2;
    }
    
    return dummy.next;
}


Q: 如何检测并找到环的入口点?

Node* detectCycleStart(Node* head) {
    if (head == NULL || head->next == NULL) {
        return NULL;
    }
    
    Node* slow = head;
    Node* fast = head;
    bool hasCycle = false;
    
    // 第一步:检测是否有环
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
        
        if (slow == fast) {
            hasCycle = true;
            break;
        }
    }
    
    if (!hasCycle) {
        return NULL;
    }
    
    // 第二步:找到环的入口点
    slow = head;
    while (slow != fast) {
        slow = slow->next;
        fast = fast->next;
    }
    
    return slow;  // 环的入口点
}


4. 高级链表问题

Q: 如何判断两个链表是否相交?如何找

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

双非本,211硕。本硕均为机械工程,自学嵌入式,在校招过程中拿到小米、格力、美的、比亚迪、海信、海康、大华、江波龙等offer。八股文本质是需要大家理解,因此里面的内容一定要详细、深刻!这个专栏是我个人的学习笔记总结,是对很多面试问题进行的知识点分析,专栏保证高质量,让大家可以高效率理解与吸收里面的知识点!掌握这里面的知识,面试绝对无障碍!

全部评论

相关推荐

在就业环境不是很好的情况下,计算机和通信专业其实大部分学校好一些的,就业可选性还是不少的。但是相比于大部分同学去了私企,化身无敌码农,熬鹰式编写代码,在这种工作压力下,国家电网绝对是一个不错的选择,对于大部分学生来说,工作的要求就是钱多事儿少离家近,基本还是能够够满足的,所以本文带大家简单了解下国网中计算机通信专业的一些情况。1、通信专业进入电网可以去哪些岗位?每年各省网公司都会招聘一定数量的非电气专业的新员工,有信息通信、计算机类、财务类、法务类其他工学类等,非电专业的通信类一般去什么岗位?岗位:通信类入职后一般可能去通信、调度、营销还有二次检修。主要说一下信息通信岗位,这个岗位的归属设置各地区有所不同,有的地方将其归属地调管理,有的则是独立出来成立信息通信中心(信息通信分公司),直接归地市局管理。信息通信主要包括通信调度、通信运检、通信光缆等班组。2、计算机专业进入电网可以去哪些岗位?主要工作是运行维护网络,主机,终端几大类设备,然后根据国网信通部下发的各项规定和计划执行相关工作,如信息安全加固,等级保护等。大多时候不需要自主开发代码,但如果你有这方面能力和成果自然也是加分项。信息内网,内网维护,电脑维护等,也有可能分到通信部门,通信检修,视频会议,程控交换机,路由器等3笔试部分:(1)计算机的笔试由两部分组合,其中专业课占80%,综合部分20%。综合部分就相当于普通行测,而专业课可以称之为加强版408,也就是在考研专业课408的基础上增加了一些杂的东西,具体包括:数据结构与算法、数据库系统、操作系统、计算机组成与体系结构、信息新技术、计算机网络、软件设计与开发,其中有两门课是408之外的内容,并且有一点需要注意,虽然有几门科目相同,但是考试范围和408有较大区别(例如408的数据结构KMP算法是必考,而国网则没有要求),所以专业课就显得非常非常杂。(2)通信的笔试部分:综合部分和计算机一致20%,专业部分80%:1、通信原理、信号与系统:2、光纤通信3、数据通信网4、移动通信及其他业务系统。
投递国家电网等公司7个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务