JavaScript'te Yığın ve Kuyruğu nasıl uygularsınız?


Yanıtlar:


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

" bilmediğiniz 9 javascript ipucu "


218
Queue.shift kullanırken dikkatli olmanızı öneririm. IIRC O (1) değil, O (n) 'dir ve kuyruk büyürse çok yavaş olabilir.
MAK

20
Bunun javascript uygulamasına bağlı olduğunu söyleyebilirim. Javascript spec tanımlanmış sanmıyorum.
Georg Schölly

9
Kuyruk performansını artıran basit bir uygulama için code.stephenmorley.org/javascript/queues adresine bakın .
Gili

15
Kuyruk performans sorunları için üzerinde yığın davranışları üç farklı türde güzel bir karşılaştırmasını görmek jsperf.com/queue-push-unshift-vs-shift-pop - Artık sadece birisi o jsperf bir rev dahil etmek güzel yeterli olsaydı o olur @Gili'in bahsettiği JS betiğini içerir ...
Nenotlep

3
Archive.org her zaman en yüksek performans göstermediği için bu cevaba bağlanan blog gönderisini dirilttim . Bağlantıları ve resimleri güncelledim, böylece çalışıyorlar ama başka bir şey değiştirmedim.
Chev

87

Javascript, sıradan Javascript dizi nesneleri üzerinde çalışan push ve pop yöntemlerine sahiptir.

Kuyruklar için buraya bakın:

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

Kuyruklar JavaScript'te dizi nesnesinin push ve shift yöntemleri veya unshift ve pop yöntemleri kullanılarak uygulanabilir. Bu, sıraları uygulamanın basit bir yolu olmasına rağmen, büyük sıralar için çok verimsizdir - yöntemler dizilerde çalıştığından, shift ve unshift yöntemleri her çağrıldığında dizideki her öğeyi taşır.

Queue.js, dequeue işlevi itfa edilmiş sabit sürede çalışan JavaScript için basit ve etkili bir kuyruk uygulamasıdır. Sonuç olarak, daha büyük kuyruklar için, dizileri kullanmaktan önemli ölçüde daha hızlı olabilir.


2
Paylaştığınız bağlantı, karşılaştırma sonuçlarını kontrol etme işlevine sahipti ve Google Chrome sürüm 59 ile test edildiğinde performans kazancı görmüyorum. Queue.js, hızıyla tutarsız, ancak Chrome hızıyla tutarlıydı.
Shiljo Paulson

Ayrıca, queue.js ile bir demo yaptım, bu, dequeue işlevi gerçekten sıradan öğeyi kaldırmaz, bu yüzden onun nasıl çalıştığını varsayalım acaba? Öyleyse, önceki öğeyi ayıkladıktan sonra yeni kuyruğu nasıl alabilirsiniz? codepen.io/adamchenwei/pen/VxgNrX?editors=0001
Ezeewei

queue.js'deki dequeue, diziyi dilim ile klonladığı için ek bellek gerektiriyor gibi görünüyor.
JaTo

Ayrıca, temel alınan dizi eklenen her öğe ile gittikçe büyüyor. Uygulama zaman zaman dizi boyutunu küçülse de, toplam boyut artar.
Philipp Mitterer

73

Diziler.

Stack:

var stack = [];

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

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

kuyruk:

var queue = [];

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

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

1
Array.prototype.pop, Dizinin üstünden (ilk öğe) değeri kaldırmaz. Değeri Dizinin altından (son öğe) kaldırır.
Michael Geller

21
@MichaelGeller Yığının üst kısmı Dizinin son öğesidir. Dizi itme ve pop yöntemleri tıpkı bir yığın gibi davranır.
mrdommyg

@mrdommyg Array.prototype.pop dizinin son öğesini kaldırır (bkz. developer.mozilla.org/en/docs/Web/JavaScript/Reference/… ). Bu bağlamda sonuncusu, en yüksek indekse sahip eleman anlamına gelir. JS'deki bir dizinin yığınla ilgisi yoktur. Bir pop yöntemi olduğu için bir yığın değildir. Pop sadece "son elemanı kaldır ve geri ver" anlamına gelir. Tabii ki bir diziye sahip bir yığının işlevselliğini taklit edebilirsiniz, ancak bir dizi hala tanım gereği bir yığın değildir. Hala bir listedir (MDN'ye göre "liste benzeri" bir nesne).
Michael Geller

