【问题标题】:Customised sorting of elements in an array [duplicate]数组中元素的自定义排序[重复]
【发布时间】:2014-01-02 09:49:50
【问题描述】:

我听说过快速排序、冒泡排序、归并排序等排序技术。我有一个像

的数组
arr[]={2, 3, 4, 1, 9, 5, 1, 2, 6, 8, 1, 3}

使用冒泡排序我可以完成排序

arr[]={1, 1, 1, 2, 2, 3, 3, 4, 5, 6, 8, 9}

但我需要以这种方式对给定的数组进行排序

arr[]={1, 2, 3, 4, 5, 6, 8, 9, 1, 1, 2, 3 )

也就是说,任何重复出现的值都需要移到数组的末尾。

我的想法是先对数组进行冒泡排序,然后使用这个排序后的数组,遍历数组,将任何重复出现的地方移动到数组的末尾。

这样可以吗?如果是,得到冒泡排序数组后的算法是什么。 或者有没有更好的方法来实现它。

【问题讨论】:

  • 重复值是否需要排序?
  • 是的,数组可以是任何东西。第一次出现和重复出现的值也需要排序,比如我的数组是 a[]={4,5,6,1,1,3,3,4,4,4,1,9,9,8 ,8}。结果数组需要是 a[]= {1,3,4,5,6,8,9,1,1,3,4,4,4,8,9}

标签: c++ c arrays algorithm sorting


【解决方案1】:

您可以分两次进行冒泡排序。

在第一遍中,找到最小的元素并将其放在首位。然后从批次中找出比最后一个找到的元素大于但最小的元素,并将其放在第二位。

执行上述操作,直到达到最大元素。

一旦达到最大元素,正常对数组的剩余部分进行冒泡排序。

复杂性顺序:完全按照冒泡排序,因为您只是将其分成两半。

C++ 中的完整工作代码:

#include <iostream>


using namespace std;

int main()
{
    int arr[] = {2, 3, 4, 1, 9, 5, 1, 2, 6, 8, 1, 3};
    int size = 12;
    // find max element.
    int max = -1;
    for ( int I = 0; I < size; I++ ) {
      if ( arr[I] > max )
        max = arr[I];
    }


    int begin = 0;
    bool maxPlaced = false;
    int lastFound = -1;
    while ( !maxPlaced ) {

      // find the first element from the end,
      // that is greater than elements already placed.
      int end = size-1;
      while ( arr[end] <= lastFound )
          end--;

      for ( int I = end; I > begin; I-- ) {

        // swap if arr[i-1] is higher than arr[i]
        // or arr[i-1] is a number that we have already placed.
        if ( arr[I] < arr[I-1] || lastFound >= arr[I-1] ) {
            int temp = arr[I];
            arr[I] = arr[I-1];
            arr[I-1] = temp;
        }
      }
      // lastfound is the highest number that we have placed till now.
      lastFound = arr[begin];
      begin++;
      if ( lastFound == max )
        maxPlaced = true;

    }

    //continue bubble sort from begin position.
    for ( int I = begin; I < size; I++ ) {
      for ( int j = begin; j < size - 1 - (I-begin); j++ ) {
        if (arr[j] > arr[j+1]) {
            int temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
      }
    }

    for ( int i = 0; i < size; i++ )
        cout << arr[i] << " ";

    return 0;
}

输出:

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

对于{4,5,6,1,1,3,3,4,4,4,1,9,9,8,8}的输入

输出:

1 3 4 5 6 8 9 1 1 3 4 4 4 8 9

【讨论】:

  • Abhi,感谢您的主动解决方案。
  • 谢谢!使用 cmets 更新代码。
  • Abhi,有时我看到运行时错误干扰了执行流程。 '进程退出,返回值 3277658738'
  • @Bala 代码需要稍作调整,因为它只是为了给你一个想法。例如。它目前不适用于负面元素。如果您找到并指定输入数组,则可以对其进行调试。目前数组的大小也是硬编码的。
【解决方案2】:

请记住,冒泡排序是您提到的这 3 种排序算法中效率最低的。
这是O(n<sup>2</sup>) 的平均情况,而其他情况是O(n log n)

堆排序

想到了heap-sort 的变体,这是一种有效的 (O(n log n)) 方法。

  • 构建一个项目堆。

  • 在数组中有一个左迭代器和一个右迭代器,分别指向最左边和最右边的位置。

  • 虽然堆不是空的:

    • 移除最大值。

    • 如果删除的项与最后删除的项相同,则将其插入右侧迭代器并减少迭代器。

    • 否则插入左边的迭代器,增加迭代器。

现在如果最后的项目也需要排序,只需颠倒它们的顺序(在上述过程结束时它们应该是相反的顺序)。

就地替代 - 选择排序

Selection sort 在每个步骤中找到最大元素,因此如果它们大于已找到的元素,则可以轻松修改以跳过适用的元素。

这可以就地完成(上面不能),但又是O(n<sup>2</sup>)

int arr[] = {2, 3, 4, 1, 9, 5, 1, 2, 6, 8, 1, 3};
int arrLength = 12;
for (int i = 0; i < arrLength; i++)
{
   int minPos = -1;
   for (int j = i; j < arrLength; j++)
      // either it's the first element, or it's greater than the last element
      //   and either it's the first such element we find, or smaller than the best one
      if ((i == 0 || arr[j] > arr[i-1]) && 
          (minPos == -1 || arr[j] < arr[minPos]))
      {
         minPos = j;
      }

   // no more elements to sort
   if (minPos == -1)
      break;

   int temp = arr[i];
   arr[i] = arr[minPos];
   arr[minPos] = temp;
}

Live demo.

如果重复的元素也需要排序,则需要额外完成(使用任何排序方法)。

【讨论】:

  • 好主意。虽然我认为你需要额外的堆空间,因为这样修改的堆排序是不可能的。
  • @AbhishekBansal 确实,我不确定就地是否是这里的要求。为我的答案添加了就地选择排序方法。
猜你喜欢
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
相关资源
最近更新 更多