आप जावास्क्रिप्ट में एक स्टैक और एक कतार कैसे लागू करते हैं?


738

जावास्क्रिप्ट में एक स्टैक और एक कतार को लागू करने का सबसे अच्छा तरीका क्या है?

मैं शंटिंग-यार्ड एल्गोरिथ्म करना चाह रहा हूं और मुझे इन डेटा-संरचनाओं की आवश्यकता है।

जवाबों:


1344
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
मैं कतार.शिफ्ट का उपयोग करने में सावधानी बरतने की सलाह दूंगा। IIRC यह O (1) नहीं है, लेकिन O (n) और कतार बहुत बड़ी होने पर धीमी हो सकती है।
MAK

20
मैं कहूँगा कि यह जावास्क्रिप्ट कार्यान्वयन पर निर्भर करता है। मुझे नहीं लगता कि यह जावास्क्रिप्ट युक्ति में परिभाषित है।
जॉर्ज स्कोली

9
एक सरल कार्यान्वयन के लिए code.stephenmorley.org/javascript/queues देखें जो कतार प्रदर्शन को बेहतर बनाता है।
गिली

15
कतार प्रदर्शन के मुद्दों के लिए, jsperf.com/queue-push-unshift-vs-shift-pop पर तीन अलग-अलग प्रकार के ढेर व्यवहारों की एक अच्छी तुलना देखें - अब यदि कोई केवल इतना अच्छा था कि वह उस jperperf का रिव्यू शामिल कर सके जेएस लिपि को सम्‍मिलित करें जिसमें @Gili का उल्‍लेख है ...
Nenotlep

3
मैंने इस उत्तर में लिंक की गई ब्लॉग पोस्ट को फिर से जीवित कर दिया क्योंकि आर्काइव.ऑर्ग हमेशा सबसे अधिक प्रदर्शन करने वाला नहीं होता है। मैंने लिंक और चित्र अपडेट किए ताकि वे काम करें लेकिन मैंने कुछ और नहीं बदला।
Chev

87

जावास्क्रिप्ट में पुश और पॉप विधियां हैं, जो सामान्य जावास्क्रिप्ट सरणी वस्तुओं पर काम करती हैं।

कतारों के लिए, यहां देखें:

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

जावास्क्रिप्ट को पुश और शिफ्ट विधियों या सरणी ऑब्जेक्ट के अनशिफ्ट और पॉप तरीकों का उपयोग करके जावास्क्रिप्ट में लागू किया जा सकता है। यद्यपि यह कतारों को लागू करने का एक सरल तरीका है, लेकिन बड़ी कतारों के लिए यह बहुत ही अक्षम है - क्योंकि तरीकों को सरणियों पर संचालित किया जाता है, शिफ्ट और अनशिफ्ट विधियां प्रत्येक तत्व को सरणी में हर बार ले जाती हैं, जिसे वे कहते हैं।

Queue.js जावास्क्रिप्ट के लिए एक सरल और कुशल कतार कार्यान्वयन है जिसका डीक्यू फंक्शन परिशोधित निरंतर समय में चलता है। नतीजतन, बड़ी कतारों के लिए, यह सरणियों का उपयोग करने की तुलना में काफी तेज हो सकता है।


2
आपके द्वारा साझा किए गए लिंक के साथ बेंचमार्क परिणामों की जांच करने की कार्यक्षमता थी और Google Chrome संस्करण 59 के साथ परीक्षण किए जाने पर मुझे प्रदर्शन लाभ दिखाई नहीं दे रहा है। Queue.js अपनी गति के साथ असंगत है, लेकिन क्रोम अपनी गति के अनुरूप था।
शिलजो पॉलसन

इसके अलावा, मैंने क्यू के साथ एक डेमो बनाया। जेएस, कि, डीक्यू फ़ंक्शन वास्तव में कतार से आइटम को नहीं हटाता है, इसलिए मुझे आश्चर्य है कि क्या इसका अनुमान है कि यह कैसे काम करता है? यदि हां, तो पिछली वस्तु को हटाने के बाद आप नई कतार कैसे प्राप्त कर सकते हैं? codepen.io/adamchenwei/pen/VxgNrX?editors=0001
एज़ेवेई

