JavaScript로 스택과 큐를 어떻게 구현합니까?


740

JavaScript에서 스택 및 큐를 구현하는 가장 좋은 방법은 무엇입니까?

Shunting-yard 알고리즘을 찾고 있는데 이러한 데이터 구조가 필요합니다.

답변:


1347
var stack = [];
stack.push(2);       // stack is now [2]
stack.push(5);       // stack is now [2, 5]
var i = stack.pop(); // stack is now [2]
alert(i);            // displays 5

var queue = [];
queue.push(2);         // queue is now [2]
queue.push(5);         // queue is now [2, 5]
var i = queue.shift(); // queue is now [5]
alert(i);              // displays 2

" 당신이 모르는 9 개의 자바 스크립트 팁 에서 발췌 "


217
queue.shift를 사용할 때는주의를 기울여야합니다. IIRC 그것은 O (1)이 아니라 O (n)이며 대기열이 커지면 너무 느릴 수 있습니다.
MAK

20
나는 이것이 자바 스크립트 구현에 달려 있다고 말하고 싶다. 나는 그것이 자바 스크립트 사양에 정의되어 있다고 생각하지 않습니다.
Georg Schölly

9
큐 성능을 향상시키는 간단한 구현 은 code.stephenmorley.org/javascript/queues 를 참조하십시오 .
길리

15
큐 성능 문제의 경우에 스택 행동의 세 가지 유형의 좋은 비교를 참조 jsperf.com/queue-push-unshift-vs-shift-pop - 이제 사람 만이 그 jsperf의 회전을 포함하는 좋은 충분히 있었다면를하는 것 @Gili가 언급 한 JS 스크립트를 포함합니다 ...
Nenotlep

3
archive.org가 항상 가장 성능이 좋은 것은 아니기 때문에이 답변에 링크 된 블로그 게시물을 부활 시켰 습니다. 작동하도록 링크와 이미지를 업데이트했지만 다른 사항은 변경하지 않았습니다.
Chev

87

Javascript에는 일반 Javascript 배열 객체에서 작동하는 push 및 pop 메소드가 있습니다.

대기열은 여기를 참조하십시오.

http://safalra.com/web-design/javascript/queues/

배열 객체의 push 및 shift 메소드 또는 unshift 및 pop 메소드를 사용하여 JavaScript로 큐를 구현할 수 있습니다. 이 방법은 대기열을 구현하는 간단한 방법이지만 대형 대기열의 경우 비효율적입니다. 메서드가 배열에서 작동하기 때문에 shift 및 unshift 메서드는 호출 될 때마다 배열의 모든 요소를 ​​이동합니다.

Queue.js는 dequeue 함수가 상각 된 일정한 시간에 실행되는 JavaScript를위한 간단하고 효율적인 큐 구현입니다. 결과적으로 더 큰 대기열의 경우 배열을 사용하는 것보다 훨씬 빠를 수 있습니다.


2
공유 한 링크를 사용하면 벤치 마크 결과를 확인하는 기능이 있었고 Chrome 버전 59로 테스트 할 때 성능 향상을 보지 못했습니다. Queue.js는 속도가 일치하지 않지만 Chrome은 속도와 일치합니다.
Shiljo Paulson

또한 queue.js로 데모를 만들었습니다. dequeue 함수는 실제로 큐에서 항목을 제거하지 않으므로 어떻게 작동하는지 궁금합니다. 그렇다면 이전 항목을 대기열에서 제거한 후 새 대기열을 어떻게 검색 할 수 있습니까? codepen.io/adamchenwei/pen/VxgNrX?editors=0001
Ezeewei

queue.js의 dequeue처럼 보이는 것은 슬라이스로 배열을 복제 할 때 추가 메모리가 필요합니다.
JaTo

또한 모든 추가 요소마다 기본 배열이 점점 커지고 있습니다. 구현으로 인해 때때로 어레이 크기가 줄어들더라도 전체 크기가 증가합니다.
Philipp Mitterer

73

배열.

스택:

var stack = [];

//put value on top of stack
stack.push(1);

//remove value from top of stack
var value = stack.pop();

열:

var queue = [];

//put value on end of queue
queue.push(1);

//Take first value from queue
var value = queue.shift();

1
Array.prototype.pop은 Array의 맨 위 (첫 번째 요소)에서 값을 제거하지 않습니다. Array의 맨 아래 (마지막 요소)에서 값을 제거합니다.
Michael Geller

21
@MichaelGeller 스택의 상단은 배열 의 마지막 요소입니다. 배열 푸시 및 팝 메소드는 스택처럼 작동합니다.
mrdommyg

