面试题答案
一键面试#include <iostream>
// 定义双向链表节点结构
struct DoubleListNode {
int data;
DoubleListNode* prev;
DoubleListNode* next;
DoubleListNode(int val) : data(val), prev(nullptr), next(nullptr) {}
};
// 创建双向链表
DoubleListNode* createList(int arr[], int n) {
if (n <= 0) return nullptr;
DoubleListNode* head = new DoubleListNode(arr[0]);
DoubleListNode* current = head;
for (int i = 1; i < n; ++i) {
current->next = new DoubleListNode(arr[i]);
current->next->prev = current;
current = current->next;
}
return head;
}
// 在指定节点后插入新节点
void insertNode(DoubleListNode* prevNode, int newData) {
if (prevNode == nullptr) return;
DoubleListNode* newNode = new DoubleListNode(newData);
newNode->next = prevNode->next;
newNode->prev = prevNode;
if (prevNode->next != nullptr) {
prevNode->next->prev = newNode;
}
prevNode->next = newNode;
}
// 删除指定节点
void deleteNode(DoubleListNode* delNode) {
if (delNode == nullptr) return;
if (delNode->prev != nullptr) {
delNode->prev->next = delNode->next;
}
if (delNode->next != nullptr) {
delNode->next->prev = delNode->prev;
}
delete delNode;
}
// 释放整个链表内存
void freeList(DoubleListNode* head) {
DoubleListNode* current = head;
DoubleListNode* nextNode;
while (current != nullptr) {
nextNode = current->next;
delete current;
current = nextNode;
}
}
// 打印双向链表
void printList(DoubleListNode* head) {
DoubleListNode* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
DoubleListNode* head = createList(arr, n);
std::cout << "Original list: ";
printList(head);
insertNode(head->next, 6);
std::cout << "List after insertion: ";
printList(head);
deleteNode(head->next->next);
std::cout << "List after deletion: ";
printList(head);
freeList(head);
return 0;
}
指针操作与结构完整性维护
-
创建链表:
- 首先为头节点分配内存并初始化数据。
- 然后通过遍历数组,为每个新节点分配内存,设置新节点的
prev
指针指向前一个节点,前一个节点的next
指针指向新节点。
-
插入节点:
- 先创建新节点并初始化数据。
- 新节点的
next
指针指向prevNode
的下一个节点,prev
指针指向prevNode
。 - 如果
prevNode
的下一个节点存在,则更新其prev
指针指向新节点。 - 最后更新
prevNode
的next
指针指向新节点。
-
删除节点:
- 如果要删除的节点存在,先更新其前后节点的指针,使其绕过被删除节点。
- 若被删除节点的前一个节点存在,将其
next
指针指向被删除节点的下一个节点。 - 若被删除节点的下一个节点存在,将其
prev
指针指向被删除节点的前一个节点。 - 最后释放被删除节点的内存。
-
释放链表:
- 使用一个临时指针
nextNode
保存当前节点的下一个节点地址。 - 释放当前节点的内存,然后将当前节点更新为
nextNode
,继续循环直到链表为空。
- 使用一个临时指针
避免内存泄漏
- 动态内存分配:每次使用
new
分配内存后,确保在不需要该内存时使用delete
释放。在创建链表节点时使用new
,在删除节点和释放链表时使用delete
。 - 边界情况处理:
- 链表为空:在创建链表时,如果数组长度为0直接返回
nullptr
。在插入节点时,如果prevNode
为nullptr
直接返回。在删除节点时,如果delNode
为nullptr
直接返回。 - 插入头节点:可以将头节点视为普通节点处理,只要传入的
prevNode
是nullptr
对应的特殊逻辑即可。例如,在insertNode
函数中,如果prevNode
为nullptr
,则新节点成为新的头节点。 - 删除头节点:在
deleteNode
函数中,若删除的是头节点,更新头节点指针为原头节点的下一个节点(如果存在)。 - 删除尾节点:在
deleteNode
函数中,若删除的是尾节点,只需更新尾节点前一个节点的next
指针为nullptr
即可。
- 链表为空:在创建链表时,如果数组长度为0直接返回