ऐसा लगता है कि क्यू में क्यू के कारण.जैसे अतिरिक्त मेमोरी की भी आवश्यकता होती है क्योंकि यह टुकड़ा के साथ सरणी को क्लोन कर रहा है।
जेटो

इसके अलावा, अंतर्निहित सरणी हर जोड़े गए तत्व के साथ बड़ा और बड़ा हो रहा है। भले ही कार्यान्वयन समय-समय पर सरणी आकार को कम करता है, लेकिन समग्र आकार बढ़ता है।
फिलिप मितर

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.prototyp.pop Array के शीर्ष (प्रथम तत्व) से मान को नहीं हटाता है। यह ऐरे के नीचे (अंतिम तत्व) से मान निकालता है।
माइकल गेलर

20
@ मिचेलगेलर स्टैक के शीर्ष एरे का अंतिम तत्व है। स्ट्रे पुश और पॉप विधियाँ एक स्टैक की तरह व्यवहार करती हैं।
मृदोमयग

@mrdommyg Array.prototype.pop सरणी का अंतिम तत्व निकालता है ( डेवलपर . mozilla.org/en/docs/Web/JavaScript/Reference/… देखें )। इस संदर्भ में अंतिम का अर्थ उच्चतम सूचकांक वाला तत्व है। JS में एक सरणी का स्टैक से कोई लेना-देना नहीं है। यह केवल एक पॉप विधि नहीं होने के कारण एक स्टैक नहीं है। पॉप का अर्थ केवल यह है कि "अंतिम तत्व को हटा दें और इसे वापस करें"। बेशक आप एक सरणी के साथ एक स्टैक की कार्यक्षमता की नकल कर सकते हैं, लेकिन एक सरणी अभी भी परिभाषा द्वारा स्टैक नहीं है। यह अभी भी एक सूची है (एमडीएन के अनुसार "सूची जैसी वस्तु")।
माइकल गेलर

5
@ मिचेलगेलर एक स्टैक का व्यवहार "पहले अंदर, आखिरी बाहर" है। यदि आप जावास्क्रिप्ट में एरे का उपयोग करके इसके तरीकों pushऔर popतरीकों से इसे लागू करते हैं , तो समस्या हल हो गई है। मैं वास्तव में आपकी बात यहाँ नहीं देखता।
रक्स वेबर

2
@ मिचेलगेलर एक स्टैक वैचारिक है। एक जेएस सरणी है (अन्य चीजों के अलावा) स्टैक शब्दार्थ को लागू करने के आधार पर एक स्टैक। सिर्फ इसलिए कि यह भी सरणी शब्दार्थ को लागू करता है कि परिवर्तन नहीं करता है। आप बॉक्स से बाहर एक स्टैक की तरह जेएस सरणी का उपयोग कर सकते हैं, और इस संदर्भ में कि आप क्या धक्का देते हैं और पॉप "शीर्ष" तत्व है।
हंस

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
अंत तक अपील करने के लिए पूरी बात पर पुनरावृति की आवश्यकता से बचने के लिए, इस संदर्भ के माध्यम से पिछले एक संदर्भ को संग्रहीत करें। = नोड;
पर्किन्स

9
जब तक आपके पास इसके लिए कोई बहुत अच्छा कारण नहीं है, तब तक इस तरह से किसी भी कतार को कभी भी लागू न करें ... जबकि यह तार्किक रूप से सही लग सकता है, सीपीयू मानव सार के अनुसार काम नहीं करते हैं। एक डाटासट्रक्चर से अधिक की जगह पर सभी बिंदुओं पर इंगित करने के परिणामस्वरूप सीपीयू में कैश मिसेज का परिणाम होगा, एक अनुक्रमिक सरणी के विपरीत जो अत्यधिक कुशल है। blog.davidecoppola.com/2014/05/… CPU एक जलते हुए जुनून के साथ हेट पॉइंटर्स - वे शायद कैश मिस का # 1 कारण हैं और रैम से मेमोरी एक्सेस करना।
19

1
यह एक आकर्षक समाधान है, लेकिन मुझे यह नहीं लगता Nodeकि पॉपिंग / डिलीट होने पर नष्ट किया जा रहा है ... क्या वे ब्राउज़र के क्रैश होने तक मेमोरी को हॉगिंग के आसपास नहीं बैठेंगे?
cneuro

