美文网首页
冒泡排序

冒泡排序

作者: xuxin2020 | 来源:发表于2021-03-11 16:39 被阅读0次

    普通方法

    $arr=[8,9,1,2,4,6,3,5,7];
    for ($j=count($arr)-1;$j>0;$j--)
    {
        for ($i=0;$i<$j;$i++)
        {
            if ($arr[$i]>$arr[$i+1])
            {
                $temp=$arr[$i];
                $arr[$i]=$arr[$i+1];
                $arr[$i+1]=$temp;
            }
    
        }
    
    }
    
    

    优化一:设置标志位

    可以设置一个标志位,记录上一次排序是否有交换,没有交换就可以提前结束了。
    $arr=[8,9,1,2,4,6,3,5,7];
    $flag=true; //初始
    for ($j=count($arr)-1;$j>0;$j--)
    {
        if(!$flag)
        {
            break;
        }
        $flag=false; //初始
        for ($i=0;$i<$j;$i++)
        {
            if ($arr[$i]>$arr[$i+1])
            {
                $temp=$arr[$i];
                $arr[$i]=$arr[$i+1];
                $arr[$i+1]=$temp;
                $flag=true; //交换了
            }
    
        }
    
    }
    

    优化二:设置标志位

    记录上一次最后交换的位置,作为下一次循环的结束边界。最后一次比较说明在那之后的元素都已经排好序,无需再比较,可以避免一些无意义的比较。
    $arr=[8,9,1,2,4,6,3,5,7];
    $flag=true; //初始
    $lastPos=count($arr)-1;//最后一次交换的位置,初始时设为“数组长度 - 1”
    for ($j=count($arr)-1;$j>0;$j--)
    {
        if(!$flag)
        {
            break;
        }
        $flag=false; //初始
        $k=$lastPos;  // 上一次的最后交换位置作为这次循环的边界
        for ($i=0;$i<$k;$i++)
        {
            if ($arr[$i]>$arr[$i+1])
            {
                $temp=$arr[$i];
                $arr[$i]=$arr[$i+1];
                $arr[$i+1]=$temp;
                $flag=true; //交换了
                $lastPos=$i; // 更新最后交换位置
            }
    
        }
    
    }
    

    优化三:双向冒泡排序

    双向冒泡排序,又叫鸡尾酒排序(Cocktail Sort)。
    它的过程是:先从左往右比较一次,再从右往左比较一次,然后又从左往右比较一次,以此类推。
    它是为了优化前面的大部分元素都已经排好序的数组的排序,例如对于数组 [2,3,4,5,6,7,8,1],如果使用普通的冒泡排序,需要比较七次;而换成双向冒泡排序,只需比较三次。
    $arr=[8,9,1,2,4,6,3,5,7];
    $left = 0; //左边位置
    $right =count($arr) - 1; //右边位置
    $lastSwapIndex = 0;      // 记录最后一次交换的位置
    $hasSwap = false;    // 标志位
    while ($left < $right) {
        for ($i = $left; $i < $right; $i++) { // 保证 a[right] 是最大的
                  if ($arr[$i] > $arr[$i+1]) {
                        $temp=$arr[$i];
                        $arr[$i]=$arr[$i+1];
                        $arr[$i+1]=$temp;
                        $hasSwap = true;
                        $lastSwapIndex = $i;
                    }
                }
                $right = $lastSwapIndex;  // 将最后一次交换的位置作为右边界
                if (!$hasSwap) { // 上一轮没有交换,提前结束
                    break;
                }
                $hasSwap = false;
                for ($i = $right; $i > $left; $i--) { // 保证 a[left] 是最小的
                    if ($arr[$i] < $arr[$i-1]) {
                        $temp=$arr[$i];
                        $arr[$i]=$arr[$i-1];
                        $arr[$i-1]=$temp;
                        $hasSwap = true;
                        $lastSwapIndex = $i;
                    }
                }
                $left = $lastSwapIndex;  // 将最后一次交换的位置作为左边界
                if (!$hasSwap) { // 上一轮没有交换,提前结束
                    break;
                }
                $hasSwap = false;
    
            }
        print_r($arr);
    

    相关文章

      网友评论

          本文标题:冒泡排序

          本文链接:https://www.haomeiwen.com/subject/pdpzqltx.html