簡體   English   中英

氣泡,選擇,插入和快速排序中的交換和比較次數

[英]number of swaps and comparisons in bubble, selection, insertion and quick sorts

我已經用Java實現了所有四種排序算法。 只是為了解決問題,我決定查看每種算法中的交換次數和比較次數。 對於大小為20的隨機數組,這是我的結果

氣泡排序:87次互換,87次比較

插入排序:87個交換,87個比較

選擇排序:19個交換,29個比較

快速排序:11940個交換,我什至不知道從哪里計算比較

為什么氣泡排序和選擇排序相同? 我的意思是看代碼我幾乎可以看到它。 循環幾乎相同,我只是希望有人為我指出。

我可以看到為什么選擇排序的交換次數最少

快速排序對我來說是個謎(該死的您遞歸)。 我認為這就是交換次數瘋狂的原因。 為什么我的執行速度這么慢? 其他三個完成之前。

*****代碼-讓我知道是否缺少任何內容**

交換對於所有三個實施都是相同的

private void swap(int firstIndex, int secondIndex) {
    int temp = array[firstIndex];
    array[firstIndex] = array[secondIndex];
    array[secondIndex] = temp;
}

氣泡

public void sort() {
    for(int out = nElements-1; out > 1; out--) {// outer backwards loop
        for(int in = 0; in < out; in++) { // inner forward loop 
            if(array[in] > array[in+1]) {
                swap(in, in + 1);
                totalSwaps++;
                totalComparisons++;
            }
        }
    }
}

選擇

public void sort() {
    for (int i = 0; i < nElements-1; i++) {
        int currentMinIndex = i;
        for (int j = i + 1; j < nElements; j++)
            if (array[j] < array[currentMinIndex]) {
                currentMinIndex = j;
                totalComparisons++;
            }
        swap(i, currentMinIndex);
        totalSwaps++;
    }
}

插入

public void sort() {
    for(int i = 1; i < nElements; i++) {
        for(int j = i; j > 0; j--) {
            if(array[j] < array[j-1]) {
                swap(j, j - 1);
                totalSwaps++;
                totalComparisons++;
            }
        }
    }
}

快速排序

public void sort() {
    sort(this.array, 0, array.length - 1);
}
private void sort(int[] array, int left, int right) {
    if(left >= right)
        return;

    int randomIndex = new Random().nextInt(array.length);
    int pivot = array[randomIndex];

    // returns the dividing point between the left side and the right side
    int index = partition(array, left, right, pivot);

    sort(array, left, index - 1);
    sort(array, index, right);
}

private int partition(int[] array, int left, int right, int pivot) {
    while(left <= right) {
        while(array[left] < pivot)  // will break when there's an element to the left of the pivot that's greater
            left++;

        while(array[right] > pivot)  // breaks when there's an element to the right of the pivot that's less
            right--;

        if(left <= right) {
            swap(left, right);
            left++;
            right--;
            totalSwaps++;

        }

    }

    return left;  // left will be at the partition point
}

主要

import java.util.Random;


public class Sorting {

private static final int maxSize = 50;
private static int[] randomArray() {
    int[] array = new int[maxSize];
    Random random = new Random();
    random.setSeed(0);
    for(int i = 0; i < maxSize; i++)
        array[i] = random.nextInt(50);
    return array;
}

public static void main(String[] args) {

    int[] randomArr = randomArray();

    BubbleSort bubbleSort = new BubbleSort(randomArr);
    bubbleSort.display();
    bubbleSort.sort();
    bubbleSort.display();

    randomArr = randomArray();

    SelectionSort selectionSort = new SelectionSort(randomArr);
    selectionSort.sort();
    selectionSort.display();

    randomArr = randomArray();

    InsertionSort insertionSort = new InsertionSort(randomArr);
    insertionSort.sort();
    insertionSort.display();

    System.out.println("Bubble Sort: Swaps = " + bubbleSort.totalSwaps + " Comparisons = " + bubbleSort.totalComparisons);
    System.out.println("Selection Sort: Swaps = " + selectionSort.totalSwaps + " Comparisons = " + selectionSort.totalComparisons);
    System.out.println("Insertion Sort: Swaps = " + insertionSort.totalSwaps + " Comparisons = " + insertionSort.totalComparisons);


    randomArr = randomArray();

    QuickSort quickSort = new QuickSort(randomArr);
    quickSort.sort();
    quickSort.display();

    System.out.println("Quick Sort: Swaps = " + quickSort.totalSwaps);
}

}

