繁体   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