5
@ Cneuro C ++ के विपरीत, जावास्क्रिप्ट एक कचरा एकत्रित भाषा है। इसका एक deleteकीवर्ड है, लेकिन यह केवल किसी वस्तु की संपत्ति को गैर-मौजूद होने के रूप में चिह्नितundefined करने के लिए उपयोगी है — जो कि संपत्ति को असाइन करने से अलग है । जावास्क्रिप्ट में एक newऑपरेटर भी होता है , लेकिन इसका उपयोग thisकिसी फ़ंक्शन को कॉल करते समय एक नई खाली वस्तु पर सेट करने के लिए किया जाता है । C ++ में आपको हर newएक के साथ युग्मित करने की आवश्यकता है delete, लेकिन जावास्क्रिप्ट में नहीं क्योंकि GC। जावास्क्रिप्ट में मेमोरी का उपयोग करना बंद करने के लिए, बस ऑब्जेक्ट को संदर्भित करना बंद कर दें और इसे अंततः पुनः प्राप्त किया जाएगा।
binki

क्या अधिकतम स्टैक आकार सेट करके अतिप्रवाह के लिए स्टैक की जांच करना भी आवश्यक नहीं है?
मधुमक्खी

16

मेरा उपयोग Stackऔर Queueउपयोग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

जावास्क्रिप्ट एलीमेंट शिफ्ट () कई तत्वों को धारण करते समय विशेष रूप से धीमा है। मैं परिमित 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

ऐसे बहुत से तरीके हैं जिनसे आप जावास्क्रिप्ट में ढेर और कतारें लागू कर सकते हैं। ऊपर दिए गए अधिकांश उत्तर काफी उथले कार्यान्वयन हैं और मैं कुछ अधिक पठनीय (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
एक नामकरण सम्मेलन के लिए डाउनवोट: एक पूंजी के साथ शुरू होने वाली विधि को एक निर्माता माना जाता है।
पावलो

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 () के विपरीत, आप जानते हैं कि यह डीक्यू विधि निरंतर समय (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

जैसा कि अन्य उत्तरों में बताया गया है कि स्टैक कार्यान्वयन तुच्छ है।

हालाँकि, मुझे जावास्क्रिप्ट में एक कतार को लागू करने के लिए इस थ्रेड में कोई संतोषजनक उत्तर नहीं मिला, इसलिए मैंने अपना स्वयं का बनाया।

इस धागे में तीन प्रकार के समाधान हैं:

  • Arrays - सबसे खराब समाधान, उपयोग करना array.shift() बड़े सरणी पर करना बहुत ही अक्षम है।
  • लिंक की गई सूचियां - यह O (1) है, लेकिन प्रत्येक तत्व के लिए एक वस्तु का उपयोग करना थोड़ा अधिक है, खासकर अगर उनमें से बहुत सारे हैं और वे छोटे हैं, जैसे कि संख्या संचय।
  • विलंबित पाली सरणियाँ - इसमें एक सूचकांक को सरणी के साथ जोड़ना शामिल है। जब कोई तत्व समाप्त होता है, तो सूचकांक आगे बढ़ता है। जब सूचकांक सरणी के मध्य तक पहुंच जाता है, तो पहले आधे को निकालने के लिए सरणी दो में कटा हुआ है।

विलंबित शिफ्ट सरणियां मेरे दिमाग में सबसे संतोषजनक समाधान हैं, लेकिन वे अभी भी एक बड़े सन्निहित सरणी में सब कुछ संग्रहीत करते हैं जो समस्याग्रस्त हो सकता है, और सरणी के कट जाने पर आवेदन डगमगा जाएगा।

मैंने छोटे सरणियों (प्रत्येक 1000 तत्व अधिकतम) की लिंक्ड सूची का उपयोग करके एक कार्यान्वयन किया। सरणियों में विलंबित शिफ्ट सरणियों की तरह व्यवहार किया जाता है, सिवाय इसके कि वे कभी कटा हुआ न हों: जब सरणी के प्रत्येक तत्व को हटा दिया जाता है, तो सरणी को केवल त्याग दिया जाता है।

पैकेज npm पर है मूल FIFO कार्यक्षमता के साथ , मैंने अभी हाल ही में इसे धक्का दिया। कोड को दो भागों में विभाजित किया गया है।

यहाँ पहला भाग है

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

यदि आप स्टैक को पुश () और पॉप () फ़ंक्शन के साथ समझते हैं, तो कतार सिर्फ ऑपोसिट अर्थ में इन कार्यों में से एक बनाने के लिए है। पुश का ओपोजिट () अनशिफ्ट () और पॉप का ओपोजिट () एस शिफ्ट () है। फिर:

//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) है, और बड़ी कतारों के लिए धीमा होगा।
रूडी करशॉ

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

Dequeue में, आपको इसके बजाय temp.data को वापस करना चाहिए। क्योंकि वही था जो कतारबद्ध था।
रोबोट

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

और लिंक्डलिस्ट कार्यान्वयन जो ऊपर के उदाहरणों में स्टैक और कतार के लिए उपयोग किया जाता है, यहां 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;
    }

}