@mrdommyg Array.prototype.pop은 배열 의 마지막 요소를 제거합니다 ( developer.mozilla.org/en/docs/Web/JavaScript/Reference/… 참조 ). 이 맥락에서 마지막은 인덱스가 가장 높은 요소를 의미합니다. JS의 배열은 스택과 관련이 없습니다. pop 메소드를 가지고 있기 때문에 스택이 아닙니다. 팝은 "마지막 요소를 제거하고 반환"을 의미합니다. 물론 배열을 사용하여 스택의 기능을 모방 할 수 있지만 배열은 여전히 ​​정의상 스택이 아닙니다. 여전히 목록입니다 (MDN에 따른 "like like"개체).
Michael Geller

5
@MichaelGeller 스택의 동작은 "선입 선출"입니다. JavaScript에서 pushpop메소드 와 함께 Array를 사용하여 구현하면 문제가 해결됩니다. 나는 당신의 요점을 여기에서 실제로 보지 못합니다.
Rax Weber

2
@MichaelGeller 스택은 개념적입니다. JS 배열은 무엇보다도 스택 의미론을 구현함으로써 스택을 정의합니다. 배열 의미를 구현한다고해서 변경되지는 않습니다. 상자에서 스택처럼 JS 배열을 사용할 수 있으며, 이러한 맥락에서 푸시 및 팝은 "최상위"요소입니다.
Hans

32

자신 만의 데이터 구조를 만들고 싶다면 자신 만의 데이터 구조를 만들 수 있습니다.

var Stack = function(){
  this.top = null;
  this.size = 0;
};

var Node = function(data){
  this.data = data;
  this.previous = null;
};

Stack.prototype.push = function(data) {
  var node = new Node(data);

  node.previous = this.top;
  this.top = node;
  this.size += 1;
  return this.top;
};

Stack.prototype.pop = function() {
  temp = this.top;
  this.top = this.top.previous;
  this.size -= 1;
  return temp;
};

그리고 대기열 :

var Queue = function() {
  this.first = null;
  this.size = 0;
};

var Node = function(data) {
  this.data = data;
  this.next = null;
};

Queue.prototype.enqueue = function(data) {
  var node = new Node(data);

  if (!this.first){
    this.first = node;
  } else {
    n = this.first;
    while (n.next) {
      n = n.next;
    }
    n.next = node;
  }

  this.size += 1;
  return node;
};

Queue.prototype.dequeue = function() {
  temp = this.first;
  this.first = this.first.next;
  this.size -= 1;
  return temp;
};

13
끝에 추가하기 위해 전체를 반복 할 필요가 없도록 this.last = node;를 통해 마지막 것에 대한 참조를 저장하십시오.
퍼킨스

9
논리적으로 올바른 것처럼 보일 수 있지만 CPU는 사람의 추상화에 따라 작동하지 않지만 이와 같은 대기열을 구현하지 마십시오. 모든 곳에서 포인터가있는 데이터 구조를 반복하면 매우 효율적인 순차 배열과 달리 CPU에서 캐시가 누락됩니다. blog.davidecoppola.com/2014/05/… CPU는 열정을 가지고 포인터를 싫어합니다. 캐시 미스와 RAM에서 메모리에 액세스해야하는 가장 큰 원인 일 것입니다.
Centril

1
이것은 유혹적인 해결책이지만 Node팝업 / 대기열에서 생성 된 파일 이 삭제되는 것을 보지 못합니다 ... 브라우저가 충돌 할 때까지 메모리가 흐르지 않습니다.
cneuro

5
@cneuro C ++와 달리 JavaScript는 가비지 수집 언어입니다. 그것은 갖는 delete키워드를하지만에만 유용 아닌 현재의 할당되는 단지 상이한 것으로 객체의 속성을 표시하는 undefined속성을이 . JavaScript에는 new연산자도 있지만 this함수를 호출 할 때 빈 객체 로 설정 하는 데 사용됩니다 . C ++에서 당신은 모든를 페어링해야 new로모그래퍼 delete아니라 자바 스크립트에서 GC 때문이다. JavaScript에서 메모리 사용을 중지하려면 객체 참조를 중지하면 결국 재생됩니다.
binki

최대 스택 크기를 설정하여 오버플로가 있는지 스택을 확인해야합니까?
꿀벌

16

내 구현 StackQueue사용Linked List

// Linked List
function Node(data) {
  this.data = data;
  this.next = null;
}

// Stack implemented using LinkedList
function Stack() {
  this.top = null;
}

Stack.prototype.push = function(data) {
  var newNode = new Node(data);

  newNode.next = this.top; //Special attention
  this.top = newNode;
}

Stack.prototype.pop = function() {
  if (this.top !== null) {
    var topItem = this.top.data;
    this.top = this.top.next;
    return topItem;
  }
  return null;
}

Stack.prototype.print = function() {
  var curr = this.top;
  while (curr) {
    console.log(curr.data);
    curr = curr.next;
  }
}

