Новый алгоритм сортировки или повторное открытие? - PullRequest
0 голосов
/ 17 января 2020

Я начинающий программист, который только начал изучать JavaScript. Пока я читал о сортировке массивов, я наткнулся на QuickSort и изучил его алгоритм. Тогда я подумал, что смогу придумать свой собственный «алгоритм».

Мое решение работает следующим образом. Он начинается с поиска самых маленьких и самых больших значений и заменяет их значениями углов одновременно. Затем он работает рекурсивно, пока оба конца не станут равными или не обойдутся

Итак, это новый алгоритм или повторное открытие?

Это моя версия алгоритма сортировки. Мой вопрос:

  1. Вам известен какой-либо другой алгоритм сортировки, который работает следующим образом?

  2. как я могу проверить его скорость по отношению к быстрой сортировке, сортировке по пузырькам ...?

'use strict';

//  +   Name : CornerSort function for sorting arrays                          +
//  +   Author : Kedyr                                                         +
//  +   Date : Jan 15 , 2020                                                   +
//  +   Description : The corner sort function is my first shot at sorting     +
//  +               algorithms.After looking into the quick sort algorithm     +
//  +               i tried to come up with my own sorting logic.It works      +
//  +               by finding the lowest and highest values in an array       +
//  +               and then replacing these values with the corner values.    +
//  +               These process continues recursively until all values are   +
//  +               correctly sorted.Now , from what i can see i believe it    +
//  +               to be a stable sorting algorithm.I haven't tested its      +
//  +               sorting speed and would love it if some one did that.      +
//  +               That is , if it is not an already known algorithm which    +
//  +               I haven't come across yet.Whatever the case is , I am      +
//  +               going to elaborately discuss my 'new' discovery step by    +
//  +               step in the comments . So please bear with me .            +
//  +               For the geniuses who created this algorith before me ,     +
//  +               (if there are any), I bow down to you dear masters.        +
//  +               please forgive my insolence. You know I wouldn't do it     +
//  +               intentionally . It is just that genius minds think         +
//  +               alike . :)                                                 +
//  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function cornerSort(array, startIndex = 0, endIndex = array.length - 1) {
  // These checks if the function is already ordered .
  if (checkOrder(array, startIndex, endIndex)) {
    return;
  }
  // the lowest and highest values.initialised to corner values.
  let lowest = array[startIndex],
    highest = array[endIndex];
  // Indices for the lowest and highest numbers in each recursion. 
  let lowIndex = startIndex,
    highIndex = endIndex;
  let temp;
  if (startIndex >= endIndex) {
    return;
  }
  for (let i = startIndex; i <= endIndex; i++) {
    if (array[i] >= highest) {
      //'or-equal-to' is added to ensure the sorting doesn't change the
      //order of equal numbers.Thus , a stable sorting algorithm.
      highest = array[i];
      highIndex = i;
    }
    if (array[i] < lowest) {
      lowest = array[i];
      lowIndex = i;
    }
  }
  // A PRECAUTION 'IF' : for when the highest number is at the beginning of the array.
  if (highIndex == startIndex) {
    highIndex = lowIndex;
  }
  // The opposite case , lowest number at the end of array ; doesn't cause any issues.
  if (lowIndex != startIndex) {
    temp = array[startIndex];
    array[startIndex] = array[lowIndex];
    array[lowIndex] = temp;
  }
  if (endIndex != highIndex) {
    temp = array[endIndex];
    array[endIndex] = array[highIndex];
    array[highIndex] = temp;
  }
  cornerSort(array, ++startIndex, --endIndex);
  return array;
}

// The CHECKORDER function checks if the array is actually sorted so as to avoid
// unnecessary rounds of recursion.
function checkOrder(array, startIndex, endIndex) {
  let unsortedCount = 0; // count of cases where array[i] > array[i+1].
  for (let i = startIndex; i <= endIndex; i++) {
    if (array[i] > array[i + 1]) {
      unsortedCount++;
    }
  }
  if (!unsortedCount) {
    return true;
  }
  return false;
}
//..............................................................................

Ответы [ 2 ]

2 голосов
/ 17 января 2020

Конечно, невозможно изобрести по-настоящему новый алгоритм сортировки, поскольку существует так много разных способов сортировки. Однако ваш алгоритм существует: он называется двусторонняя выборочная сортировка .

Выборочная сортировка работает путем многократного выбора наименьшего элемента в несортированной части массива и замены его на место. Ваш алгоритм является разновидностью сортировки выбора, поскольку он также выбирает самый большой элемент в несортированной части массива и заменяет его на место в той же итерации внешнего l oop. Это означает, что несортированная часть представляет собой средний сегмент, а не end сегмент массива.

Ваша реализация также намного сложнее, чем она должна быть Вот упрощенная версия, которая должна быть немного более эффективной из-за else if во внутренней l oop. Элемент не может быть одновременно ниже lowest и выше highest. Поскольку мы сканируем как самые низкие, так и самые высокие элементы, также можно определить, когда «несортированная» часть массива постоянна (т. Е. Все ее значения одинаковы) и break early.

