如何在C++中实现可动态调整大小的堆栈

How to implement a dynamically resizable stack in C++?

本文关键字:调整 堆栈 动态 C++ 实现      更新时间:2023-10-16

我现在的代码只是一个简单的堆栈,具有推送,弹出和显示方法。如何更改堆栈,以便堆栈的大小根据输入的元素数量动态调整大小?因此,例如,如果堆栈已满,我将创建一个大小是原始堆栈两倍的新堆栈,并将数据复制到新堆栈。

谢谢。

#include <iostream>
#include <stdexcept>
using namespace std;
class Stack
{
private:
    int *p;
    int top,length;
public:
    Stack(int = 0);
    ~Stack();
    void push(int);
    int pop();
    void display();
};
Stack::Stack(int size)
{
    top=-1;
    length=size;
    while(length <= 0)                //If the stack size is zero, allow user to mention it at runtime
    {
        cout<<"Stack of zero size"<<endl;
        cout<<"Enter a size for stack : ";
        cin >> length;
    }
    p=new int[length];
}
Stack::~Stack()
{
    delete [] p;
}
void Stack::push(int elem)
{
    if(top==(length-1))     //If the top reaches to the maximum stack size
    {
        throw overflow_error("Can't push onto a full stack");
    }
    else
    {
        top++;
        p[top]=elem;
    }
}
int Stack::pop()
{
    if(top==-1)
    {
       throw underflow_error("Can't pop from an empty stack");
    }
    int ret=p[top];
    top--;
    length--;
    return ret;
}
void Stack::display()
{
    for(int i = 0; i <= top; i++)
        cout<<p[i]<<" ";
    cout<<endl;
}
int main()
{
    int len;
    cout<<"Enter a size for stack : ";
    cin >> len;
    Stack s1(len);
    try{
        s1.push(1);
        s1.display();
        s1.push(2);
        s1.push(3);
        s1.push(4);
        s1.push(5);
        s1.display();
        s1.pop();
        s1.display();
        s1.pop();
        s1.display();
        s1.pop();
        s1.display();
        s1.pop();
        s1.display();
        s1.pop();
        s1.display();
    }
    catch(overflow_error){
        cerr<< "Illegal operation. Cannot push onto a full stack.";
        return -1;
    }
    catch(underflow_error){
        cerr<< "Illegal operation. Cannot pop from an empty stack.";
        return -1;
    }

}
void Stack::push(int elem)
{
    if(top==(length-1))     //If the top reaches to the maximum stack size
    {
        int* newp = new int[length * 2];
        std::memcpy(newp, p, sizeof(int) * length);
        delete[] p;
        p = newp;
        top++;
        p[top]=elem;
        length*=2;
   }
   else
   {
       top++;
       p[top]=elem;
   }

}

标准库中的堆栈类 ( std::stack ) 通过委托给容器类(如 std::vector )来解决这个问题。不过,这有点作弊。

然而,std::vector<>背后的想法相当简单和可重用。当您达到最大大小时,请按顺序执行以下操作:

  1. 分配新内存。如果失败没有大问题(不会丢失数据)
  2. 复制所有现有元素。使用std::uninitialized_copy而不是std::copy
  3. 交换新旧指针
  4. 删除旧对象
  5. 释放旧分配

一种简单的方法是每次推送新元素会使堆栈溢出时将堆栈大小加倍。在这种情况下,您检测到潜在的溢出,然后使用声明一个大小是旧数组两倍的新 int 数组,然后将旧数组复制到这个新数组中,并将指针重新分配给该新数组并删除旧数组。这是其他更优化的方法,但这是一种简单的方法,您可以消耗比添加新项目所需的内存多得多的内存,但它比重新分配每个会溢出堆栈的新项目要快得多。

与其抛出异常overflow_error("无法推送到整个堆栈"),您可以使用 new 分配更多内存并将内容复制到该内存并释放先前分配的内存(内存交换)。

void Stack::push(int elem)
{
   if(top==(length-1))     //If the top reaches to the maximum stack size
   {
    //throw overflow_error("Can't push onto a full stack");
      int *pTemp = new int[length + 10/*value u want to increment*/];
      memcpy(p,pTemp,length);  //for using this include stdlib
      delete[] p;
      p = pTemp;
   }
   top++;
   p[top]=elem;
}