// var stack = new Stack();
// stack.push(3);
// stack.push(5);
// stack.push(7);
// stack.print();

// Queue implemented using LinkedList
function Queue() {
  this.head = null;
  this.tail = null;
}

Queue.prototype.enqueue = function(data) {
  var newNode = new Node(data);

  if (this.head === null) {
    this.head = newNode;
    this.tail = newNode;
  } else {
    this.tail.next = newNode;
    this.tail = newNode;
  }
}

Queue.prototype.dequeue = function() {
  var newNode;
  if (this.head !== null) {
    newNode = this.head.data;
    this.head = this.head.next;
  }
  return newNode;
}

Queue.prototype.print = function() {
  var curr = this.head;
  while (curr) {
    console.log(curr.data);
    curr = curr.next;
  }
}

var queue = new Queue();
queue.enqueue(3);
queue.enqueue(5);
queue.enqueue(7);
queue.print();
queue.dequeue();
queue.dequeue();
queue.print();


10

Javascript 배열 shift ()는 특히 많은 요소를 보유 할 때 느립니다. 상각 된 O (1) 복잡도로 대기열을 구현하는 두 가지 방법을 알고 있습니다.

첫 번째는 순환 버퍼와 테이블 이중화를 사용하는 것입니다. 나는 이것을 전에 구현했다. 내 소스 코드는 https://github.com/kevyuu/rapid-queue에서 볼 수 있습니다.

두 번째 방법은 두 개의 스택을 사용하는 것입니다. 이것은 두 개의 스택이있는 대기열의 코드입니다.

function createDoubleStackQueue() {
var that = {};
var pushContainer = [];
var popContainer = [];

function moveElementToPopContainer() {
    while (pushContainer.length !==0 ) {
        var element = pushContainer.pop();
        popContainer.push(element);
    }
}

that.push = function(element) {
    pushContainer.push(element);
};

that.shift = function() {
    if (popContainer.length === 0) {
        moveElementToPopContainer();
    }
    if (popContainer.length === 0) {
        return null;
    } else {
        return popContainer.pop();
    }
};

that.front = function() {
    if (popContainer.length === 0) {
        moveElementToPopContainer();
    }
    if (popContainer.length === 0) {
        return null;
    }
    return popContainer[popContainer.length - 1];
};

that.length = function() {
    return pushContainer.length + popContainer.length;
};

that.isEmpty = function() {
    return (pushContainer.length + popContainer.length) === 0;
};

return that;}

이것은 jsPerf를 사용한 성능 비교입니다.

CircularQueue.shift () 및 Array.shift ()

http://jsperf.com/rapidqueue-shift-vs-array-shift

보시다시피 큰 데이터 세트의 경우 훨씬 빠릅니다.


8

Javascript에서 스택 및 큐를 구현할 수있는 몇 가지 방법이 있습니다. 위의 답변 대부분은 상당히 얕은 구현이며 es6의 새로운 구문 기능을 사용하여 더 읽기 쉽고 강력한 것을 구현하려고합니다.

스택 구현은 다음과 같습니다.

class Stack {
  constructor(...items){
    this._items = []

    if(items.length>0)
      items.forEach(item => this._items.push(item) )

  }

  push(...items){
    //push item to the stack
     items.forEach(item => this._items.push(item) )
     return this._items;

  }

  pop(count=0){
    //pull out the topmost item (last item) from stack
    if(count===0)
      return this._items.pop()
     else
       return this._items.splice( -count, count )
  }

  peek(){
    // see what's the last item in stack
    return this._items[this._items.length-1]
  }

  size(){
    //no. of items in stack
    return this._items.length
  }

  isEmpty(){
    // return whether the stack is empty or not
    return this._items.length==0
  }

  toArray(){
    return this._items;
  }
}

그리고 이것이 스택을 사용하는 방법입니다.

let my_stack = new Stack(1,24,4);
// [1, 24, 4]
my_stack.push(23)
//[1, 24, 4, 23]
my_stack.push(1,2,342);
//[1, 24, 4, 23, 1, 2, 342]
my_stack.pop();
//[1, 24, 4, 23, 1, 2]
my_stack.pop(3)
//[1, 24, 4]
my_stack.isEmpty()
// false
my_stack.size();
//3

이 구현에 대한 자세한 설명과 추가 개선 방법을 보려면 여기를 참조하십시오. http://jschap.com/data-structures-in-javascript-stack/

es6의 큐 구현 코드는 다음과 같습니다.

class Queue{
 constructor(...items){
   //initialize the items in queue
   this._items = []
   // enqueuing the items passed to the constructor
   this.enqueue(...items)
 }

  enqueue(...items){
    //push items into the queue
    items.forEach( item => this._items.push(item) )
    return this._items;
  }

  dequeue(count=1){
    //pull out the first item from the queue
    this._items.splice(0,count);
    return this._items;
  }

