题目

原文:

Describe how you could use a single array to implement three stacks.

译文:

你如何只用一个数组实现三个栈?

解答

我们可以很容易地用一个数组来实现一个栈,压栈就往数组里插入值,栈顶指针加1; 出栈就直接将栈顶指针减1;取栈顶值就把栈顶指针指向的单元的值返回; 判断是否为空就直接看栈顶指针是否为-1。

如果要在一个数组里实现3个栈,可以将该数组分为3个部分。如果我们并不知道哪个栈将装 入更多的数据,就直接将这个数组平均分为3个部分,每个部分维护一个栈顶指针, 根据具体是对哪个栈进行操作,用栈顶指针去加上相应的偏移量即可。

代码如下:

class stack3{
public:
stack3(int size = ){
buf = new int[size*];
ptop[]=ptop[]=ptop[]=-;
this->size = size;
}
~stack3(){
delete[] buf;
}
void push(int stackNum, int val){
int idx = stackNum*size + ptop[stackNum] + ;
buf[idx] = val;
++ptop[stackNum];
}
void pop(int stackNum){
--ptop[stackNum];
}
int top(int stackNum){
int idx = stackNum*size + ptop[stackNum];
return buf[idx];
}
bool empty(int stackNum){
return ptop[stackNum]==-;
} private:
int *buf;
int ptop[];
int size;
};

当然,我们也可以有第二种方案。数组不分段,无论是哪个栈入栈,都依次地往这个数组里 存放。这样一来,我们除了维护每个栈的栈顶指针外,我们还需要维护每个栈中, 每个元素指向前一个元素的指针。这样一来,某个栈栈顶元素出栈后,它就能正确地找到下 一个栈顶元素。

所以,数组里存放的不再是基本数据类型的数据,我们需要先定义一个结点结构:

typedef struct node{
int val,preIdx;
}node;

数组中的每个元素将是这样一个结点,它保存当前位置的值,和指向上一个结点的索引。

具体代码如下:

class stack3_1{
public:
stack3_1(int totalSize = ){
buf = new node[totalSize];
ptop[]=ptop[]=ptop[]=-;
this->totalSize = totalSize;
cur = ;
}
~stack3_1(){
delete[] buf;
}
void push(int stackNum, int val){
buf[cur].val = val;
buf[cur].preIdx = ptop[stackNum];
ptop[stackNum] = cur;
++cur;
}
void pop(int stackNum){
ptop[stackNum] = buf[ptop[stackNum]].preIdx;
}
int top(int stackNum){
return buf[ptop[stackNum]].val;
}
bool empty(int stackNum){
return ptop[stackNum]==-;
} private:
node *buf;
int ptop[];
int totalSize;
int cur;
};

这种实现有一个缺点,在频繁地入栈出栈后,会造成数组空间的大量浪费。 因为当前指针cur是一直递增的,而堆栈在出栈后相应位置的空间将不会再被利用到。 代码中pop函数,只是修改了栈顶指针。如果我们对一个栈先执行出栈,再入栈, 那么再次入栈的位置是在cur,而不是原来栈顶的位置。

有没有避免这种空间浪费的方法呢?当然是有的。不过这样一来,对cur的操作就变得复杂 了。第一,每次执行pop操作,检查该元素对应索引是否小于cur,如果是, 将cur更新到该元素索引;否则cur不变。第二,每次执行完push操作, cur要沿着数组依次向后查找,直到找到第一个空的空间,用它的索引更新cur。 这部分代码实现起来也是没什么难度的,这里不再贴出。

以下是完整代码:

#include <iostream>
using namespace std; class stack3{
public:
stack3(int size = ){
buf = new int[size*];
ptop[]=ptop[]=ptop[]=-;
this->size = size;
}
~stack3(){
delete[] buf;
}
void push(int stackNum, int val){
int idx = stackNum*size + ptop[stackNum] + ;
buf[idx] = val;
++ptop[stackNum];
}
void pop(int stackNum){
--ptop[stackNum];
}
int top(int stackNum){
int idx = stackNum*size + ptop[stackNum];
return buf[idx];
}
bool empty(int stackNum){
return ptop[stackNum]==-;
} private:
int *buf;
int ptop[];
int size;
}; typedef struct node{
int val,preIdx;
}node; class stack3_1{
public:
stack3_1(int totalSize = ){
buf = new node[totalSize];
ptop[]=ptop[]=ptop[]=-;
this->totalSize = totalSize;
cur = ;
}
~stack3_1(){
delete[] buf;
}
void push(int stackNum, int val){
buf[cur].val = val;
buf[cur].preIdx = ptop[stackNum];
ptop[stackNum] = cur;
++cur;
}
void pop(int stackNum){
ptop[stackNum] = buf[ptop[stackNum]].preIdx;
}
int top(int stackNum){
return buf[ptop[stackNum]].val;
}
bool empty(int stackNum){
return ptop[stackNum]==-;
} private:
node *buf;
int ptop[];
int totalSize;
int cur;
}; int main(){
stack3_1 mystack;//stack3 mystack;
for(int i=; i<; ++i)
mystack.push(, i);
for(int i=; i<; ++i)
mystack.push(, i);
for(int i=; i<; ++i)
mystack.push(, i);
for(int i=; i<; ++i)
cout<<mystack.top(i)<<" "; cout<<endl;
for(int i=; i<; ++i){
mystack.pop(i);
cout<<mystack.top(i)<<" ";
}
mystack.push(, );
mystack.push(, );
mystack.push(, );
for(int i=; i<; ++i)
cout<<mystack.top(i)<<" ";
return ;
}

