常见排序方式

常见的排序方式


插入排序

待排序数据较少时用时少
从数组的第二个元素(即待插入的元素)开始,分别与之前的元素进行比较,若满足一定的条件就将此元素插入此位置。
例对[8,9,6,7,2]进行排序。
第一次排序:9为待插入的元素(i=1),与其之前元素8(j=0)进行比较,8>9,不满足条件,9要插入的位置为1(j=0+1),即9位置不发生变化;此时待排序元素顺序为[8,9,6,7,2]
第二次排序:6为带插入的元素(i=2).
- 首先与其之前元素9(j=1)进行比较,j>=0并且9>6,满足条件,把9放入6的位置上($ary[$j+1]=$ary[$j];($ary[2]=$ary[1])),此时待排序元素顺序为[8,9,9,7,2],j=0;
- 继续进行比较,6与数组的第一个元素(即序号为j=0)进行比较,依然满足条件,把8放入9的位置上($ary[$j+1]=$ary[$j];($ary[1]=$ary[0])),此时待排序元素顺序为[8,8,9,7,2],j=-1(发生了自减);
- 由于j>=0不再成立,因此while部分到此结束,把6放入位置0(此时j+1=0)处,此时待排序元素顺序为[6,8,9,7,2]
接下来依次进行剩下排序

function InsertSort(array $ary){
    $lenth=count($ary);//获取数组长度即待排序数据个数
    for ($i=1;$i<$lenth;$i++){
        $val=$ary[$i];
        $j=$i-1;
        while ($j>=0 && $ary[$j]>$val){//升序排序
            $ary[$j+1]=$ary[$j];
            $j=$j-1;            
        }
        $ary[$j+1]=$val;//把元素插入指定位置
    }
    return $ary;
}

冒泡排序

流行低效
原理:反复交换相邻的未按次序排列的元素
例对[8,9,6,7,2]进行排序。
第一次排序:
- i=0;j=4;
- 4>1(i+1),执行第二个for部分
- 位置4(j)上元素为2,位置3(j-1)上元素为7,2<7进行交换,此时元素顺序变化为[8,9,6,2,7],j值为3
- 3>1(i+1),继续执行第二个for部分
- 位置3(j)上元素仍为2,位置2(j-1)上元素为6,2<6进行交换,此时元素顺序变化为[8,9,2,6,7],j值为2
- 依次比较,直到最小元素(2)冒泡至位置i(0),成为第一个元素,此时元素顺序变化为[2,8,9,6,7],j值为0,i为0,0(j)<1(i+1),不再执行第二个for部分,i自加,值为1,重复之上步骤将第二小元素(6)冒泡至位置i(1)成为第二个元素
- 以此继续比较,直到i为3(即倒数第二个元素,剩下最后一个元素无须比较)

function BubbleSort(array $ary){
    for ($i=0;$i$ary);$i++){
        for($j=count($ary)-1;$j>=$i+1;$j--){
            if($ary[$j]<$ary[$j-1]){
               $mid= $ary[$j];
               $ary[$j]=$ary[$j-1];
               $ary[$j-1]=$mid;
            }
        }
    }
    return $ary;
}

快速排序法

使用了递归
原理:根据数据里的第一个元素val把所有元素分为两个数组,比val大的放入right数组,比val小的放入left数组;按照此方法把right、left数组继续分割,直到分割为一个个元素的数组;最后把这些数组合并即可

function QucikSort(array $ary){
    if(count($ary)>1){
        $val=$ary[0];
        $left=array();
        $right=array();
        $size=count($ary);
        for ($i=1;$i<$size;$i++){
        //根据首元素把所有元素分为两部分
            if($ary[$i]<=$val){
                $left[]=$ary[$i];
            }else if($ary[$i]>$val){
                $right[]=$ary[$i];
            }
        }
        $left=QucikSort($left);//对较小元素进行再次分割
        $right=QucikSort($right);//对较大元素进行再次分割
         //合并元素
        return array_merge($left,array($val),$right);
    }else{
        return $ary;
    }
}

选择排序法

原理:首先通过依次比较选择出最小的值,将最小值放入数组开始位置,重复这一步骤,直到完成所有排序。

function SelectSort(array $ary){
    $count=count($ary);
    for($i=0;$i<$count-1;$i++){    
        //找出最小值  
        $min=$i;       
        for($j=$i+1;$j<$count;$j++){          
            if($ary[$min]>$ary[$j]){
                $min=$j;
            }
        }    
        //把最小值放入位置i处   
        if($min!=$i){
            $temp=$ary[$min];
            $ary[$min]=$ary[$i];
            $ary[$i]=$temp;
        }
    }
    return$ary;
}

归并排序法

使用了递归
原理:把待排序数组从中间分开,一分为二,并按此方法(即递归),拆分为单个元素数组,按照顺序(12\34\56\78)两两组合为有序数组,再将生成的有序数组合并为大的有序数组,重复操作,直到合并成一个有序数组。
例:对[8,9,6,7,2]使用归并排序法
- 第一:拆分[8,9] [6,7,2]
- 第二:拆分左侧数组[8][9]
- 第三:合并为有序数组[8,9]
- 第四:拆分右侧数组[6,7,2]
- 第五:继续拆分右侧数组[6][7,2]
- 第六:[6]无需拆分,继续拆分右侧数组[7][2]
- 第七:合并为有序数组[2,7]
- 第八:合并为有序数组[2,6,7]
- 第九:两个大数组[8,9][2,6,7]合并为有序数组[2,6,7,8,9]

function Merge($ary,$bry){
    $cry=array();
    while (count($ary) && count($bry)){
        $cry[]=$ary[0]<$bry[0] ? array_shift($ary) : array_shift($bry);
    }
    return array_merge( $cry,$ary,$bry);
}
//主排序程序
function MergeSort(array $ary){
    $count=count($ary);
    if($count<=1){
        return $ary;
    }
    $mid=intval($count/2);
    $left=array_slice($ary, 0,$mid);
    $right=array_slice($ary, $mid);
    $left=MergeSort($left);
    $right=MergeSort($right);
    return Merge($left,$right);
}

思考

快速排序法,归并排序法等其他使用了递归的排序法,都是把问题分解为一些小问题,这些小问题与原问题问题一样,只是包含的元素更少,更容易解决,递归地求解出这些小问题,如果小问题的规模更小(一般情况下都是分解为单元素的数组),则停止递归,进行求解,最后把解决过的小问题合并,直至合并为一个数组。

你可能感兴趣的:(学习,笔记)