जावास्क्रिप्ट Array.sort कार्यान्वयन?


236

जावास्क्रिप्ट Array#sort()फ़ंक्शन किस एल्गोरिथ्म का उपयोग करता है? मैं समझता हूं कि विभिन्न प्रकार के प्रदर्शन करने के लिए यह सभी तरह के तर्क और कार्य कर सकता है, मुझे बस दिलचस्पी है कि एल्गोरिथ्म में वेनिला सॉर्ट का उपयोग होता है।


आपको दिए गए विकल्पों में से एक वैकल्पिक समाधान पर विचार करना चाहिए।
एंथनी

जवाबों:


77

यदि आप इस बग 224128 को देखते हैं , तो ऐसा प्रतीत होता है कि मर्जर्ट का उपयोग मोज़िला द्वारा किया जा रहा है।


3
वैसे यह भी गलत है कि यह केवल एक विशिष्ट कार्यान्वयन के लिए एक एल्गोरिथ्म बताता है। विनिर्देश ऐसा कोई दावा नहीं करता है, और अन्य कार्यान्वयन अन्य एल्गोरिदम का उपयोग करते हैं, इसलिए यह काफी भ्रामक है।
पैट्रिक रॉबर्ट्स

292

मैंने अभी-अभी WebKit (Chrome, Safari…) स्रोत पर एक नज़र डाली है । सरणी के प्रकार के आधार पर, विभिन्न प्रकार के तरीकों का उपयोग किया जाता है:

संख्यात्मक सरणियों (या आदिम प्रकार के सरणियों) को C ++ मानक लाइब्रेरी फ़ंक्शन का उपयोग करके सॉर्ट किया जाता है std::qsortजो क्विकॉर्ट्स (आमतौर पर इंट्रोसर्ट ) के कुछ भिन्नता को लागू करता है ।

नॉन-न्यूमेरिक प्रकार के समवर्ती सरणियों को कड़ा कर दिया जाता है और मर्जों का उपयोग करके सॉर्ट किया जाता है, यदि उपलब्ध हो (एक स्थिर सॉर्टिंग प्राप्त करने के लिए) या qsortयदि कोई मर्ज सॉर्ट उपलब्ध नहीं है।

अन्य प्रकारों के लिए (गैर-सन्निहित सरणियों और संभवतः साहचर्य सरणियों के लिए) WebKit चयन प्रकार (जिसे वे "न्यूनतम" सॉर्ट कहते हैं ) का उपयोग करता है या, कुछ मामलों में, यह AVL ट्री के माध्यम से सॉर्ट करता है। दुर्भाग्य से, यहाँ प्रलेखन अस्पष्ट है, इसलिए आपको कोड पथ का पता लगाने के लिए वास्तव में यह देखना होगा कि किस प्रकार की विधि का उपयोग किया जाता है।

और फिर इस टिप्पणी की तरह रत्न भी हैं :

// FIXME: Since we sort by string value, a fast algorithm might be to use a
// radix sort. That would be O(N) rather than O(N log N).

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

(मूल उत्तर में त्रुटि को इंगित करने के लिए phsource के लिए धन्यवाद।)


46

जेएस के लिए किसी विशिष्ट छंटाई वाले अल्गोरथिम का उपयोग करने के लिए कोई मसौदा आवश्यकता नहीं है। जैसा कि कई लोगों ने यहां बताया है, मोज़िला मर्ज सॉर्ट का उपयोग करता है। हालांकि, क्रोम के v8 स्रोत कोड में, आज तक, यह छोटे सरणियों के लिए क्विकॉर्ट और इंसर्शनसॉर्ट का उपयोग करता है।

V8 इंजन स्रोत

लाइन्स से 807 - 891

  var QuickSort = function QuickSort(a, from, to) {
    var third_index = 0;
    while (true) {
      // Insertion sort is faster for short arrays.
      if (to - from <= 10) {
        InsertionSort(a, from, to);
        return;
      }
      if (to - from > 1000) {
        third_index = GetThirdIndex(a, from, to);
      } else {
        third_index = from + ((to - from) >> 1);
      }
      // Find a pivot as the median of first, last and middle element.
      var v0 = a[from];
      var v1 = a[to - 1];
      var v2 = a[third_index];
      var c01 = comparefn(v0, v1);
      if (c01 > 0) {
        // v1 < v0, so swap them.
        var tmp = v0;
        v0 = v1;
        v1 = tmp;
      } // v0 <= v1.
      var c02 = comparefn(v0, v2);
      if (c02 >= 0) {
        // v2 <= v0 <= v1.
        var tmp = v0;
        v0 = v2;
        v2 = v1;
        v1 = tmp;
      } else {
        // v0 <= v1 && v0 < v2
        var c12 = comparefn(v1, v2);
        if (c12 > 0) {
          // v0 <= v2 < v1
          var tmp = v1;
          v1 = v2;
          v2 = tmp;
        }
      }
      // v0 <= v1 <= v2
      a[from] = v0;
      a[to - 1] = v2;
      var pivot = v1;
      var low_end = from + 1;   // Upper bound of elements lower than pivot.
      var high_start = to - 1;  // Lower bound of elements greater than pivot.
      a[third_index] = a[low_end];
      a[low_end] = pivot;

      // From low_end to i are elements equal to pivot.
      // From i to high_start are elements that haven't been compared yet.
      partition: for (var i = low_end + 1; i < high_start; i++) {
        var element = a[i];
        var order = comparefn(element, pivot);
        if (order < 0) {
          a[i] = a[low_end];
          a[low_end] = element;
          low_end++;
        } else if (order > 0) {
          do {
            high_start--;
            if (high_start == i) break partition;
            var top_elem = a[high_start];
            order = comparefn(top_elem, pivot);
          } while (order > 0);
          a[i] = a[high_start];
          a[high_start] = element;
          if (order < 0) {
            element = a[i];
            a[i] = a[low_end];
            a[low_end] = element;
            low_end++;
          }
        }
      }
      if (to - high_start < low_end - from) {
        QuickSort(a, high_start, to);
        to = low_end;
      } else {
        QuickSort(a, from, low_end);
        from = high_start;
      }
    }
  };