  peek(){
    //peek at the first item from the queue
    return this._items[0]
  }

  size(){
    //get the length of queue
    return this._items.length
  }

  isEmpty(){
    //find whether the queue is empty or no
    return this._items.length===0
  }
}

이 구현을 사용하는 방법은 다음과 같습니다.

let my_queue = new Queue(1,24,4);
// [1, 24, 4]
my_queue.enqueue(23)
//[1, 24, 4, 23]
my_queue.enqueue(1,2,342);
//[1, 24, 4, 23, 1, 2, 342]
my_queue.dequeue();
//[24, 4, 23, 1, 2, 342]
my_queue.dequeue(3)
//[1, 2, 342]
my_queue.isEmpty()
// false
my_queue.size();
//3

이러한 데이터 구조의 구현 방법과 추가 개선 방법에 대한 전체 자습서를 보려면 jschap.com의 '자바 스크립트의 데이터 구조로 재생'시리즈를 살펴보십시오. 다음은 대기열에 대한 링크입니다-http: //jschap.com/playing-data-structures-javascript-queues/


7

개념을 기반으로 사용자 정의 클래스를 사용할 수 있습니다. 여기서 작업을 수행하는 데 사용할 수있는 코드 스 니펫

/*
*   Stack implementation in JavaScript
*/



function Stack() {
  this.top = null;
  this.count = 0;

  this.getCount = function() {
    return this.count;
  }

  this.getTop = function() {
    return this.top;
  }

  this.push = function(data) {
    var node = {
      data: data,
      next: null
    }

    node.next = this.top;
    this.top = node;

    this.count++;
  }

  this.peek = function() {
    if (this.top === null) {
      return null;
    } else {
      return this.top.data;
    }
  }

  this.pop = function() {
    if (this.top === null) {
      return null;
    } else {
      var out = this.top;
      this.top = this.top.next;
      if (this.count > 0) {
        this.count--;
      }

      return out.data;
    }
  }

  this.displayAll = function() {
    if (this.top === null) {
      return null;
    } else {
      var arr = new Array();

      var current = this.top;
      //console.log(current);
      for (var i = 0; i < this.count; i++) {
        arr[i] = current.data;
        current = current.next;
      }

      return arr;
    }
  }
}

이것을 확인하려면 콘솔을 사용 하고이 줄을 하나씩 사용해보십시오.

>> var st = new Stack();

>> st.push("BP");

>> st.push("NK");

>> st.getTop();

>> st.getCount();

>> st.displayAll();

>> st.pop();

>> st.displayAll();

>> st.getTop();

>> st.peek();

2
명명 규칙에 대한 Downvote : 생성자로 간주되는 대문자로 시작하는 메소드입니다.
Pavlo

6
/*------------------------------------------------------------------ 
 Defining Stack Operations using Closures in Javascript, privacy and
 state of stack operations are maintained

 @author:Arijt Basu
 Log: Sun Dec 27, 2015, 3:25PM
 ------------------------------------------------------------------- 
 */
var stackControl = true;
var stack = (function(array) {
        array = [];
        //--Define the max size of the stack
        var MAX_SIZE = 5;

        function isEmpty() {
            if (array.length < 1) console.log("Stack is empty");
        };
        isEmpty();

        return {

            push: function(ele) {
                if (array.length < MAX_SIZE) {
                    array.push(ele)
                    return array;
                } else {
                    console.log("Stack Overflow")
                }
            },
            pop: function() {
                if (array.length > 1) {
                    array.pop();
                    return array;
                } else {
                    console.log("Stack Underflow");
                }
            }

        }
    })()
    // var list = 5;
    // console.log(stack(list))
if (stackControl) {
    console.log(stack.pop());
    console.log(stack.push(3));
    console.log(stack.push(2));
    console.log(stack.pop());
    console.log(stack.push(1));
    console.log(stack.pop());
    console.log(stack.push(38));
    console.log(stack.push(22));
    console.log(stack.pop());
    console.log(stack.pop());
    console.log(stack.push(6));
    console.log(stack.pop());
}
//End of STACK Logic

/* Defining Queue operations*/

var queue = (function(array) {
    array = [];
    var reversearray;
    //--Define the max size of the stack
    var MAX_SIZE = 5;

    function isEmpty() {
        if (array.length < 1) console.log("Queue is empty");
    };
    isEmpty();

    return {
        insert: function(ele) {
            if (array.length < MAX_SIZE) {
                array.push(ele)
                reversearray = array.reverse();
                return reversearray;
            } else {
                console.log("Queue Overflow")
            }
        },
        delete: function() {
            if (array.length > 1) {
                //reversearray = array.reverse();
                array.pop();
                return array;
            } else {
                console.log("Queue Underflow");
            }
        }
    }



})()

console.log(queue.insert(5))
console.log(queue.insert(3))
console.log(queue.delete(3))

