数据结构《20》----Immutable stack

本文探讨了如何使用不可变数据结构(immutable stack)在常数时间内完成push、pop和getMax等操作。通过内存共享和均摊时间复杂度的思想,作者提供了一个C++的实现方案,其中核心是利用栈的特性让多个链表能够共享节点,从而达到高效操作的目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有趣的函数式数据结构《一》----不可变栈

什么是不可变?往栈中插入一个元素,原来的栈保持不变,返回一个新的栈(已插入新的元素)。

push, pop,getMax 等操作都要求在 常数时间内完成。


可能读者会产生疑惑,既然要返回一个新的栈,是不是就必须先拷贝一份原来的栈,然后在新的栈中插入元素。

但是这样复杂度就是线性的,如何能够在常数时间内完成呢??

这里,就是immutable DATA STRUCTRUE 的强大。。


本文给出一个C++ 的实现版本,基本理想是利用内存共享,以及均摊时间的思想。

下图给出了实现的核心思想。

三个链表[1,2,3], [1,2,4], [1,2,5]共用节点1,2

这是因为一个节点可以有多个前驱节点指向它本身。。而栈的特性:仅仅在链表的头部插入删除的性质保证了节点的共享。



//copyrigt @ L.J.SHOU May.25, 2014
#include 
using namespace std;

/**
 * This class is a functional datatype, representing 
 *      an immutable stack of objects.
 *
 * 1. stack is based on a list implementation
 * 2. std::shared_ptr is used to collect garbage
 * 3. thread safe
 */

template
struct Node {
  Node(T x, shared_ptr &tail) 
    : val_(x), next_(tail), max_(x){
      if(tail) max_ = max(val_, tail->max_); 
    }

  /** 
   * To avoid too deep recursive call
   *
   * Normally, default destructor provided by c++ compiler is enough
   * but in some cases, where the list is too long,
   * the recursive call of this function would be too deep,
   * leading a stack overflow error.
   */
  ~Node() {
    shared_ptr *ptr = &next_, *next(nullptr);
    vector > vec;

    while(*ptr) {
      if((*ptr).unique() == false) break;
      next = &((*ptr)->next_);
      vec.push_back(*ptr);
      *ptr = nullptr;
      ptr = next;
    }
  }
  T val_;
  T max_;
  shared_ptr next_;
};


template
class Stack
{
public:
  Stack(): count_(0), head_(nullptr) {}
  Stack(T x, Stack tail): head_(make_shared>(x, tail.head_)){
    count_ = 1 + tail.count_;
  }

  int size() { return count_;}

  bool empty() { return count_ == 0;}

  T getMax() { assert(!empty()); return head_->max_;}

  T getHead() { assert(!empty()); return head_->val_;}

  Stack getTail() { assert(!empty()); return Stack(head_->next_, count_-1);}

  Stack addHead(const T &x) {
    return Stack(x, *this);
  }

  Stack reverse() {
    Stack new_list;
    Stack it = *this; // make a "copy" first
    for(int i=0; i > tail, int count) 
    : head_(tail), count_(count) {}

  shared_ptr > head_;
  int count_;
};

int main(void)
{
  Stack list;
  for(int i=0; i<10; ++i)
    list = list.addHead(i);

  //print
  Stack temp = list;
  while(!temp.empty()) {
    cout << temp.getHead() << " ";
    temp = temp.getTail();
  }
  cout << endl;

  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值