Cracking the coding interview--Q3.1的更多相关文章

  1. Cracking the coding interview

    写在开头 最近忙于论文的开题等工作,还有阿里的实习笔试,被虐的还行,说还行是因为自己的水平或者说是自己准备的还没有达到他们所需要人才的水平,所以就想找一本面试的书<Cracking the co ...

  2. Cracking the coding interview 第一章问题及解答

    Cracking the coding interview 第一章问题及解答 不管是不是要挪地方,面试题具有很好的联系代码总用,参加新工作的半年里,做的大多是探索性的工作,反而代码写得少了,不高兴,最 ...

  3. Cracking the Coding Interview(Trees and Graphs)

    Cracking the Coding Interview(Trees and Graphs) 树和图的训练平时相对很少,还是要加强训练一些树和图的基础算法.自己对树节点的设计应该不是很合理,多多少少 ...

  4. Cracking the Coding Interview(Stacks and Queues)

    Cracking the Coding Interview(Stacks and Queues) 1.Describe how you could use a single array to impl ...

  5. 《Cracking the Coding Interview》读书笔记

    <Cracking the Coding Interview>是适合硅谷技术面试的一本面试指南,因为题目分类清晰,风格比较靠谱,所以广受推崇. 以下是我的读书笔记,基本都是每章的课后习题解 ...

  6. Cracking the coding interview目录及资料收集

    前言 <Cracking the coding interview>是一本被许多人极力推荐的程序员面试书籍, 详情可见:http://www.careercup.com/book. 第六版 ...

  7. 《Cracking the Coding Interview》——第13章:C和C++——题目6

    2014-04-25 20:07 题目:为什么基类的析构函数必须声明为虚函数? 解法:不是必须,而是应该,这是种规范.对于基类中执行的一些动态资源分配,如果基类的析构函数不是虚函数,那么 派生类的析构 ...

  8. 《Cracking the Coding Interview》——第5章:位操作——题目7

    2014-03-19 06:27 题目:有一个数组里包含了0~n中除了某个整数m之外的所有整数,你要设法找出这个m.限制条件为每次你只能用O(1)的时间访问第i个元素的第j位二进制位. 解法:0~n的 ...

  9. Cracking the Coding Interview 10.7

    Design an algorithm to find the kth number such that the only prime factors are 3,5 and 7 方法一: a[i]= ...

  10. 二刷Cracking the Coding Interview(CC150第五版)

    第18章---高度难题 1,-------另类加法.实现加法. 另类加法 参与人数:327时间限制:3秒空间限制:32768K 算法知识视频讲解 题目描述 请编写一个函数,将两个数字相加.不得使用+或 ...

随机推荐

  1. laravel 5.1 添加第三方扩展库

    步骤一:确定你要放第三方库的目录,假设:app/libs,并在该目录下放置类文件common.php.

  2. Oracle游标解析

    本节对Oracle中的游标进行详细讲解. 本节所举实例来源Oracle中scott用户下的emp表dept表: 一.游标: 1.概念: 游标的本质是一个结果集resultset,主要用来临时存储从数据 ...

  3. C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序

    C#中缓存的使用   缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可:  <%@ Outp ...

  4. 转 selenium 自动下载文件

    #coding=utf-8from selenium import webdriver #实例化一个火狐配置文件fp = webdriver.FirefoxProfile() #设置各项参数,参数可以 ...

  5. 配置SELINUX

    selinux的配置文件:# more /etc/selinux/config # This file controls the state of SELinux on the system. # S ...

  6. PLSQL_统计信息系列09_统计信息在不同数据库中迁移

    2014-01-05 Created By BaoXinjian

  7. Python 字典 keys() 方法

    描述 Python 字典 keys() 方法以列表形式(并非直接的列表,若要返回列表值还需调用list函数)返回字典中的所有的键. 语法 keys() 方法语法: D.keys() 参数 无. 返回值 ...

  8. 分享Memcached shell启动停止脚本

    注意:要使用这个shell,必须先成功建立memcache环境 1>建立memcached文件和权限 [root@luozhonghua ~]# touch /etc/init.d/memcac ...

  9. Java web中listener、 filter、servlet 加载顺序

    真正的加载顺序为:context-param -> listener -> filter -> servlet 加载顺序与它们在 web.xml 文件中的先后顺序无关.即不会因为 f ...

  10. e到底是什么?

    e到底是什么? 今天看到一个下面这么一个简单的求极限问题- 一时恍惚了,为什么结果是e^m. 这个e是什么呢? 然后就百度了下,发现不少文章介绍这个e. 有几篇写得很赞 - An Intuitive ...