5

또는 두 개의 배열을 사용하여 큐 데이터 구조를 구현할 수 있습니다.

var temp_stack = new Array();
var stack = new Array();

temp_stack.push(1);
temp_stack.push(2);
temp_stack.push(3);

이제 요소를 팝하면 3,2,1이 출력됩니다. 그러나 FIFO 구조를 원하므로 다음을 수행 할 수 있습니다.

stack.push(temp_stack.pop());
stack.push(temp_stack.pop());
stack.push(temp_stack.pop());

stack.pop(); //Pop out 1
stack.pop(); //Pop out 2
stack.pop(); //Pop out 3

1
이 아니라 작동 만약 당신이 결코 push후 처음으로pop
jnnnnn

5

다음은 두 가지 목표를 가진 상당히 간단한 큐 구현입니다.

  • array.shift ()와 달리이 dequeue 메서드에는 일정한 시간 (O (1))이 걸립니다.
  • 속도를 향상시키기 위해이 방법은 링크 된 목록 방법보다 훨씬 적은 할당량을 사용합니다.

스택 구현은 두 번째 목표 만 공유합니다.

// Queue
function Queue() {
        this.q = new Array(5);
        this.first = 0;
        this.size = 0;
}
Queue.prototype.enqueue = function(a) {
        var other;
        if (this.size == this.q.length) {
                other = new Array(this.size*2);
                for (var i = 0; i < this.size; i++) {
                        other[i] = this.q[(this.first+i)%this.size];
                }
                this.first = 0;
                this.q = other;
        }
        this.q[(this.first+this.size)%this.q.length] = a;
        this.size++;
};
Queue.prototype.dequeue = function() {
        if (this.size == 0) return undefined;
        this.size--;
        var ret = this.q[this.first];
        this.first = (this.first+1)%this.q.length;
        return ret;
};
Queue.prototype.peek = function() { return this.size > 0 ? this.q[this.first] : undefined; };
Queue.prototype.isEmpty = function() { return this.size == 0; };

// Stack
function Stack() {
        this.s = new Array(5);
        this.size = 0;
}
Stack.prototype.push = function(a) {
        var other;
    if (this.size == this.s.length) {
            other = new Array(this.s.length*2);
            for (var i = 0; i < this.s.length; i++) other[i] = this.s[i];
            this.s = other;
    }
    this.s[this.size++] = a;
};
Stack.prototype.pop = function() {
        if (this.size == 0) return undefined;
        return this.s[--this.size];
};
Stack.prototype.peek = function() { return this.size > 0 ? this.s[this.size-1] : undefined; };

5

스택 구현은 다른 답변에서 설명한 것처럼 사소합니다.

그러나이 스레드에서 자바 스크립트로 큐를 구현하기위한 만족스러운 답변을 찾지 못했기 때문에 직접 만들었습니다.

이 스레드에는 세 가지 유형의 솔루션이 있습니다.

  • 배열- array.shift()큰 배열 에서 사용하는 최악의 솔루션 은 매우 비효율적입니다.
  • 연결된 목록-O (1)이지만 각 요소에 개체를 사용하는 것은 다소 과도합니다. 특히 요소가 많고 숫자를 저장하는 것과 같이 작은 경우 특히 그렇습니다.
  • 지연된 시프트 배열-인덱스를 배열과 연관시키는 것으로 구성됩니다. 요소가 큐에서 제외되면 인덱스가 앞으로 이동합니다. 인덱스가 배열의 중간에 도달하면 배열은 2 개로 슬라이스되어 전반부를 제거합니다.

지연 시프트 배열은 내 마음에 가장 만족스러운 솔루션이지만 문제가 될 수있는 하나의 큰 연속 배열에 모든 것을 저장하며 배열이 슬라이스 될 때 응용 프로그램이 엇갈리게됩니다.

작은 배열의 링크 된 목록 (각 1000 요소)을 사용하여 구현했습니다. 배열은 슬라이스되지 않은 것을 제외하고 지연된 시프트 배열처럼 동작합니다. 배열의 모든 요소가 제거되면 배열은 단순히 삭제됩니다.

패키지는 기본 FIFO 기능 으로 npm에 있으며 최근에 푸시했습니다. 코드는 두 부분으로 나뉩니다.

여기 첫 번째 부분이 있습니다

/** Queue contains a linked list of Subqueue */
class Subqueue <T> {
  public full() {
    return this.array.length >= 1000;
  }

  public get size() {
    return this.array.length - this.index;
  }

  public peek(): T {
    return this.array[this.index];
  }

  public last(): T {
    return this.array[this.array.length-1];
  }

  public dequeue(): T {
    return this.array[this.index++];
  }

  public enqueue(elem: T) {
    this.array.push(elem);
  }

  private index: number = 0;
  private array: T [] = [];

