Javascript:如何使用单个数组实现三个堆栈?

时间:2018-09-18 18:56:58

标签: javascript arrays algorithm stack queue

因此,我尝试了自己的方法,该方法不起作用,并且似乎有太多的控制语句,这有些令人困惑。这个问题很明显。

如何使用单个数组实现三个堆栈?

我知道答案已经用Java回答了,但是我在Javascript中找不到任何东西。

就目前而言,每个堆栈具有固定空间的潜在解决方案将是不错的。我知道,在空间分配上更加灵活的解决方案也会更加复杂。

谢谢您的帮助:)

编辑:这是我的代码

function ThreeInOne() {
  this.stack = []; 
  this.firstStackBeginning;
  this.firstStackEnd;
  this.secondStackBeginning;
  this.secondStackEnd;
  this.thirdStackBeginning;
  this.thirdStackEnd;

  this.addAtStack = function(stackIndex, value) { 
    if (this.stack.length === 0) {
      this.stack.push(value);
      if (stackIndex = 1) {
        this.firstStackBeginning = 0;
        this.firstStackEnd = 0;
      } else if (stackIndex = 2) {
        this.secondStackBeginning = 0;
        this.secondStackEnd = 0;
      } else if (stackIndex = 3) {
        this.thirdStackBeginning = 0;
        this.thirdStackEnd = 0;
      } else if (stackIndex > 3) {
        console.log("There are only 3 stacks available to add to")
      }
    } else if (this.stack.length > 0) {
      if (stackIndex == 1) {
        if (this.secondStackBeginning == 0) {
          this.stack.unshift(value);
          this.secondStackBeginning++;
          this.secondStackEnd++;
          this.firstStackBeginning = 0;
          this.firstStackEnd = 0;
        }
        if (this.secondStackBeginning && this.secondStackBeginning !== 0) {
          this.stack.splice(this.secondStackBeginning-1, 0, value);
          this.firstStackEnd++;
        } 
      } else if (stackIndex == 2) {
        if (this.thirdStackBeginning==0) {
          this.stack.unshift(value);
          this.thirdStackBeginning++;
          this.thirdStackEnd++;
          this.secondStackBeginning = 0;
          this.secondStackEnd = 0;
        } else if (this.thirdStackBeginning != 0) {
          this.stack.splice(this.thirdStackBeginning-1, 0, value);
          this.secondStackEnd = this.thirdStackBeginning-1;
          this.thirdStackBeginning++;
          this.thirdStackEnd++;
        }
      } else if (stackIndex == 3) {
        if (this.firstStackEnd && !this.secondStackEnd && !this.thirdStackBeginning) {
          this.thirdStackBeginning = this.firstStackEnd+1;
          this.stack.push(value);
        } else if (this.seconStackEnd )
      }
    }
  }
}

这还没有完成,但是我们的想法是保留每个堆栈的开始和结束的指针并相应地更新它们。我认为关键是不要使用另一种数据结构(除了那个数组),否则我将只创建一个具有三个内部数组的数组并相应地更新它们。所以这个想法是,例如,如果我们以array = [4,5,1,2,0,3,6]开头,则此数组实际上由三个堆栈组成,一个= [4,5),两个= [1 ,2)和三个= [0,3,6)。这个想法是,如果我想将x加到堆栈2,那么我将得到数组= [4,5,1,2,2,x,0,3,6]

我希望这可以使它更清楚!

2 个答案:

答案 0 :(得分:2)

在JavaScript中,此练习实际上比在许多其他语言中容易得多,因为JavaScript中的数组的行为更像是带有键而不是数字索引的关联数组。这意味着稀疏数组仅占用其元素所占用的空间;例如该数组:

var array = [];
array[0] = "one";
array[999] = "two";

只有两个元素,实际上没有998个空元素占用空间。这意味着,如果您要使用一个数组创建三个堆栈,则可以简单地为其赋予索引,例如从0、1000和2000,然后每个堆栈可以容纳一千个元素,而数组实际上不占用3000个元素的空间。

因此,在一个数组中设置三个堆栈可能是这样的(并且可以很容易地扩展为在一个数组中具有可变数量的堆栈):

