【问题标题】:How do I implement this bubble sort differently?我如何以不同的方式实现这种冒泡排序?
【发布时间】:2012-01-24 00:31:39
【问题描述】:

我希望实现冒泡排序。我编写了以下代码,它在do 循环内使用了for 循环。如何将其变成使用两个 for 循环的冒泡排序?

这是我的代码:

do {
    switched = false;
    for (int i = 1; i < size; i++) {
        if (a[i] < a[i-1]) {
            int temp = a[i];
            a[i] = a[i-1];
            a[i-1] = temp;
            switched = true;
        }
    }
} while (switched);

(这是标记为作业,但这是为期末考试而学习,而不是实际作业。)

【问题讨论】:

  • “我正在寻找实现冒泡排序”——这就是你的问题! (说真的,他们为什么继续坚持教授 Bubblesort 的使用......)
  • @MitchWheat,实施冒泡排序只是教授排序的开始......它可以帮助您了解其他排序技术。
  • 你不应该从零开始吗?
  • @glowcoder:我不认为 JVM 对 C++ 代码有太多抱怨。
  • @DeadMG 是的,是的,正如我所说,乍一看似乎是一个 Java 问题。 :-) 我今天早上起得很早,与国际客户一起工作 :-( 我要怪罪它!哇。为什么讨厌?:(

标签: c++ bubble-sort


【解决方案1】:

冒泡排序的一个简单改进是记住发生交换的最后位置。每次通过后,超过该点的元素都会被排序。下一次循环只迭代到前一个高水位线。

void bubble_sort(int *arr, int size)
{
    for (int hwm; size > 1; size = hwm)
    {
        hwm = 0;
        for (int i = 1; i < size; ++i)
        {
            if (arr[i] < arr[i-1])
            {
                std::swap(arr[i], arr[i-1]);
                hwm = i;
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    因为您知道列表中的最后一个元素将始终被排序(因为它冒泡到顶部),所以您可以停在那里。

    for(int x = size; x >= 0; x--) {
        bool switched = false;
        for(int i = 1; i < x; i++) {
            if(blah) {
                // swap code here
                switched = true;
            }
    
        }
        if(!switched) break; // not the biggest fan of this but it gets the job done
    }
    

    【讨论】:

    • 如果你不喜欢break,你可以在条件句中使用i&lt;x &amp;&amp; !switched
    • @Jon 之前完成了 CS101 作业,是的,我同意。这将是教授最有可能寻找的内容,尤其是关于“最近最高元素”如何始终排序的小 sn-p。
    • @Jon 这是真的。我更喜欢break。这样做会将变量放在循环之外,因此范围比它需要的范围大。函数往往会变得足够大,我们不应该给人们提供比他们需要的更多的变量。
    • 我也是break的粉丝。
    • 意识到break 是完全可选的,如果您不介意最好的情况 == 最坏的情况。 x &gt; 1 也不会在第一个循环中工作吗?
    【解决方案3】:

    由于您的内循环将运行的最大次数是size 次,您知道外循环只能被size 绑定。

    for (int x = 0; x < size; x++ )
    {
        switched = false;
        for (int i = 1; i < size; i++)
        {
            if (a[i] < a[i - 1])
            {
                int temp = a[i];
                a[i] = a[i - 1];
                a[i - 1] = temp;
                switched = true;
            }
        }
    
        if(switched)
        {
            break;
        }
    }
    

    【讨论】:

      【解决方案4】:

      使用两个 for 循环的一个非常愚蠢的方法如下:

      for(bool switched=true;switched;)
      {
          switched=false;
          for(int i=1; i<size; ++i)
          {
              if (a[i] < a[i-1]) 
              {
                  int temp = a[i];
                  a[i] = a[i-1];
                  a[i-1] = temp;
                  switched = true;
              }
          }
      }
      

      一个更严肃的答案可能如下......但现在我想这可能不是冒泡排序:

      for(int i=0; i<(size-1); ++i)
      {
          for(int j=(i+1); j<(size-1); ++j)
          {
              if(a[i]>a[j])
              {
                  temp=a[i];
                  a[i]=a[j];
                  a[j]=temp;
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        想想do 循环可以执行的最大次数。

        【讨论】:

          【解决方案6】:

          有点义务,但是,嘿,你要求的:

          for(bool switched=true; switched;)
          {
              switched = false;
              for (int i = 1; i < size; i++) {
                  if (a[i] < a[i-1]) {
                      int temp = a[i];
                      a[i] = a[i-1];
                      a[i-1] = temp;
                      switched = true;
                  }
              }
          }
          

          两个 for 循环...

          【讨论】:

          • 我不想投票,因为......哇,这太糟糕了!同时,我不想投反对票,因为它 1) 聪明 2) 正确。撕裂!
          • 你应该被举报虐待for声明!
          • @glowcoder:随意不投票。非常感谢评论!我在这个活泼的答案和一个尖刻的评论之间纠结:)
          【解决方案7】:

          第一次完整循环(即外部do 循环的第一次迭代)保证将最大元素放在a[size - 1] 位置。 (你明白为什么吗?)保证下一个完整的传递不会改变这一点,并且,此外,将第二大元素放在位置a[size - 2]。 (再次,你明白为什么吗?)等等。所以第一遍需要i1size - 1,但第二遍只需要i1size - 2,第三遍只需要i从@987654331 @ 到 size - 3,等等。总体而言,您最多需要 size - 1 传递(最后一次传递刚好覆盖位置 1 并将 a[1]a[0] 进行比较以确保最小的元素就位)。

          所以,你的外部for-loop 需要改变max_i,最初设置为size - 1 并最终设置为1,你的内部for-loop 需要改变i 和@987654343 @到max_i

          【讨论】:

            【解决方案8】:

            您可以运行内部循环size 次,而不是检查switched,方法是使用外部循环for(int j=0; j&lt;size; ++j)。为了稍微降低效率,您可以将内部循环每次缩短 1 步。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-12-14
              • 1970-01-01
              • 2017-03-11
              • 2012-07-23
              • 1970-01-01
              • 2014-12-04
              • 1970-01-01
              相关资源
              最近更新 更多