  public next: Subqueue<T> = null;
}

그리고 여기 메인 Queue클래스가 있습니다 :

class Queue<T> {
  get length() {
    return this._size;
  }

  public push(...elems: T[]) {
    for (let elem of elems) {
      if (this.bottom.full()) {
        this.bottom = this.bottom.next = new Subqueue<T>();
      }
      this.bottom.enqueue(elem);
    }

    this._size += elems.length;
  }

  public shift(): T {
    if (this._size === 0) {
      return undefined;
    }

    const val = this.top.dequeue();
    this._size--;
    if (this._size > 0 && this.top.size === 0 && this.top.full()) {
      // Discard current subqueue and point top to the one after
      this.top = this.top.next;
    }
    return val;
  }

  public peek(): T {
    return this.top.peek();
  }

  public last(): T {
    return this.bottom.last();
  }

  public clear() {
    this.bottom = this.top = new Subqueue();
    this._size = 0;
  }

  private top: Subqueue<T> = new Subqueue();
  private bottom: Subqueue<T> = this.top;
  private _size: number = 0;
}

: XES6 자바 스크립트 코드를 얻기 위해 타입 주석 ( )을 쉽게 제거 할 수 있습니다.


4

push () 및 pop () 함수를 사용하여 스택을 이해하면 대기열은 이러한 작업 중 하나를 반대 의미로 만드는 것입니다. push ()는 unshift ()이고 pop ()은 esshift ()입니다. 그때:

//classic stack
var stack = [];
stack.push("first"); // push inserts at the end
stack.push("second");
stack.push("last");
stack.pop(); //pop takes the "last" element

//One way to implement queue is to insert elements in the oposite sense than a stack
var queue = [];
queue.unshift("first"); //unshift inserts at the beginning
queue.unshift("second");
queue.unshift("last");
queue.pop(); //"first"

//other way to do queues is to take the elements in the oposite sense than stack
var queue = [];
queue.push("first"); //push, as in the stack inserts at the end
queue.push("second");
queue.push("last");
queue.shift(); //but shift takes the "first" element

성능이 중요한 소프트웨어를 작성하는 사람들에게 경고의 말. 이 .shift()메소드는 적절한 큐 구현이 아닙니다. O (1)이 아니라 O (n)이며 큰 대기열의 경우 속도가 느려집니다.
Rudi Kershaw

3

@perkins가 제안하고 가장 적합한 마지막 노드도 포함하는 큐의 링크 된 목록 버전입니다.

// QUEUE Object Definition

var Queue = function() {
  this.first = null;
  this.last = null;
  this.size = 0;
};

var Node = function(data) {
  this.data = data;
  this.next = null;
};

Queue.prototype.enqueue = function(data) {
  var node = new Node(data);

  if (!this.first){ // for empty list first and last are the same
    this.first = node;
    this.last = node;
  } else { // otherwise we stick it on the end
    this.last.next=node;
    this.last=node;
  }

  this.size += 1;
  return node;
};

Queue.prototype.dequeue = function() {
  if (!this.first) //check for empty list
    return null;

  temp = this.first; // grab top of list
  if (this.first==this.last) {
    this.last=null;  // when we need to pop the last one
  }
  this.first = this.first.next; // move top of list down
  this.size -= 1;
  return temp;
};

대기열에서 대신 temp.data를 반환해야합니다. 그것이 대기열에 있던 것입니다.
not-a-robot

3

링크 된 목록을 기반으로 몇 가지 기본 작업으로 스택 및 큐 데이터 구조의 ES6 OOP 구현을 찾고 있다면 다음과 같이 보일 수 있습니다.

Queue.js

import LinkedList from '../linked-list/LinkedList';

export default class Queue {
  constructor() {
    this.linkedList = new LinkedList();
  }

  isEmpty() {
    return !this.linkedList.tail;
  }

  peek() {
    if (!this.linkedList.head) {
      return null;
    }

    return this.linkedList.head.value;
  }

  enqueue(value) {
    this.linkedList.append(value);
  }

  dequeue() {
    const removedHead = this.linkedList.deleteHead();
    return removedHead ? removedHead.value : null;
  }

  toString(callback) {
    return this.linkedList.toString(callback);
  }
}

Stack.js

import LinkedList from '../linked-list/LinkedList';

export default class Stack {
  constructor() {
    this.linkedList = new LinkedList();
  }

  /**
   * @return {boolean}
   */
  isEmpty() {
    return !this.linkedList.tail;
  }

  /**
   * @return {*}
   */
  peek() {
    if (!this.linkedList.tail) {
      return null;
    }

    return this.linkedList.tail.value;
  }

  /**
   * @param {*} value
   */
  push(value) {
    this.linkedList.append(value);
  }

  /**
   * @return {*}
   */
  pop() {
    const removedTail = this.linkedList.deleteTail();
    return removedTail ? removedTail.value : null;
  }

