【问题标题】:c++ write a stack methodc++写一个堆栈方法
【发布时间】: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::stackstd::list。编写自己的列表和堆栈只会将您引向未初始化指针和内存泄漏的路径。只需在 stackoverflow 上查找 C++ 列表中的所有问题……有数百个。所有这些人都在使用 C++ 学习数据结构(他们不是在学习 C++)
  • 好的,这是作业。你尝试了什么?你遇到了什么问题?你在哪一部分上挣扎?一旦您进行了诚实的尝试,如果您在某个时候遇到问题,请返回此处,这次您将遇到一个实际问题。
  • @PepijnKramer“编写自己的列表和堆栈只会将您引向未初始化指针和内存泄漏的路径。”为什么 ?我同意在 C++ 中做这样的事情毫无意义(除了你提到的学习数据结构机制)但是可以在 C++ 中完美地编写正确的堆栈或列表实现。如果不是这种情况,就不会有 std::stackstd::list 可用,而且 C++ 甚至可能都不存在 :)
  • @Fareanor 我想说的是编写您自己的数据结构不应该是在 C++ 中要做的第一件事。我见过太多人与他们作斗争并遇到问题并失去编程的“乐趣”。是后期开发非常有用的技能。
  • @PepijnKramer 我完全同意这一点,老实说,我明白你的意思 :) 只是,正如所写的那样,你的主张可能被误解了。

标签: c++ stack


【解决方案1】:

你的想法不错。

基本上我不会改变那么多。只需反转结果堆栈中的值。这可以简单地通过临时堆栈来完成。

顶部/弹出一个堆栈中的元素,然后将其放入结果堆栈。就这样。

请参见:

#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 << '
';
    }
};


void mergeSortedStacks(Stack& s1, Stack& s2, Stack& merged) {
    
    Stack tempStack{};  // ****** New

    // 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
                tempStack.push(s1.top());
                s1.pop();
            }
            else {
                // S2 top is smaller. push on resulting output stack
                tempStack.push(s2.top());
                s2.pop();
            }
        }
        // Only s1 has still some elements
        else if (s1.size()) {
            // Copy them to other stack
            tempStack.push(s1.top());
            s1.pop();
        }
        // Only s2 has still some elements
        else if (s2.size()) {
            tempStack.push(s2.top());
            s2.pop();
        }
    }
    // Reverse stack *****
    const int stacksize = tempStack.size();
    for (int i = 0; i < stacksize; ++i) {
        merged.push(tempStack.top());
        tempStack.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();
}

【讨论】:

  • 细节,但我不会使用 int 作为元素的数量(因为它永远不应该 < 0 ),而是 std::size_t (就像所有容器一样)
猜你喜欢
  • 2011-10-05
  • 1970-01-01
  • 2012-06-19
  • 2011-11-15
  • 1970-01-01
  • 2013-12-26
  • 2021-07-15
  • 1970-01-01
  • 2015-02-02
相关资源
最近更新 更多