【发布时间】:2022-11-27 07:47:08
【问题描述】:
我想在 C++ 中开发一个函数,它将采用两个排序的堆栈 A 和 B(最小值在顶部),并创建一个合并和排序的新堆栈(最小值在顶部)。
只允许使用最小的标准堆栈操作,例如 pop、push、size 和 top。
对于此任务,不允许使用其他数据结构,例如数组。
堆栈应由单链表 So 实现,具有 Stack 类和 Node 类。
我想出了下面的尝试,这是行不通的。 堆栈中的元素顺序错误。
Current output: 10 9 8 7 6 5 4 3 2 1
Expected Output: 1 2 3 4 5 6 7 8 9 10
如何正确地做到这一点?
请在下面查看我的无效代码:
#include <initializer_list>
#include <iostream>
// Node class for a minimum singly linked list
struct Node {
int data{}; // Data part
Node* next{}; // Link
};
// Stack, implemented as singly linked list with only minimum necessary functions
class Stack {
Node* head{}; // Head of singly linked list
int numberOfElements{}; // Housekeeping. Stack size
public:
Stack() {}; // Default constructor. Do nothing
// Convenience function. Build stack from initailizer list
Stack(const std::initializer_list<int>& il) { for (const int i : il) push(i); }
// And destructor, will release memory
~Stack() {
Node* temp = head; // Start with the head
while (temp) { // Iterate along the list
Node* toDelete = temp; // Remember Node that must be deleted
temp = temp->next; // Goto next element
delete toDelete; // Delete Remebered Element
}
}
void push(const int value) { // Push a new element onto the stack. Insert at beginning
Node* temp = new Node; // Allocate memory for a new node
temp->data = value; // Assign data part to new Node
temp->next = head; // This will be the new head, so, next will point to previous head
head = temp; // Set head pointer to new Node
++numberOfElements; // Bookkeeping, incremenent size
}
void pop() { // Simply dlete the first element in the linked list
if (head) { // If there is something in the list at all
Node* temp = head; // Remember current head Node
head = head->next; // New head will be the current heads next node
delete temp; // Delete old head
--numberOfElements; // Bookkeeping, decremenent size
}
};
int top() const { return head ? head->data : 0; } // Simply retun data from head node
int size() const { return numberOfElements; } // expose size to outside world
void print() { // Helper for printing debug output
Node* temp = head; // We will iterate over the list beginning at the head
while (temp) { // As long as we are not at the end of the list
std::cout << temp->data << ' '; // Show data
temp = temp->next; // And continue with next node
}
std::cout << '\n';
}
};
// This is the function that needs to be done
void mergeSortedStacks(Stack& s1, Stack& s2, Stack& merged) {
// As long as there are elements in s1 or in s1
while (s1.size() or s2.size()) {
// If there are elements in both s1 and s2
if (s1.size() and s2.size()) {
// Which top element is smaller?
if (s1.top() < s2.top()) {
// S1 top is smaller. push on resulting output stack
merged.push(s1.top());
s1.pop();
}
else {
// S2 top is smaller. push on resulting output stack
merged.push(s2.top());
s2.pop();
}
}
// Only s1 has still some elements
else if (s1.size()) {
// Copy them to other stack
merged.push(s1.top());
s1.pop();
}
// Only s2 has still some elements
else if (s2.size()) {
merged.push(s2.top());
s2.pop();
}
}
}
// Test
int main() {
Stack s1{ 10, 8, 6, 4 ,2 };
s1.print();
Stack s2{ 9, 7, 5, 3, 1};
s2.print();
Stack m{};
mergeSortedStacks(s1, s2, m);
m.print();
}
【问题讨论】:
-
不,您不必用 C++ 编写堆栈和列表:C++ 有
std::stack和std::list。编写自己的列表和堆栈只会将您引向未初始化指针和内存泄漏的路径。只需在 stackoverflow 上查找 C++ 列表中的所有问题……有数百个。所有这些人都在使用 C++ 学习数据结构(他们不是在学习 C++) -
好的,这是作业。你尝试了什么?你遇到了什么问题?你在哪一部分上挣扎?一旦您进行了诚实的尝试,如果您在某个时候遇到问题,请返回此处,这次您将遇到一个实际问题。
-
@PepijnKramer“编写自己的列表和堆栈只会将您引向未初始化指针和内存泄漏的路径。”为什么 ?我同意在 C++ 中做这样的事情毫无意义(除了你提到的学习数据结构机制)但是可以在 C++ 中完美地编写正确的堆栈或列表实现。如果不是这种情况,就不会有
std::stack和std::list可用,而且 C++ 甚至可能都不存在 :) -
@Fareanor 我想说的是编写您自己的数据结构不应该是在 C++ 中要做的第一件事。我见过太多人与他们作斗争并遇到问题并失去编程的“乐趣”。是后期开发非常有用的技能。
-
@PepijnKramer 我完全同意这一点,老实说,我明白你的意思 :) 只是,正如所写的那样,你的主张可能被误解了。