  /**
   * @return {*[]}
   */
  toArray() {
    return this.linkedList
      .toArray()
      .map(linkedListNode => linkedListNode.value)
      .reverse();
  }

  /**
   * @param {function} [callback]
   * @return {string}
   */
  toString(callback) {
    return this.linkedList.toString(callback);
  }
}

위의 예제에서 스택 및 큐에 사용되는 LinkedList 구현은 여기 GitHub에서 찾을 수 있습니다 .


2

배열 없음

//Javascript stack linked list data structure (no array)

function node(value, noderef) {
    this.value = value;
    this.next = noderef;
}
function stack() {
    this.push = function (value) {
        this.next = this.first;
        this.first = new node(value, this.next);
    }
    this.pop = function () {
        var popvalue = this.first.value;
        this.first = this.first.next;
        return popvalue;
    }
    this.hasnext = function () {
        return this.next != undefined;
    }
    this.isempty = function () {
        return this.first == undefined;
    }

}

//Javascript stack linked list data structure (no array)
function node(value, noderef) {
    this.value = value;
    this.next = undefined;
}
function queue() {
    this.enqueue = function (value) {
        this.oldlast = this.last;
        this.last = new node(value);
        if (this.isempty())
            this.first = this.last;
        else 
           this.oldlast.next = this.last;
    }
    this.dequeue = function () {
        var queuvalue = this.first.value;
        this.first = this.first.next;
        return queuvalue;
    }
    this.hasnext = function () {
        return this.first.next != undefined;
    }
    this.isempty = function () {
        return this.first == undefined;
    }

}

푸시 팝과 같은 내부 기능을 어떻게 실행할 수 있습니까?
Chandan Kumar

2

Javascript의 일반 배열 구조는 스택 (선입 선출)이며 호출에 따라 대기열 (선입 선출)로도 사용할 수 있습니다.

배열을 대기열처럼 작동시키는 방법을 보려면이 링크를 확인하십시오.

대기열


2

문안 인사,

Javascript에서 스택 및 큐의 구현은 다음과 같습니다.

스택 : 스택은 후입 선출 (LIFO) 원리에 따라 삽입 및 제거되는 객체의 컨테이너입니다.

  • 푸시 : 메소드는 배열 끝에 하나 이상의 요소를 추가하고 배열의 새 길이를 리턴합니다.
  • Pop : 메서드는 배열에서 마지막 요소를 제거하고 해당 요소를 반환합니다.

대기열 : 대기열은 선입 선출 (FIFO) 원칙에 따라 삽입 및 제거되는 객체 컨테이너 (선형 컬렉션)입니다.

  • Unshift : 메소드는 배열의 시작 부분에 하나 이상의 요소를 추가합니다.

  • Shift :이 메소드는 배열에서 첫 번째 요소를 제거합니다.

let stack = [];
 stack.push(1);//[1]
 stack.push(2);//[1,2]
 stack.push(3);//[1,2,3]
 
console.log('It was inserted 1,2,3 in stack:', ...stack);

stack.pop(); //[1,2]
console.log('Item 3 was removed:', ...stack);

stack.pop(); //[1]
console.log('Item 2 was removed:', ...stack);


let queue = [];
queue.push(1);//[1]
queue.push(2);//[1,2]
queue.push(3);//[1,2,3]

console.log('It was inserted 1,2,3 in queue:', ...queue);

queue.shift();// [2,3]
console.log('Item 1 was removed:', ...queue);

queue.shift();// [3]
console.log('Item 2 was removed:', ...queue);


1
  var x = 10; 
  var y = 11; 
  var Queue = new Array();
  Queue.unshift(x);
  Queue.unshift(y);

  console.log(Queue)
  // Output [11, 10]

  Queue.pop()
  console.log(Queue)
  // Output [11]

1

내장 배열이 스택에 적합하다고 생각됩니다. TypeScript에서 대기열을 원한다면 여기에 구현이 있습니다.

/**
 * A Typescript implementation of a queue.
 */
export default class Queue {

  private queue = [];
  private offset = 0;

  constructor(array = []) {
    // Init the queue using the contents of the array
    for (const item of array) {
      this.enqueue(item);
    }
  }

  /**
   * @returns {number} the length of the queue.
   */
  public getLength(): number {
    return (this.queue.length - this.offset);
  }

  /**
   * @returns {boolean} true if the queue is empty, and false otherwise.
   */
  public isEmpty(): boolean {
    return (this.queue.length === 0);
  }

  /**
   * Enqueues the specified item.
   *
   * @param item - the item to enqueue
   */
  public enqueue(item) {
    this.queue.push(item);
  }