अपडेट 2018 के अनुसार V8 टिमशॉर्ट का उपयोग करता है, धन्यवाद @सेलवेल। स्रोत


9
मेरा मानना ​​है कि V8 अब TimSort का उपयोग कर रहा है: github.com/v8/v8/blob/78f2610345fdd14ca401d920c140f8f461b631d1/…
ccwell

24

ECMAscript मानक निर्दिष्ट नहीं करता है कि किस प्रकार के एल्गोरिदम का उपयोग किया जाना है। दरअसल, विभिन्न ब्राउज़रों में अलग-अलग तरह के एल्गोरिदम होते हैं। उदाहरण के लिए, मोज़िला / फ़ायरफ़ॉक्स का सॉर्ट () शब्द की छंटाई के समय स्थिर नहीं है (शब्द की सॉर्टिंग अर्थ में)। IE का सॉर्ट () स्थिर है।


15
अद्यतन: हाल के फ़ायरफ़ॉक्स में एक स्थिर है Array.sort; इस प्रश्न को देखें ।
स्केडल

मुद्दा यह है कि छंटाई एल्गोरिथ्म कार्यान्वयन-निर्भर है।
शॉन

जिज्ञासु के लिए, ECMAscript
बेंजामिन

10

कुछ और शोध के बाद, यह दिखाई देता है, मोज़िला / फ़ायरफ़ॉक्स के लिए, कि Array.sort () मर्जर्ट का उपयोग करता है। यहां कोड देखें ।


8

मुझे लगता है कि इस बात पर निर्भर करेगा कि आप किस ब्राउज़र कार्यान्वयन को संदर्भित कर रहे हैं।

प्रत्येक ब्राउज़र प्रकार में इसका स्वयं का जावास्क्रिप्ट इंजन कार्यान्वयन होता है, इसलिए यह निर्भर करता है। आप मोज़िला और वेबकिट / खटमल के लिए अलग-अलग कार्यान्वयन के लिए स्रोत कोड की जांच कर सकते हैं।

IE, हालांकि स्रोत बंद है, इसलिए आपको Microsoft में किसी से पूछना पड़ सकता है।


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

2
@JasonBunting यदि फ़ंक्शन कार्यान्वित किया जाता है और वह करता है जो इसे विनिर्देश में परिभाषित किया जाना चाहिए, तो ब्राउज़र डेवलपर्स फ़ंक्शन को लागू करने के लिए स्वतंत्र हैं जैसे वे चाहते हैं: यह बुलबुला या त्वरित प्रकार हो। ECMA चश्मा उपयोग किए जाने वाले सॉर्ट एल्गोरिथ्म को परिभाषित नहीं करता है।
दामिर ज़ेकिच

4

V8 v7.0 / Chrome 70 के रूप में, V8 TimSort , पायथन के सॉर्टिंग एल्गोरिथ्म का उपयोग करता है। क्रोम 70 को 13 सितंबर, 2018 को रिलीज़ किया गया था।

इस परिवर्तन के विवरण के लिए V8 देव ब्लॉग पर पोस्ट देखें । आप स्रोत कोड या पैच 1186801 भी पढ़ सकते हैं ।


0

JavaScript का Array.sort () फ़ंक्शन में सरणी तत्वों के डेटाटाइप के आधार पर सर्वोत्तम सॉर्टिंग एल्गोरिथ्म (QuickSort, MergeSort, आदि) का चयन करने के लिए आंतरिक तंत्र है।


0

इसे त्वरित रूप से आज़माएं:

function sort(arr, compareFn = (a, b) => a <= b) {

    if (!arr instanceof Array || arr.length === 0) {
        return arr;
    }

    if (typeof compareFn !== 'function') {
        throw new Error('compareFn is not a function!');
    }

    const partition = (arr, low, high) => {
        const pivot = arr[low];
        while (low < high) {
            while (low < high && compareFn(pivot, arr[high])) {
                --high;
            }
            arr[low] = arr[high];
            while (low < high && compareFn(arr[low], pivot)) {
                ++low;
            }
            arr[high] = arr[low];
        }
        arr[low] = pivot;
        return low;
    };

    const quickSort = (arr, low, high) => {
        if (low < high) {
            let pivot = partition(arr, low, high);
            quickSort(arr, low, pivot - 1);
            quickSort(arr, pivot + 1, high);
        }
        return arr;
    };

    return quickSort(arr, 0, arr.length - 1);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.