|
| 1 | +- 栈实现 |
| 2 | + - 问题: |
| 3 | + - 讨论栈数据结构。使用链表或动态数组在C中实现栈,并且说出选择链表或动态数组的原因。设计的栈接口应完整、一致且易于使用。 |
| 4 | + - 考察点: |
| 5 | + 1. 候选人对基本数据结构的了解 |
| 6 | + 2. 候选人编写程序来操作这些结构的能力 |
| 7 | + 3. 候选人为一组程序设计一致的接口的能力 |
| 8 | + - 解释利弊: |
| 9 | + - 无论选择哪一种,都要向面试官说明两种方法的利弊。 |
| 10 | + - 动态数组的主要优点: |
| 11 | + 1. 可以随机访问(尽管在栈的实现中,这一点不起作用) |
| 12 | + 2. 良好的空间局部性。动态数组中的相邻元素在存储器中往往也是相邻的,于是实现的栈会更快。 |
| 13 | + - 动态数组的主要缺点: |
| 14 | + 1. 实现起来比链表更复杂。 |
| 15 | + 2. 扩容的操作费时,因为需要将旧元素从旧数组复制到新数组。 |
| 16 | + - 链表的主要优点: |
| 17 | + 1. 向头部插入元素的时间复杂度始终是O(1) |
| 18 | + 2. 在头部删除元素的时间复杂度始终是O(1) |
| 19 | + - 链表的主要缺点: |
| 20 | + 1. 每次插入元素时需要分配内存,分配内存的时间会比较长 |
| 21 | + 2. 不能随机访问元素 |
| 22 | + - 两者的对比: |
| 23 | + 1. 插入时间:链表插入元素的时间复杂度始终是O(1);而动态数组插入元素时,申请到的内存可能会满了,这时就必须扩容,扩容的操作会比较费时。 |
| 24 | + 2. 访问时间:动态数组访问某元素的时间复杂度始终是O(1);而链表访问某元素的时间复杂度是O(n) |
| 25 | + |
| 26 | + 代码实现: |
| 27 | + |
| 28 | + ```cpp |
| 29 | + // 单链表实现栈 |
| 30 | + #include <iostream> |
| 31 | + #include <forward_list> |
| 32 | + using namespace std; |
| 33 | + |
| 34 | + class Stack{ |
| 35 | + public: |
| 36 | + void push(int x); // 入栈 |
| 37 | + int pop(); // 出栈 |
| 38 | + int top(); // 返回栈顶元素 |
| 39 | + bool is_empty(); // 返回栈是否为空 |
| 40 | + |
| 41 | + private: |
| 42 | + std::forward_list<int>::iterator p;// 栈顶指针 |
| 43 | + std::forward_list<int> linklist;// 单链表 |
| 44 | + }; |
| 45 | + |
| 46 | + void Stack::push(int x){ |
| 47 | + this->linklist.push_front(x); |
| 48 | + this->p = this->linklist.begin(); |
| 49 | + } |
| 50 | + |
| 51 | + int Stack::pop(){ |
| 52 | + if (this->linklist.empty()){ |
| 53 | + return -1; |
| 54 | + } |
| 55 | + int ans = *this->p; |
| 56 | + this->linklist.pop_front(); |
| 57 | + this->p = this->linklist.begin(); |
| 58 | + return ans; |
| 59 | + } |
| 60 | + |
| 61 | + int Stack::top(){ |
| 62 | + if (this->linklist.empty()){ |
| 63 | + return -9999; |
| 64 | + } |
| 65 | + return *this->p; |
| 66 | + } |
| 67 | + |
| 68 | + bool Stack::is_empty(){ |
| 69 | + return this->linklist.empty(); |
| 70 | + } |
| 71 | + |
| 72 | + int main(){ |
| 73 | + Stack stack; |
| 74 | + std::cout<< stack.is_empty() << endl;// true |
| 75 | + |
| 76 | + stack.push(1); |
| 77 | + std::cout<< stack.top() << endl;// 1 |
| 78 | + |
| 79 | + stack.push(2); |
| 80 | + std::cout<< stack.top() << endl;// 2 |
| 81 | + |
| 82 | + stack.pop(); |
| 83 | + std::cout<< stack.top() << endl;// 1 |
| 84 | + std::cout<< stack.is_empty() << endl;// false |
| 85 | + |
| 86 | + stack.pop(); |
| 87 | + std::cout<< stack.top() << endl;// -9999 |
| 88 | + std::cout<< stack.is_empty() << endl;// true |
| 89 | + |
| 90 | + return 0; |
| 91 | + } |
| 92 | + ``` |
0 commit comments