簡體   English   中英

我在做什么插入排序,我認為邏輯是正確的但非常規?

[英]Is what I'm doing an Insertion sort, I think the logic is correct but unconventional?

這段代碼應該是一個插入排序,但它是這樣實現的嗎? 我迷路了。 第一個循環遍歷數組並檢查下一個元素是否小於當前元素。 嵌套循環將下一個元素 (j) 正確插入到數組已排序部分的位置。

#include <iostream>

using namespace std;

// Print array
void printArray(int array[], int arraySize)
{
    for (int i = 0; i < arraySize; i++)
    {
        cout << array[i] << " ";
    }
    cout << endl;
}

int main()
{
    int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};
    int array1Size = sizeof(array1)/sizeof(int);

    printArray(array1, array1Size);

    for (int i = 0; i < array1Size - 1; i++)
    {
        int oldNum = array1[i];
        if (array1[i] > array1[i + 1])
        {
            array1[i] = array1[i + 1];
            array1[i + 1] = oldNum;
        }

        int newI = array1[i];
        // Check if arranged correctly
        if ( i > 0)
        {
            // Swap bigger number and newI
            for (int j = i - 1; newI < array1[j]; j--)
            {
                if (j < 0)
                {
                    break;
                }
            
                array1[j + 1] = array1[j];
                array1[j] = newI;
            }
        }
        printArray(array1, array1Size);

    }

    return 0;
}

插入排序的關鍵是維護一個“排序區域”並循環擴展它。 開始區域只有一個元素,最后是所有列表。 我們在排序區域之外取一個元素,並決定它應該放置在排序區域中的哪個 position 中。

順便說一句,循環不變式很容易理解,但功能強大且令人敬畏。 推薦的。

int main() {
  int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};
  int array1Size = sizeof(array1)/sizeof(int);
  
  // loop invariant: array1[0..i-1] is sorted
  // array1[i] is the element to be inserted
  for (size_t i = 1; i < array1Size; i++) {
    int temp = array1[i];
    // find the right place to insert array1[i]. Can be replaced by binary search(but moving elements is more expensive than comparing)
    size_t j = i; // j is used to save the right place
    for (; j > 0 && array1[j-1] > temp; j--) {
      array1[j] = array1[j-1];
    }
    array1[j] = temp;
  }
  return 0;
}

這個for循環

    for (int j = i - 1; newI < array1[j]; j--)
    {
        if (j < 0)
        {
            break;
        }
    
        array1[j + 1] = array1[j];
        array1[j] = newI;
    }

由於 for 循環條件中的此表達式,當j等於-1時可以調用未定義的行為

newI < array1[j]

而且代碼太復雜了。 例如這個代碼片段

    if (array1[i] > array1[i + 1])
    {
        array1[i] = array1[i + 1];
        array1[i + 1] = oldNum;
    }

交換兩個元素的地方是多余的。 而這個 if 語句

    if ( i > 0)
    { 

也是多余的。 從 1 而不是從 0 開始外循環就足夠了。

最好定義一個單獨的 function。 例如,它可以通過以下方式查看

void InsertionSort( int a[], size_t n )
{
    for (size_t i = 1; i < n; i++)
    {
        if (a[i] < a[i - 1])
        {
            int tmp = a[i];

            size_t j = i;
            for ( ; j != 0 && tmp < a[j - 1]; --j )
            {
                a[j] = a[j - 1];
            }

            a[j] = tmp;
        }
    }
}

請注意,運算符sizeof會產生size_t類型的值。 您應該將此類型size_t用於將存儲數組中元素數量的變量。 通常int類型不足以存儲 arrays 的大小。

如果您的編譯器支持 C++ 17 則不要使用帶有sizeof運算符的表達式

int array1Size = sizeof(array1)/sizeof(int);

你至少可以寫

#include <iterator>

//...

int array1Size = std::size( array1 );

此外,由於 function printArray 不會更改傳遞的數組,因此應使用限定符const聲明它的第一個參數。

void printArray(const int array[], int arraySize);

這是一個演示程序,顯示了使用插入排序方法對 arrays 進行排序的單獨 function 的用法。

#include <iostream>
#include <iterator>

void InsertionSort( int a[], size_t n )
{
    for (size_t i = 1; i < n; i++)
    {
        if (a[i] < a[i - 1])
        {
            int tmp = a[i];

            size_t j = i;
            for ( ; j != 0 && tmp < a[j - 1]; --j )
            {
                a[j] = a[j - 1];
            }

            a[j] = tmp;
        }
    }
}

int main() 
{

    int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};

    for ( const auto &item : array1 )
    {
        std::cout << item << ' ';
    }
    std::cout << '\n';

    InsertionSort( array1, std::size( array1 ) ); 

    for ( const auto &item : array1 )
    {
        std::cout << item << ' ';
    }
    std::cout << '\n';
}

程序 output 是

5 3 1 9 8 2 4 7 
1 2 3 4 5 7 8 9 

暫無
暫無

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

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