產量

10 48 29 47 15 3 41 11 19 4 27 27 23 12 45 44 34 25 41 20  // original
3 4 10 11 12 15 19 20 23 25 27 27 29 34 41 41 44 45 47 48  // bubble
3 4 10 11 12 15 19 20 23 25 27 27 29 34 41 41 44 45 47 48  // selection
3 4 10 11 12 15 19 20 23 25 27 27 29 34 41 41 44 45 47 48  // insertion
Bubble Sort: Swaps = 87 Comparisons = 87
Selection Sort: Swaps = 19 Comparisons = 29
Insertion Sort: Swaps = 87 Comparisons = 87
3 4 10 11 12 15 19 20 23 25 27 27 29 34 41 41 44 45 47 48  // quick
Quick Sort: Swaps = 25283

至於如何計算操作,您總是可以考慮添加一個間接層。 例如,使用此類之類來執行和計數操作:

class Instrumentation {
    int compares = 0;
    int swaps = 0;

    boolean compareLess(int left, int right) {
        compares++;
        return left < right;
    }

    boolean compareGreater(int left, int right) {
        compares++;
        return left > right;
    }

    void swap(int[] array, int index1, int index2) {
        int temp = array[index1];

        array[index1] = array[index2];
        array[index2] = temp;

        swaps++;
    }

    void printResult(String label) {
        System.out.print(label);
        System.out.print(": Swaps = ");
        System.out.print(swaps);
        System.out.print(" Comparisons = ");
        System.out.println(compares);
    }
}

修改了足以使用該檢測類計數操作的代碼之后,我得到了以下結果:

Original data:
10 48 29 47 15 3 41 11 19 4 27 27 23 12 45 44 34 25 41 20 

BubbleSort: Swaps = 87 Comparisons = 189
3 4 10 11 12 15 19 20 23 25 27 27 29 34 41 41 44 45 47 48 

SelectionSort: Swaps = 19 Comparisons = 190
3 4 10 11 12 15 19 20 23 25 27 27 29 34 41 41 44 45 47 48 

InsertionSort: Swaps = 87 Comparisons = 190
3 4 10 11 12 15 19 20 23 25 27 27 29 34 41 41 44 45 47 48 

QuickSort: Swaps = 3221 Comparisons = 110575
3 4 10 11 12 15 19 20 23 25 27 27 29 34 41 41 44 45 47 48 

現在觀察到,比較排序的主要特征是在最壞的情況下,它們涉及將每個元素與每個其他元素進行比較。 對於20個元素,這就是20 * 19/2 = 190個比較,這基本上是您的比較排序實現在每種情況下都會產生的結果(對於冒泡排序,則少於一個)。

實際上,在每種情況下,這都是您對Bubble和Selection排序的期望,但在一般情況下,這並不是您期望的插入排序。 那是因為您的插入排序實現存在缺陷:這種排序的前提是它依賴於中間結果(按順序放入數組的第一部分)來減少所需的比較次數。 第一次在內部循環中進行的比較失敗,因此不需要進行交換,您應該從(內部)循環中中斷,因為您知道直到外部循環的下一次迭代才需要進行進一步的交換。 實施后,您的特定數據的比較次數減少到105。

比較排序之間的交換次數也很有意義:冒泡排序和插入排序都通過與相鄰元素的一系列交換將每個元素從其初始位置移動到最終位置。 確實,您的實現實際上是彼此的鏡像。 但是,我不准備超越這只揮手的手。

至於選擇排序,是的,對於排序n個元素,它將始終執行( n *( n -1))/ 2個比較,並且最多進行n -1個交換(如果執行並計算自交換,則為n -1個交換) 。

然后是您的快速排序。 顯然,這不是很快-確實存在嚴重錯誤。 稍微多一點的檢測告訴我,遞歸深度下降太大(平均約為400,而即使在最壞的情況下也不應超過n )。 問題在於您隨機選擇樞軸。 無需從要排序的子數組中選擇樞軸,而是從整個數組中選擇它。 要解決此問題,請更換

int randomIndex = new Random().nextInt(array.length);

int randomIndex = left + new Random().nextInt(right + 1 - left);

這應該使您對比較和交換都有更有利的計數,但是直到您開始對更大的數組進行排序之前,您才真正注意到快速排序相對於其他排序沒有多少優勢。

您可以做更多的事情來改善QuickSort的實現,但是我看不到任何其他真正的錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM