算法复制堆栈

时间:2012-06-27 13:08:20

标签: c algorithm data-structures stack

是否可以在不使用任何外部堆栈或阵列的情况下将堆栈复制到另一个堆栈中?

我知道可以使用递归来完成,但是在提到的约束内是否还有其他可能的解决方案?

4 个答案:

答案 0 :(得分:8)

是的,这是可能的,但它需要O(N^2)。考虑堆栈S(来源)和T(目标)。

  1. 初始化count为零
  2. 将顶部元素E从堆栈S中弹出,然后将剩余数据推送到堆栈T,将count项留在堆栈S
  3. E
  4. 之上推送S
  5. 将元素从T复制回S
  6. 增量count
  7. 如果count不等于S上的项目数,请返回步骤1
  8. S的pop元素并推送到T
  9. 步骤0到5反向堆栈S到位;第6步将其移至T,撤消订单并生成原件的副本。但这是一个破坏性的副本,因为原始堆栈现在是空的。

答案 1 :(得分:4)

效率不高,但是可行。

Stack S = source, Stack T = target, int size = number of elements;
while(size >0 ) {
  pop size-1 elements from S (all but last), pushing them onto T (using it as temp storage)
  pop and copy the last element from S; push it back onto S;
  pop and push size-1 elements on T back to S.
  push your copy  of the last element onto T
  decrement size;
}

引用ugoren,这类似于“河内有2个钉子,加上恒定数量的1碟存储空间”的塔楼

答案 2 :(得分:2)

好的,我将展示自己的可视化和解决方案,以便从一个堆栈到另一个堆栈的真正非破坏性副本。

所以我们有一对堆栈ST,我们可以想象它们会像这样相互增长:

    ____________        _______________
    |                                  |
S   | S0 S1 S2   ........     T2 T1 T0 | T
    |____________       _______________| 

如果我们将整个数据结构视为单个序列(S0, S1, S2, ...., T2, T1, T0),我们可以执行将特定元素从位置i移动或复制到位置j的操作。我们如何做到这一点?我们可以通过以下小步骤来完成这个序列:

void MoveLeft()
{
    T.push( S.pop() );
    curPosition--;
}

void MoveRight()
{
    S.push( T.pop() );
    curPosition++;
}

然后我们可以访问任何元素,记住它,然后移动到任何其他位置并将该元素放在那里。这是辅助函数:

void MoveToI(int i)
{
    while( curPosition > i ) {
        MoveLeft();
    }

    while( curPosition < i ) {
        MoveRight();
    }
}

因此,使用这些操作,我们基本上将序列(S0,S1,S2,...,SN)转换为(S0,S1,S2,...,SN,SN,SN-1,...,S2,S1,S0)

这是算法:

curPosition = NElements;
for( int i = 0; i < NElements; ++i ) {
    MoveToI( i );
    x = T.peek();
    MoveToI(Nelements);
    T.push( x );
}

MoveToI( Nelements );

答案 3 :(得分:0)

这是一个O(N)操作,因为堆栈是已知开始和结束的连续区域,从一个进程到共享内存可以是import csv with open ("example.csv", "r") as csv_file: csv_reader = csv.reader(csv_file, delimiter ="\ ") with open("new_example.csv","w") as new_file: csv_writer = csv.writer(new_file, delimiter="\t") for line in csv_reader: csv_writer.writerow(line) memlcpy(),也可以通过IPC发送。理想情况下,如果这个过程重放或实时迁移代码,请在执行任何操作之前检查数据结构和ABI是否足够接近。另外,复制堆。然后,诀窍是在某处设置一个魔术变量,以指示一个进程应该等待准备运行而另一个进程应该关闭。还需要复制文件句柄,互斥锁,信号量和其他内核模式状态。它是更便宜的a)使用memcpy_s()为你完成所有这些或者b)有一个可以“停止世界”的检查点反应堆(堆栈,堆和外部资源)暂停所有线程并重新启动所有线程在杀死它之前的子进程中。我会fork()+ exec()并复制堆栈和堆。可能需要一个辅助入口指针补丁表(两个指针的数组:旧指针 - &gt;新指针),它们必须修补代码,堆栈,堆,常量表才能不崩溃。