简体   繁体   English

我在做什么插入排序,我认为逻辑是正确的但非常规?

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

This code is supposed to be an Insertion sort but is it implemented as such?这段代码应该是一个插入排序,但它是这样实现的吗? I'm lost.我迷路了。 The first loop goes through the array and checks if the next element is smaller than the current element.第一个循环遍历数组并检查下一个元素是否小于当前元素。 The nested loop inserts the next element(j) correctly in its place in the sorted portion of the array.嵌套循环将下一个元素 (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;
}

The key to insertion sort is to maintain a "sorted zone" and expand it in loop.插入排序的关键是维护一个“排序区域”并循环扩展它。 In the beginning the zone is only one element, and finally it's all the list.开始区域只有一个元素,最后是所有列表。 We take an element outside the sorted zone and decide which position in sorted zone that it should be placed in.我们在排序区域之外取一个元素,并决定它应该放置在排序区域中的哪个 position 中。

BTW, loop invariant is easy to understand but powerful and awesome.顺便说一句,循环不变式很容易理解,但功能强大且令人敬畏。 Recommended.推荐的。

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;
}

This for loop这个for循环

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

can invoke undefined behavior when j is equal to -1 due to this expression in the condition of the for loop由于 for 循环条件中的此表达式,当j等于-1时可以调用未定义的行为

newI < array1[j]

And the code is too complicated.而且代码太复杂了。 For example this code snippet例如这个代码片段

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

where two elements are swapped is redundant.交换两个元素的地方是多余的。 And this if statement而这个 if 语句

    if ( i > 0)
    { 

also is redundant.也是多余的。 It is enough to start the outer loop from 1 instead of from 0.从 1 而不是从 0 开始外循环就足够了。

It is better to define a separate function.最好定义一个单独的 function。 It can look for example the following way例如,它可以通过以下方式查看

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;
        }
    }
}

Pay attention to that the operator sizeof yields a value of the type size_t .请注意,运算符sizeof会产生size_t类型的值。 You should use this type size_t for the variable that will be store the number of elements in the array.您应该将此类型size_t用于将存储数组中元素数量的变量。 In general the type int is not large enough to store sizes of arrays.通常int类型不足以存储 arrays 的大小。

If your compiler supports C++ 17 then instead of using the expression with the sizeof operator如果您的编译器支持 C++ 17 则不要使用带有sizeof运算符的表达式

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

you could write at least你至少可以写

#include <iterator>

//...

int array1Size = std::size( array1 );

Also as the function printArray does not change the passed array then it first parameter should be declared with the qualifier const .此外,由于 function printArray 不会更改传递的数组,因此应使用限定符const声明它的第一个参数。

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

Here is a demonstration program that shows usage of a separate function that sorts arrays using the insertion sort method..这是一个演示程序,显示了使用插入排序方法对 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';
}

The program output is程序 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