5
@MichaelGeller Bir yığının davranışı "ilk giren son çıkar" dır. JavaScript pushve popyöntemleriyle bir Array kullanarak uygularsanız , sorun çözülmüştür. Burada gerçekten ne demek istediğini anlamıyorum.
Rax Weber

2
@MichaelGeller Bir yığın kavramsaldır. Bir JS dizisi (diğer şeylerin yanı sıra) tanım anlamında yığın semantiğini uygulayarak bir yığıntır. Dizi semantiği de uyguladığı için bunu değiştirmez. Kutusundan çıkmış gibi bir JS dizisi kullanabilirsiniz ve bu bağlamda "it" (pop) öğesinin "üst" öğedir.
Hans

32

Kendi veri yapılarınızı oluşturmak istiyorsanız, kendi veri yapılarınızı oluşturabilirsiniz:

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;
};

Ve kuyruk için:

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
Sonuna eklemek için her şeyi yinelemekten kaçınmak için, this.last = node;
Perkins

9
Gerçekten iyi bir nedeniniz olmadıkça asla böyle bir Kuyruk uygulamayın ... mantıksal olarak doğru görünse de, CPU'lar insan soyutlamalarına göre çalışmaz. Her yerde işaretçiler bulunan bir veri yapısı üzerinde yineleme yapmak, oldukça verimli olan sıralı bir dizinin aksine CPU'da önbellek hatalarına neden olacaktır. blog.davidecoppola.com/2014/05/… İşlemciler yanan tutkuyla işaretçilerden NEFRET EDİYOR - muhtemelen önbellek hatalarının ve RAM'den belleğe erişmenin 1 numaralı nedeni.
Centril

1
Bu cazip bir çözüm, ancak Nodehaşhaş / ayıklama sırasında oluşturulan s siliniyor görmüyorum ... tarayıcı çöker kadar sadece hogging bellek etrafında oturmak olmaz mı?
cneuro

5
@cneuro C ++ 'dan farklı olarak, JavaScript çöp toplanmış bir dildir. Bu bir var deleteanahtar kelime, ama bu kullunın olmayan mevcut -ki sadece atama farklıdır olarak bir nesnenin bir özelliğini işaretlemek undefinedözelliğine . JavaScript'in bir de newoperatörü vardır, ancak bu sadece thisbir işlevi çağırırken yeni bir boş nesneye ayarlamak için kullanılır . C ++ newile her birini deleteGC ile eşleştirmeniz gerekir; JavaScript'te bellek kullanmayı durdurmak için, nesneye başvurmayı durdurmanız yeterlidir ve sonunda geri kazanılacaktır.
binki

Maksimum yığın boyutu ayarlayarak bir yığını taşma açısından kontrol etmek gerekli değil mi?
arı

16

Uygulamam Stackve QueuekullanmamLinked 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 dizi shift () özellikle birçok öğeyi tutarken yavaştır. İtfa edilmiş O (1) karmaşıklığı ile kuyruğu uygulamanın iki yolunu biliyorum.

Birincisi, dairesel tampon ve tablonun iki katına çıkarılmasıdır. Bunu daha önce uygulamıştım. Kaynak kodumu burada görebilirsiniz https://github.com/kevyuu/rapid-queue

İkinci yol, iki yığın kullanmaktır. Bu, iki yığına sahip kuyruk için koddur

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;}

Bu, jsPerf kullanan performans karşılaştırmasıdır

CircularQueue.shift () ve Array.shift ()

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

Gördüğünüz gibi büyük veri seti ile çok daha hızlı


8

Javascript'te Yığınları ve Kuyrukları uygulayabileceğiniz birkaç yol vardır. Yukarıdaki cevapların çoğu oldukça sığ uygulamalardır ve daha okunabilir bir şey (es6'nın yeni sözdizimi özelliklerini kullanarak) ve sağlam bir şey uygulamaya çalışacağım.

