排序算法

1、直接插入排序


将一个记录插入到已排序好的有序的序列中,从而得到一个新的记录数增1的有序序列。(先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。)

设立标识值作为临时存储和判断数组边界的作用。



算法实现:

function InsertSort($num){
    $count = count($num);
    for($i =1 ; $i < $count ; $i++){
        if($num[$i] < $num[$i-1]){          // 若第i个元素值大于第i-1个元素值,则直接插入;若小于则移动到有序序列后插入
            $j = $i-1;                      // 有序序列中的最后一个元素的索引值
            $x = $num[$i];                  // 复制为标识值,即存储待排序元素
            $num[$i] = $num[$i-1];          // 先将有序序列中的最后一个值向后移覆盖待排序的元素
            while ($x < $num[$j]){          // 查找在有序序列中的插入位置
                $num[$j+1] = $num[$j];
                $j--;                       // 元素向后移动
            }
            $num[$j+1] = $x;                // 插入到正确位置
        }
        print_r($num);
    }
}


2、简单选择排序


在要排序的队列中,选出最小(或者最大)的一个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,直至第n-1个元素(倒数第二个数)和第n个元素(最后一个数为止)。

选择排序与冒泡排序的区别:冒泡排序通过依次交换相邻两个顺序不对的元素的位置,从而将当前最小(最大)元素放到合适的位置;而选择排序每遍历一次都记住了当前最小(最大)元素的位置,最后仅需一次交换操作即可将其放到合适的位置。

/*
 * 给出的剩下的元素中寻找出最小值
 * @param $i数组的索引值
 * @return $k 返回最小值的索引值
 */
function SelectMinKey($arr,$i){
    $k = $i;
    $n = count($arr);
    for ($j=$i+1;$j<$n;++$j){
        if($arr[$k] > $arr[$j]){
            $k = $j;
        }
    }
    return $k;
}
// 选择排序
function selectSort($arr){
    $n = count($arr);
    for( $i = 0; $i<$n; ++$i ){
        $key = SelectMinKey($arr,$i);    ​    ​// 选择最小的元素
        if($key != $i){
            $tmp = $arr[$i];    ​    ​// 最小元素与第i位置元素互换
            $arr[$i] = $arr[$key];
            $arr[$key] = $tmp;
        }
        print_r($arr);
    }
}



3、二元选择排序


每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数。改进后对n个数据进行排序,最多只需进行[n/2]趟循环即可。即每次循环确定最大最小值的索引,分别将当前循环中的最前和最后的索引的值进行替换。它是对简单选择排序的改进。

function selectSort($arr){
    $len = count($arr);
    for( $i=0; $i<$len/2; $i++ ){
        $max = $i;
        $min = $i;
        for($j=$i+1 ; $j<=$len-1-$i;$j++){
            $max = $arr[$j] > $arr[$max] ? $j : $max;   // 每一趟取出当前最大和最小的数组下标
            $min = $arr[$j] < $arr[$min] ? $j : $min;
        }
        $tmp = $arr[$i];
        $arr[$i] = $arr[$min];
        if($i == $max){     // 最大数在数组头部
            if(($len-$i-1) !== $min){       // 最大数在头部,最小数在尾部
                $arr[$min] = $arr[$len-$i-1];
            }
            $arr[$len-$i-1] = $tmp;
        }else if( ($len-$i-1) == $min ){    // 最大数不在头部,最小数在尾部
            $arr[$len-$i-1] = $arr[$max];
            $arr[$max] = $tmp;
        }else{     
            $arr[$min] = $tmp;
            $tmp = $arr[$len-$i-1];
            $arr[$len-$i-1] = $arr[$max];
            $arr[$max] = $tmp;
        }
    }
    print_r($arr);
}

4、冒泡算法


越小(或越大)的元素经由交换慢慢浮到队列顶端,它是比较相邻的元素,如果前一个比后一个大,则将它们两个调换位置,最后的元素将是最大的数。每次最大元素像气泡一样浮到数组的最后,依次比较相邻的两个元素,使较大的那个向后移。

function bubbleSort($arr){
    $n = count($arr);
    for($j=0;$j<$n-1;$j++){
        for($i=0;$i<$n-1-$j;$i++){
            if( $arr[$i] > $arr[$i+1] ){
                $temp = $arr[$i];
                $arr[$i] = $arr[$i+1];
                $arr[$i+1] = $temp;
            }
        }
    }
}

5、鸡尾酒排序


也叫定向冒泡排序,是对冒泡排序的一种改进。它是从低到高然后从高到低去比较队列中的元素。

function cocktailSort($arr){
    $n = count($arr);
    $left = 0;          // 初始化边界
    $right = $n - 1;
    while ($left < $right){
        for( $i=$left; $i<$right; $i++ ){       // 前半轮,将最大元素放到后面
            if($arr[$i] > $arr[$i+1]){
                $temp = $arr[$i];
                $arr[$i] = $arr[$i+1];
                $arr[$i+1] = $temp;
            }
        }
        $right--;
        for( $i=$right; $i>$left; $i-- ){       // 后半轮,将最小元素放前面
            if( $arr[$i-1] > $arr[$i] ){
                $temp = $arr[$i-1];
                $arr[$i-1] = $arr[$i];
                $arr[$i] = $temp;
            }
        }
        $left++;
    }
}

6、希尔排序


核心:先将序列分成较多个子序列分别进行排序,再分成较少个子序列分别进行排序,直到最后为一个序列排序。希尔排序采用每隔固定距离选取一个数的方法划分子序,其中间距距离称为增量。增量就是隔多少距离的数都为同一个子序,如果增量为N,则可以分成N个子序。每次子序都排好后,增量减半,增量减少意味着子序数减少,直到增量为1,便是全部的数序了,希尔排序完成。

划分子序后对子序分别排序,希尔排序的子序排序方法为插入排序。通过增量是否为1控制整个排序的结束,在增量为d时,遍历此时的d个子序,从k=0到k=d-1,随后对每个子序进行插入排序操作。希尔排序是插入排序的加强版,通过对原始数据进行分组再排序。

插入排序的明显的缺点是插入元素时需要与已排序的元素进行对比,对比的次数可能比较多。希尔排序就是通过将元素数组划分为若干小组,然后对各个小组进行插入排序来减少元素之间对比的次数,大大地降低了排序的时间复杂度。

function shellSort($arr){
   $n = count($arr);
   $d = floor( $n / 2 );                            // 设置起始增量
   while ( $d >= 1 ){                               // 排序为1时排序结束
       for($k=0;$k<$d;$k++){                        // 遍历所有的子序
           for($i=$k+$d;$i<$n;$i+=$d){              // 对每个子序进行插入排序
               $temp = $arr[$i];
               $j = $i-$d;
               while ($j>=$k && $arr[$j]>$temp){
                   $arr[$j+$d] = $arr[$j];
                   $j = $j-$d;
               }
               $arr[$j+$d] = $temp;
           }
       }
       $d = floor($d/2);                            // 缩小增量
   }
}

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;

不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;

内排序:所有的排序操作都在内存中完成;

外排序:由于数据太大,因此将数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值