function doubleEndedSelectionSort(arr) {
    for(var i = 0, j = arr.length - 1; i < j; i++, j--) {
        var minIdx = i, maxIdx = i;
        var lowest = arr[minIdx], highest = arr[maxIdx];
        for(var k = i + 1; k <= j; k++) {
            var value = arr[k];
            if(value < lowest) {
                minIdx = k;
                lowest = value;
            } else if(value > highest) {
                maxIdx = k;
                highest = value;
            }
        }
        if(minIdx === maxIdx) { break; } // the "unsorted" part of the array is constant
        var iValue = arr[i], jValue = arr[j];
        arr[minIdx] = iValue;
        arr[i] = lowest;
        arr[maxIdx] = jValue;
        arr[j] = highest;
    }
}

Что касается производительности, временная сложность алгоритма такая же, как у O (n²) сортировки выбора, потому что он все еще имеет вложенные циклы, которые повторяют O ( n ) раз каждый. В вашей реализации внешний l oop заменяется рекурсией, но он все еще повторяется O ( n ) раз, поэтому эффект тот же. Это означает, что для достаточно больших входных данных он будет работать хуже, чем алгоритмы сортировки O ( n log n ), такие как быстрая сортировка, сортировка слиянием или сортировка кучи.

1 голос
/ 17 января 2020

Прежде чем начать, я бы предположил, что это, вероятно, больше подходит для информатики

Я не могу сказать, действительно ли это новый алгоритм сортировки; Я думаю, что для того, чтобы кто-то мог ответить на такой вопрос, ему нужно было бы иметь достаточно всестороннее знание алгоритмов сортировки, поскольку их довольно много.

Я могу продемонстрировать, как сравнивать производительность. Вам нужно сделать что-то похожее на других языках, если вы хотите протестировать их, и это тестирует только первые реализации каждой из них, которые я могу найти в inte rnet.

Чтобы правильно понять скорость алгоритм, который у вас есть, вам, вероятно, понадобится найти способ описать, как он работает в различных обстоятельствах; Я понимаю, что обычно это относительно математическое описание алгоритма; возможно, кто-то с большим знанием информатики мог бы восполнить этот пробел.

Но, несмотря на эти условия, вот что может работать при переполнении стека:

function cornerSort(array, startIndex = 0, endIndex = array.length - 1) {
  // These checks if the function is already ordered .
  if (checkOrder(array, startIndex, endIndex)) {
    return;
  }
  // the lowest and highest values.initialised to corner values.
  let lowest = array[startIndex],
    highest = array[endIndex];
  // Indices for the lowest and highest numbers in each recursion. 
  let lowIndex = startIndex,
    highIndex = endIndex;
  let temp;
  if (startIndex >= endIndex) {
    return;
  }
  for (let i = startIndex; i <= endIndex; i++) {
    if (array[i] >= highest) {
      //'or-equal-to' is added to ensure the sorting doesn't change the
      //order of equal numbers.Thus , a stable sorting algorithm.
      highest = array[i];
      highIndex = i;
    }
    if (array[i] < lowest) {
      lowest = array[i];
      lowIndex = i;
    }
  }
  // A PRECAUTION 'IF' : for when the highest number is at the beginning of the array.
  if (highIndex == startIndex) {
    highIndex = lowIndex;
  }
  // The opposite case , lowest number at the end of array ; doesn't cause any issues.
  if (lowIndex != startIndex) {
    temp = array[startIndex];
    array[startIndex] = array[lowIndex];
    array[lowIndex] = temp;
  }
  if (endIndex != highIndex) {
    temp = array[endIndex];
    array[endIndex] = array[highIndex];
    array[highIndex] = temp;
  }
  cornerSort(array, ++startIndex, --endIndex);
  return array;
}

// The CHECKORDER function checks if the array is actually sorted so as to avoid
// unnecessary rounds of recursion.
function checkOrder(array, startIndex, endIndex) {
  let unsortedCount = 0; // count of cases where array[i] > array[i+1].
  for (let i = startIndex; i <= endIndex; i++) {
    if (array[i] > array[i + 1]) {
      unsortedCount++;
    }
  }
  if (!unsortedCount) {
    return true;
  }
  return false;
}

function bubbleSort(a) {
    var swapped;
    do {
        swapped = false;
        for (var i=0; i < a.length-1; i++) {
            if (a[i] > a[i+1]) {
                var temp = a[i];
                a[i] = a[i+1];
                a[i+1] = temp;
                swapped = true;
            }
        }
    } while (swapped);
}

function swap(items, leftIndex, rightIndex){
    var temp = items[leftIndex];
    items[leftIndex] = items[rightIndex];
    items[rightIndex] = temp;
}
function partition(items, left, right) {
    var pivot   = items[Math.floor((right + left) / 2)], //middle element
        i       = left, //left pointer
        j       = right; //right pointer
    while (i <= j) {
        while (items[i] < pivot) {
            i++;
        }
        while (items[j] > pivot) {
            j--;
        }
        if (i <= j) {
            swap(items, i, j); //sawpping two elements
            i++;
            j--;
        }
    }
    return i;
}

function quickSort(items, left, right) {
    var index;
    if (items.length > 1) {
        index = partition(items, left, right); //index returned from partition
        if (left < index - 1) { //more elements on the left side of the pivot
            quickSort(items, left, index - 1);
        }
        if (index < right) { //more elements on the right side of the pivot
            quickSort(items, index, right);
        }
    }
    return items;
}


const testData = [...Array(10000).keys()].map(x => Math.random() * 1000)

console.time('corner')
const x = cornerSort(testData);
console.timeEnd('corner')

console.time('bubble')
const y = bubbleSort(testData);
console.timeEnd('bubble')

console.time('quick')
const z = quickSort(testData);
console.timeEnd('quick')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...