C++笔试必备:链表反转与String类实现解析

需积分: 12 2 下载量 85 浏览量 更新于2024-07-28 1 收藏 210KB PDF 举报
"这篇资料是关于C++的笔试题集合,特别适合初级程序员在面试前进行准备。其中包括了两个典型问题:链表反转和自定义String类的成员函数实现。" 链表反转是一个常见的编程面试题,主要考察对数据结构和指针操作的理解。有以下两种常见方法: 1. 非递归法: 这种方法通过迭代来实现。首先定义三个指针,`pre`、`cur`和`ne`,分别表示当前节点的前一个节点、当前节点和当前节点的下一个节点。初始时,`pre`设为`head`,`cur`设为`head->next`。然后遍历链表,每次将`cur`指向的下一个节点赋值给`pre`,`cur->next`指向前一个节点`pre`,然后移动`cur`和`pre`,直到遍历结束。最后更新`head`指向反转后的头节点,确保链表的末尾不连接回头部。 ```cpp struct LinkA { int data; LinkA* next; }; void reverse(LinkA*& head) { if (head == NULL) return; LinkA* pre, * cur, * ne; pre = head; cur = head->next; while (cur) { ne = cur->next; cur->next = pre; pre = cur; cur = ne; } head->next = NULL; head = pre; } ``` 2. 递归法: 递归方法则通过函数调用来实现链表反转。基本思路是从当前节点开始,先递归地反转后续节点,然后将当前节点插入到反转后的链表头部。由于递归返回时,最后一个节点会形成循环,因此需要在返回前将节点的`next`指针设为`NULL`。这里使用了引用参数`head`来改变原链表的头指针。 ```cpp LinkA* reverse(LinkA* p, LinkA*& head) { if (p == NULL || p->next == NULL) { head = p; return p; } else { LinkA* tmp = reverse(p->next, head); tmp->next = p; return p; } } ``` 接下来是第二个问题,关于自定义的`String`类。这个类模拟了标准库中的`std::string`,需要实现四个基本的成员函数: 1. 通用构造函数:默认构造函数,可以接受一个`const char*`类型的字符串作为参数,用于初始化`String`对象。如果没有提供参数,则创建一个空字符串。 2. 拷贝构造函数:当一个`String`对象被另一个`String`对象初始化时,拷贝构造函数用于复制所有的数据。这包括内存管理,确保新对象拥有独立的字符串副本。 3. 析构函数:当`String`对象被销毁时,析构函数负责释放与对象关联的内存。 4. 赋值运算符:实现赋值操作(`=`),允许将一个`String`对象赋值给另一个`String`对象。这里应包含深拷贝,以防止浅拷贝导致的悬挂指针问题。 ```cpp class String { public: // 通用构造函数 String(const char* str = NULL) : m_data(new char[strlen(str) + 1]) { strcpy(m_data, str); } // 拷贝构造函数 String(const String& another) : m_data(new char[strlen(another.m_data) + 1]) { strcpy(m_data, another.m_data); } // 析构函数 ~String() { delete[] m_data; } // 赋值函数 String& operator=(const String& rhs) { if (this != &rhs) { delete[] m_data; m_data = new char[strlen(rhs.m_data) + 1]; strcpy(m_data, rhs.m_data); } return *this; } private: char* m_data; // 用于保存字符串 }; ``` 以上就是针对提供的C++笔试题的解答,涉及了链表反转的两种方法以及自定义`String`类的成员函数实现。这些知识点在C++程序员的面试和日常工作中都非常重要。