İşte yığın uygulaması:

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;
  }
}

Ve yığını şu şekilde kullanabilirsiniz:

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

Bu uygulama ve bunun nasıl daha da geliştirilebileceği ile ilgili ayrıntılı açıklamayı görmek isterseniz, buradan okuyabilirsiniz: http://jschap.com/data-structures-in-javascript-stack/

İşte es6'da kuyruk uygulaması için kod:

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
  }
}

Bu uygulamayı nasıl kullanabileceğiniz aşağıda açıklanmıştır:

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

Bu veri yapılarının nasıl uygulandığına ve bunların nasıl daha da geliştirilebileceğine dair tam bir eğiticiden geçmek için jschap.com adresindeki 'Javascript'te veri yapılarıyla oynama' serisini incelemek isteyebilirsiniz. İşte kuyruklar için bağlantılar - http://jschap.com/playing-data-structures-javascript-queues/


7

Konsepte dayalı olarak kendi özelleştirme sınıfınızı kullanabilirsiniz, burada işleri yapmak için kullanabileceğiniz kod snippet'i

/*
*   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;
    }
  }
}

bunu kontrol etmek için konsolunuzu kullanın ve bu satırı tek tek deneyin.

>> 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
Bir adlandırma kuralı için aşağı oy: yapıcı olduğu varsayılan bir sermaye ile başlayan yöntem.
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

Ya da kuyruk veri yapısını uygulamak için iki dizi kullanabilirsiniz.

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

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

Elemanları şimdi patlatırsam, çıktı 3,2,1 olacaktır. Ancak FIFO yapısını istiyoruz, böylece aşağıdakileri yapabilirsiniz.

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
Bu sadece pushilk kez sen sonra asla çalışırpop
jnnnnn

5

İşte iki amacı olan oldukça basit bir kuyruk uygulaması:

  • Array.shift () 'in aksine, bu dequeue yönteminin sabit zaman aldığını (O (1)) bilirsiniz.
  • Hızı artırmak için, bu yaklaşım bağlantılı liste yaklaşımından çok daha az tahsis kullanır.

Yığın uygulaması yalnızca ikinci amacı paylaşır.

// 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

Yığın uygulaması diğer cevaplarda açıklandığı gibi önemsizdir.

Ancak, ben javascript bir kuyruk uygulamak için bu iş parçacığında herhangi bir tatmin edici cevap bulamadık, bu yüzden kendi yaptı.

Bu iş parçacığında üç tür çözüm vardır:

  • Diziler - array.shift()Büyük bir dizide kullanılan en kötü çözüm çok verimsizdir.
  • Bağlantılı listeler - O (1), ancak her öğe için bir nesne kullanmak biraz fazla, özellikle de birçoğu varsa ve sayıları depolamak gibi küçükse.
  • Gecikmeli kaydırma dizileri - Bir dizinin diziyle ilişkilendirilmesinden oluşur. Bir öğe ayıklandığında, dizin ileriye doğru hareket eder. Dizin dizinin ortasına ulaştığında, dizi ilk yarıyı kaldırmak için ikiye bölünür.

Gecikmeli vardiya dizileri aklımdaki en tatmin edici çözümdür, ancak yine de her şeyi sorunlu olabilecek büyük bir bitişik dizide saklarlar ve dizi dilimlendiğinde uygulama sendeleyecektir.

Bağlantılı küçük diziler (her biri maksimum 1000 öğe) kullanarak bir uygulama yaptım. Diziler, hiçbir zaman dilimlenmemesi dışında gecikmeli kaydırma dizileri gibi davranırlar: dizideki her öğe kaldırıldığında dizi atılır.

Paket npm'de temel FIFO işlevselliği ile, son zamanlarda ittim. Kod iki kısma ayrılmıştır.

İşte ilk bölüm

/** 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;
}

Ve işte ana Queuesınıf:

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 javascript kodunu elde etmek için tür ek açıklamaları ( ) kolayca kaldırılabilir.


4

Push () ve pop () işlevlerine sahip yığınları anlarsanız, sıra yalnızca bu işlemlerden birini dışsal anlamda yapmaktır. Push () öğesinin opareti unshift () ve pop () es shift () öğesinin opozisidir. Sonra:

//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

Performans açısından kritik öneme sahip yazılımlar yazanlar için bir uyarı. .shift()Yöntem uygun bir kuyruk bir uygulama değildir. O (1) yerine O (n) 'dir ve büyük kuyruklar için yavaş olacaktır.
Rudi Kershaw

3

@Perkins tarafından önerilen ve en uygun olanı da son düğümü içeren bir kuyruğun bağlantılı liste sürümü.

// 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;
};

Dequeue'de bunun yerine temp.data döndürmelisiniz. Çünkü sıraya konan buydu.
robot değil

3

Bazı temel işlemlerle (bağlantılı listelere dayalı) Stack ve Queue veri yapısının ES6 OOP uygulamasını arıyorsanız, aşağıdaki gibi görünebilir:

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);
  }
}

Yukarıdaki örneklerde Yığın ve Kuyruk için kullanılan LinkedList uygulaması GitHub'da burada bulunabilir .


2

Dizi Yok

//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;
    }

}

Push pop gibi verilen dahili işlevi nasıl çalıştırabilirim?
Chandan Kumar

2

Javascript'teki normal Dizi yapısı bir Yığın (ilk giriş, son çıkış) ve ayrıca yaptığınız aramalara bağlı olarak Kuyruk (ilk giriş, ilk çıkış) olarak da kullanılabilir.

Bir Dizinin nasıl Kuyruk gibi davranacağını görmek için bu bağlantıyı kontrol edin:

Kuyruklar


2

Saygılarımızla,

Javascript'te yığınların ve kuyrukların uygulanması aşağıdaki gibidir:

Yığın: Yığın, ilk giren ilk çıkar (LIFO) ilkesine göre eklenen ve çıkarılan bir nesne kabıdır.

  • Push: Yöntem bir dizinin sonuna bir veya daha fazla öğe ekler ve dizinin yeni uzunluğunu döndürür.
  • Pop: Yöntem bir dizideki son öğeyi kaldırır ve o öğeyi döndürür.

Kuyruk: Kuyruk , ilk giren ilk çıkar (FIFO) ilkesine göre eklenen ve çıkarılan bir nesne kabıdır (doğrusal bir koleksiyon).

  • Kaldır: Yöntem, bir dizinin başına bir veya daha fazla öğe ekler.

  • Shift: Yöntem, bir dizideki ilk öğeyi kaldırır.

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

Yerleşik dizi bir yığın için iyi görünüyor bana. TypeScript'te bir Kuyruk istiyorsanız burada bir uygulama var

/**
 * 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);
  }

}

Ve işte bunun için bir Jesttest

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();
});

Umarım birisi bunu faydalı bulur,

Alkış,

Stu


0

Bu veri yapılarının her birinin sahip olduğu çeşitli yöntemleri (push, pop, peek, vb.) Sağlayan bir çift sınıf oluşturun. Şimdi yöntemleri uygulayın. Yığın / kuyruğun arkasındaki kavramlara aşina iseniz, bu oldukça basit olmalıdır. Yığını bir dizi ve bağlantılı bir listeye sahip bir kuyrukla uygulayabilirsiniz, ancak bununla ilgili kesinlikle başka yollar da vardır. Javascript bunu kolaylaştıracaktır, çünkü zayıf yazılmıştır, bu yüzden Java veya C # ile uygularsanız yapmanız gereken genel türler hakkında endişelenmenize bile gerek yoktur.


0

İşte Yığının Uygulanması.

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

WeakMaps'i ES6 sınıfında özel mülk uygulamak ve aşağıdaki gibi JavaScript dilinde String özelliklerinin ve yöntemlerinin avantajlarını uygulamak için kullanabilirsiniz:

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

İki Yığın kullanarak bir Kuyruk oluşturun.

O (1) hem enqueue hem de dequeue işlemleri için.

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());
    }
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.