function ThreeStacksInOne(capacity) {
    this.stack = [];
    this.begin = [0, capacity, 2 * capacity, 3 * capacity];
    this.end = [,,];

    this.push = function(stack, value) { 
        if (stack > 2) {
            console.log("Illegal stack index: " + stack + ".");
            return false;
        }
        if (this.end[stack] === undefined) {
            this.end[stack] = this.begin[stack];
        }
        else if (this.end[stack] + 1 == this.begin[stack + 1]) {
            console.log("Stack " + stack + " is full.");
            return false;
        }
        else ++this.end[stack];
        this.stack[this.end[stack]] = value;
        return true;
    }

    this.pop = function(stack) {
        if (stack > 2) {
            console.log("Illegal stack index: " + stack + ".");
            return undefined;
        }
        if (this.end[stack] === undefined) {
            console.log("Stack " + stack + " is empty.");
            return undefined;
        }
        var value = this.stack[this.end[stack]];
        delete this.stack[this.end[stack]];
        if (this.end[stack] == this.begin[stack]) {
            this.end[stack] = undefined;
        }
        else --this.end[stack];
        return value;
    }
}

var stack = new ThreeStacksInOne(1000000000);
stack.push(0,"a");
document.write(stack.pop(0));
var x = stack.pop(0);
stack.push(3,"b");

您可以轻松地对此进行调整,以适应可变数量的堆栈,并且在创建多堆栈时不必决定要多少个堆栈。您可以设置每个堆栈的最大容量,然后可以使用任意数量的堆栈,只要堆栈×容量不大于最大安全整数2 52 -1,这表示您可以使用例如一百万个堆栈,每个堆栈具有十亿个元素。并且,如上所述,这仅使用实际存在的元素数量所需的空间量。

function multiStack(maxSizePerStack) {
    this.stack = [];
    this.size = maxSizePerStack;
    this.end = [];

    this.push = function(stack, value) { 
        if (this.end[stack] === undefined) {
            this.end[stack] = this.size * stack;
        }
        else if (this.end[stack] + 1 == this.size * (stack + 1)) {
            console.log("Stack " + stack + " is full.");
            return false;
        }
        else ++this.end[stack];
        this.stack[this.end[stack]] = value;
        return true;
    }
    this.pop = function(stack) {
        if (this.end[stack] === undefined) {
            console.log("Stack " + stack + " is empty.");
            return undefined;
        }
        var value = this.stack[this.end[stack]];
        delete this.stack[this.end[stack]];
        if (this.end[stack] == this.size * stack) {
            this.end[stack] = undefined;
        }
        else --this.end[stack];
        return value;
    }
}
var stack = new multiStack(1000000000);
stack.push(0,"a");
stack.push(0,"b");
document.write(stack.pop(0) + "<br>");
document.write(stack.pop(0) + "<br>");
document.write(stack.pop(0) + "<br>");
stack.push(1000000,"c");
document.write(stack.pop(1000000) + "<br>");
document.write(stack.pop(9) + "<br>");

答案 1 :(得分:1)

即使在一个数组中,这个问题在JS中也是微不足道的,因此看起来似乎超出了问题的实质。原因是因为JS数组将自动扩展以添加元素,从而使其比Java中的ArrayList或原始数组更容易使用。

一种方法可能涉及将每个堆栈映射到数组中的偏移量。例如,在三堆栈配置中,第一个堆栈从索引0开始,并使用元素0、3、6、9,依此类推。第二个堆栈从索引1开始,并使用索引1、4、7、10,依此类推。对数组的顶部操作进行索引使用公式i + n * (sizes[i] - 1),而推入新的顶部为i + n * sizes[i],其中i是堆栈ID号,n是堆栈数在构造函数中指定。

class NStack {
  constructor(n) {
    this.stacks = [];
    this.sizes = new Array(n).fill(0);
  }
  
  peek(i) {
    return this.stacks[i+(this.sizes[i]-1)*this.sizes.length];
  }
  
  pop(i) {
    if (this.sizes[i] > 0) {
      return this.stacks.splice(
        i + (--this.sizes[i]) * this.sizes.length, 1, null
      );
    }
  }
  
  push(i, elem) {
    if (this.sizes[i] >= 0) {
      this.stacks[i+(this.sizes[i]++)*this.sizes.length] = elem;
    }
  }
}

const tripleStack = new NStack(3);
tripleStack.push(0, "banana");
console.log(tripleStack);
tripleStack.push(2, "apple");
console.log(tripleStack);
tripleStack.push(1, "watermelon");
console.log(tripleStack);
tripleStack.push(2, "jackfruit");
console.log(tripleStack);
tripleStack.pop(0);
console.log(tripleStack);
tripleStack.pop(2);
console.log(tripleStack);
console.log(tripleStack.peek(0));
console.log(tripleStack.peek(1));
console.log(tripleStack.peek(2));