用C++实现懒惰排序算法

Implementing Lazy Sorting algorithm using C++

本文关键字:排序 算法 C++ 实现      更新时间:2023-10-16

我们的教授给我们做了一个编程练习:

胡安·塔马德是个懒惰的人。他的任务是对数字列表进行排序,但是他超级懒惰。他厌倦了想办法把所有的直到所有的数字都按递增顺序排列。所以,他来了用他自己的算法来保证新列表排序。以下是它的工作原理:

对于大小为n的列表,我们需要n-1次迭代。在每次迭代中,

检查第n个数字是否小于第n+1个数字。如果是,那么这两个数字已经排序了,我们可以跳过这个迭代如果不是,我们连续递减第一个n直到这两个数字按顺序排列。

例如,假设输入是

10 5 7 6 1

在第一次迭代中,我们比较了10和5。10比5大,所以我们递减直到其较小:

4 5 7 6 1

现在我们比较5和7。5比7小,所以我们不需要这样做任何东西,我们跳过这个迭代。我们转到下一个并比较7和6。7大于6,所以我们递减前三个数字直到它小于6,我们得到这个:

2 3 5 6 1

现在我们比较6和1。同样,6大于1,因此我们递减前四个数字,直到它小于1,我们得到这个:

-4 -3 -1 0 1

我们完了。现在,列表已按完美的排序顺序排列。

您的任务是在中实现Juan Tamad的排序算法一个C++程序。您的程序读取输入n和n的列表数字。你的程序使用Juan Tamad的算法。

所以我想知道是否有人能帮忙,也许至少在阐明问题方面。到目前为止,我的大脑已经产生了:

#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
int a[n];
for(int i = 0; i< n; i++)
cin>> a[i];
for(int i = 0; i< n; i++)
cout<< a[i] << " ";
//______________________________________
for(int i = 0; i < n-1; i++){
for(int j = i + 1; j < n-1; j++){
if(a[i] > a[j])
a[i]--;
}
}
for(int i = 0; i < n; i++)
cout << a[i] << " ";
return 0;
}

样品运行:

$./a.out
Enter value of n: 5 
Enter 5 numbers: 10 5 7 6 1
Output: -4 -3 -1 0 1
$./a.out
Enter value of n: 10 
Enter 10 numbers: 10 9 8 7 6 5 4 3 2 1
Output: -8 - 7 - 6 -5 -4 -3 -2 -1 0 1
$./a.out
Enter value of n: 6 
Enter 6 numbers: 1 2 3 1 2 3
Output: -2 -1 0 1 2 3
$./a.out
Enter value of n: 10
Enter 6 numbers: 5 7 11 6 16 2 9 16 6 16
Output: -27 -25 -21 -20 -10 -9 -2 5 6 16
$./a.out
Enter value of n: 1
Enter 6 numbers: 100
Output: 100

以下是一些要点:

for(int i = 0; i < n-1; i++)

而不是去[first, last),我会去(first, last],这是因为你需要查看以前的值。但你的方式也有效。

for(int j = i + 1; j < n-1; j++)

在这里您无条件地通过i的权限。这是错误的。您需要:

  • 首先检查v[i + 1] >= v[i]。如果没有,则元素已就位。你可以继续
  • 否则。您需要递减所有元素[first, i)。为此,for应该如下所示:

    对于(int j=0;j<i;++j)

  • 并且不需要实际递减CCD_ 7。你可以看到元素之间的差异,然后减去。例如,当遇到元素6 1时,需要从所有元素中减去6(6 - 1 + 1),直到i

剩下的由你决定。

这是上述懒惰算法的超懒惰实现:它只有O(n)复杂度:

template <class It>
auto lazy_sort(It begin, It end) -> void
{
auto rbegin = std::make_reverse_iterator(end);
auto rend = std::make_reverse_iterator(begin);
auto it = rbegin;
if (it == rend)
return;
auto prev_val = *it;
++it;
int diff = 0;
for (; it != rend; ++it)
{
diff += std::max(0, *it - prev_val + 1);
prev_val = *it;
*it -= diff;
}
}
BOOST_AUTO_TEST_CASE(test_lazy_sort)
{
std::vector<int> v = {10, 5, 7, 6, 1};    
lazy_sort(v.begin(), v.end());
BOOST_CHECK((v == std::vector<int>{-4, -3, -1, 0, 1}));
}