  /**
   *  Dequeues an item and returns it. If the queue is empty, the value
   * {@code null} is returned.
   *
   * @returns {any}
   */
  public dequeue(): any {
    // if the queue is empty, return immediately
    if (this.queue.length === 0) {
      return null;
    }

    // store the item at the front of the queue
    const item = this.queue[this.offset];

    // increment the offset and remove the free space if necessary
    if (++this.offset * 2 >= this.queue.length) {
      this.queue = this.queue.slice(this.offset);
      this.offset = 0;
    }

    // return the dequeued item
    return item;
  };

  /**
   * Returns the item at the front of the queue (without dequeuing it).
   * If the queue is empty then {@code null} is returned.
   *
   * @returns {any}
   */
  public peek(): any {
    return (this.queue.length > 0 ? this.queue[this.offset] : null);
  }

}

그리고 여기에 대한 Jest테스트가 있습니다

it('Queue', () => {
  const queue = new Queue();
  expect(queue.getLength()).toBe(0);
  expect(queue.peek()).toBeNull();
  expect(queue.dequeue()).toBeNull();

  queue.enqueue(1);
  expect(queue.getLength()).toBe(1);
  queue.enqueue(2);
  expect(queue.getLength()).toBe(2);
  queue.enqueue(3);
  expect(queue.getLength()).toBe(3);

  expect(queue.peek()).toBe(1);
  expect(queue.getLength()).toBe(3);
  expect(queue.dequeue()).toBe(1);
  expect(queue.getLength()).toBe(2);

  expect(queue.peek()).toBe(2);
  expect(queue.getLength()).toBe(2);
  expect(queue.dequeue()).toBe(2);
  expect(queue.getLength()).toBe(1);

  expect(queue.peek()).toBe(3);
  expect(queue.getLength()).toBe(1);
  expect(queue.dequeue()).toBe(3);
  expect(queue.getLength()).toBe(0);

  expect(queue.peek()).toBeNull();
  expect(queue.dequeue()).toBeNull();
});

누군가가 이것이 유용하다는 것을 알기를 바랍니다.

건배,

스투


0

이러한 각 데이터 구조에있는 다양한 메소드 (푸시, 팝, 엿보기 등)를 제공하는 클래스 쌍을 작성하십시오. 이제 메소드를 구현하십시오. 스택 / 큐의 기본 개념을 잘 알고 있다면 매우 간단합니다. 확실히 다른 방법이 있지만 배열과 스택을 사용하여 스택을 스택으로 구현할 수 있습니다. Javascript는 약하게 입력 되었기 때문에 이것을 쉽게 할 수 있으므로 일반적인 유형에 대해 걱정할 필요가 없습니다.이 유형은 Java 또는 C #으로 구현하는 경우해야합니다.


0

여기 내 스택 구현이 있습니다.

function Stack() {
this.dataStore = [];
this.top = 0;
this.push = push;
this.pop = pop;
this.peek = peek;
this.clear = clear;
this.length = length;
}
function push(element) {
this.dataStore[this.top++] = element;
}
function peek() {
return this.dataStore[this.top-1];
}
function pop() {
return this.dataStore[--this.top];
}
function clear() {
this.top = 0;
}
function length() {
return this.top;
}

var s = new Stack();
s.push("David");
s.push("Raymond");
s.push("Bryan");
console.log("length: " + s.length());
console.log(s.peek());

0

ES6 클래스에서 개인 속성을 구현하기 위해 WeakMaps를 사용할 수 있으며 아래와 같이 JavaScript 언어로 된 문자열 속성 및 메서드의 이점을 사용할 수 있습니다.

const _items = new WeakMap();

class Stack {
  constructor() {
    _items.set(this, []);
  }

push(obj) {
  _items.get(this).push(obj);
}

pop() {
  const L = _items.get(this).length;
  if(L===0)
    throw new Error('Stack is empty');
  return _items.get(this).pop();
}

peek() {
  const items = _items.get(this);
  if(items.length === 0)
    throw new Error ('Stack is empty');
  return items[items.length-1];
}

get count() {
  return _items.get(this).length;
}
}

const stack = new Stack();

//now in console:
//stack.push('a')
//stack.push(1)
//stack.count   => 2
//stack.peek()  => 1
//stack.pop()   => 1
//stack.pop()   => "a"
//stack.count   => 0
//stack.pop()   => Error Stack is empty

0

두 개의 스택을 사용하여 큐를 구성하십시오.

대기열에 넣고 대기열에 넣기 작업 모두에 대해 O (1).

class Queue {
  constructor() {
    this.s1 = []; // in
    this.s2 = []; // out
  }

  enqueue(val) {
    this.s1.push(val);
  }

  dequeue() {
    if (this.s2.length === 0) {
      this._move();
    }

    return this.s2.pop(); // return undefined if empty
  }

  _move() {
    while (this.s1.length) {
      this.s2.push(this.s1.pop());
    }
  }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.