使用链表定义堆栈,实现pop,push

首先我要说明的是stack在标准库中是有其头文件的大家不需要自己去实现一个stack。其次实现stack可以使用动态数组或者链表两种方式,如果大家去实现stack,我推荐大家使用动态数组。
首先让我们比较一下链表和动态数组的优缺点吧。
链表:
优点:
1,访问最后一个节点的时间是一样的,0(n)
2,插入任何一个结点的时间是一样的
缺点:
1,处理小规模的数据开销很大,因为需要不断的申请地址
2,即便是处理大的数据,也不见得比动态数组快。因为内存读到cache中的时候,会将hit的数据周围都会读进cache中。所以如果地址不是连续的,hit这个内存的时间其实是挺高的。
动态数组:
优点:
1,数组在任何节点的访问时间都是o(1),因为可以通过下标直接访问。
2,在内存被hit的时候,数组周围的数据都被缓存,所以访问时间上也会减少
缺点:
如果实现方法不好,会导致很大的重复操作,例如:
每一次push一个数据,都申请一个将数组大小+1的地址。然后转移数据,清除之前留下的数据。这是一种很不好的实现方法。
实际上,vs2010里面自带的stack、实现方式是通过protected中的成员变量deque来实现puck和pop的。
而deque其实是双向队列, 该空间中每个元素都是指针,指向另一段较大的区域,这个区域称为缓冲区,缓冲区用来保存deque中的数据。因此deque在随机访问和遍历数据会比动态数组慢。

所以综上所述,如果一定要自己实现stack的话,用动态数组更好。
但是这里我用的是链表去实现stack,也只是为了演示作用。
代码中的我已经运行过了,代码的注释也很多我相信大家都能够看的很明白。


#include "stdafx.h"
#include
#include
using namespace std;
template
class my_stack
{
private:
//这里私有定义节点,里面有两个变量:数据和指向下一个节点的指针
    struct my_data
{
my_data *next;
Type data;
};
//根节点要重要保护,因为这是链表所有的内容都要通过根节点去查找
my_data *root;
public:
//构造函数将root赋值为nullptr
//注意这里是nullptr不是null,这是C++0X新的内容,希望大家在定义空指针的时候使用nullptr,这样其实更符合规范
my_stack():root(nullptr){}

void push(Type new_data)//插入数据
{
if(root==nullptr)//如果链表内部是空的
{
//注意这里要用try,catch,因为这里涉及内存的分配,很有可能会报出异常,所以要做好内存处理,否则会产生内存泄露
try
{
root=new my_data;
root->data=new_data;
root->next=nullptr;
}
catch(exception &e)//std::exception用来捕捉九大异常,e.what()用来显示异常的错误信息
{
if(root!=nullptr)
    {
    delete root;
root=nullptr;
cout<<e.what()<<endl;
}
}
}
else//如果插入时链表不为空
{
      my_data *old_ptr=root;
  while(old_ptr->next!=nullptr)old_ptr=old_ptr->next;//将插入位置移到链表的末端
  try
  {
 
  old_ptr->next=new my_data;
  old_ptr->next->data=new_data;
  old_ptr->next->next=nullptr;
  }
  catch (exception &e)
  {
  if(old_ptr->next!=nullptr)
  {
  delete (old_ptr->next);
  old_ptr->next=nullptr;
  cout<<e.what()<<endl;
  }
  }

}
}
bool pop(Type& new_data)//这里使用bool返回值也是检测返回值是否正确的一个方法,因为pop的时候有很大的可能链表内部已经为空了,这时候就要返回一个提示。
{
if(root==nullptr)//如果链表内部已经为空了
{
cout<<"the stack is empty now."<<endl;
return false;

}
else if(root->next==nullptr)//如果只有根节点这一个数据
{
new_data=root->data;
delete root;
root=nullptr;
return true;
}
else//如果链表内部有多个节点
{
 
  try
  {
  my_data *old_ptr=root;
  my_data *new_ptr=root;
      while(old_ptr->next!=nullptr)
  {
  new_ptr=old_ptr;
  old_ptr=old_ptr->next;
  }
  new_data=old_ptr->data;
  delete old_ptr;
  new_ptr->next=nullptr;
  return true;
  }
  catch(exception &e)
  {
  cout<<e.what()<<endl;
  return false;
  }
}
}
    ~my_stack()//析构函数用来回收所有内存
    {
my_data *this_data;
this_data=root;
while(root!=nullptr)
{
this_data=root;
root=root->next;
delete this_data;
}
    }
};


int main()
{
my_stack my_stack1;
my_stack1.push(1);
my_stack1.push(2);
my_stack1.push(3);
my_stack1.push(4);
my_stack1.push(5);
int new_data;
while(my_stack1.pop(new_data))
{
cout<<"pop data "<<new_data<<endl;
}
return 0;
}


运行结果:
使用链表定义堆栈,实现pop,push


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值