मैं पुश पॉप जैसे आंतरिक फ़ंक्शन को कैसे चला सकता हूं?
चंदन कुमार

2

जावास्क्रिप्ट में नियमित सरणी संरचना एक स्टैक (पहली, आखिरी आउट) है और इसे आपके द्वारा किए गए कॉल के आधार पर एक कतार (पहली बार, पहली बाहर) के रूप में भी इस्तेमाल किया जा सकता है।

एक कतार की तरह एक ऐरे बनाने के तरीके को देखने के लिए इस लिंक को देखें:

कतार


2

सादर,

जावास्क्रिप्ट में स्टैक और कतारों का कार्यान्वयन निम्नानुसार है:

स्टैक: स्टैक ऑब्जेक्ट्स का एक कंटेनर होता है जिसे अंतिम-इन-पहले-आउट (LIFO) सिद्धांत के अनुसार डाला और हटाया जाता है।

  • पुश: विधि किसी सरणी के अंत में एक या अधिक तत्व जोड़ता है और सरणी की नई लंबाई लौटाता है।
  • पॉप: विधि एक सरणी से अंतिम तत्व को निकालती है और उस तत्व को वापस करती है।

कतार: एक कतार वस्तुओं का एक कंटेनर (एक रैखिक संग्रह) है जिसे पहले-पहले-आउट (फीफो) सिद्धांत के अनुसार डाला और हटाया जाता है।

  • अनशिफ्ट: विधि किसी सरणी की शुरुआत में एक या अधिक तत्व जोड़ती है।

  • शिफ्ट: विधि एक सरणी से पहला तत्व निकालती है।

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

मुझे लगता है कि एक सरणी के लिए निर्मित सरणी ठीक है। यदि आप टाइपस्क्रिप्ट में एक कतार चाहते हैं तो यहां एक कार्यान्वयन है

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

उन वर्गों की एक जोड़ी बनाएं जो विभिन्न तरीकों को प्रदान करते हैं जो इन डेटा संरचनाओं में से प्रत्येक में हैं (पुश, पॉप, स्ट्रीमिंग, आदि)। अब विधियों को लागू करें। यदि आप स्टैक / कतार के पीछे की अवधारणाओं से परिचित हैं, तो यह बहुत सीधा होना चाहिए। आप एक सरणी के साथ स्टैक को लागू कर सकते हैं, और एक लिंक्ड सूची के साथ एक क्यू, हालांकि निश्चित रूप से इसके बारे में जाने के अन्य तरीके हैं। जावास्क्रिप्ट यह आसान बना देगा, क्योंकि यह कमजोर रूप से टाइप किया गया है, इसलिए आपको जेनेरिक प्रकारों के बारे में चिंता करने की ज़रूरत नहीं है, जो आपको करना होगा यदि आप इसे जावा या सी # में लागू कर रहे हैं।


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 का उपयोग कर सकते हैं और स्ट्रिंग प्रोपेटिज और जावास्क्रिप्ट भाषा में विधियों के लाभ नीचे दिए गए हैं:

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

दो स्टैक का उपयोग करके एक कतार का निर्माण करें।

हे (1) दोनों enqueue और dequeue संचालन के लिए।

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());
    }
  }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.