ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
### 基本原理 在要排序的一组数中,选出最小的一个数与第一个位置的数交换。然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。 ### 动画演示 ![](https://box.kancloud.cn/44be35da53ae9ee564ce444542a43d10_811x248.gif) ### 算法步骤 1. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置 2. 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。 3. 重复第二步,直到所有元素均排序完毕。 ![](https://box.kancloud.cn/1ac0da15f5338d00aab56a4e87c2490b_1140x534.jpg =600x) ### 代码实现 ``` // 选择排序(一) function selectSort($arr) { $length = count( $arr ); if( $length <= 1 ) return $arr; for($i = 0; $i < $length-1; $i ++) { $min = $i; for( $j = $i+1; $j < $length; $j ++) { if( $arr[$min] > $arr[$j] ) { $min = $j; } } if( $min != $i ) { $temp = $arr[$min]; $arr[$min] = $arr[$i]; $arr[$i] = $temp; } } return $arr; } ``` ``` // 选择排序(二) function selectSort2($arr) { $length = count($arr); // 数组长度 for ($i = 0;$i < $length-1; $i++) { // 遍历数组 $iTemp = $arr[$i]; // 暂存当前值 $iPos = $i; // 暂存当前位置 for ($j = $i + 1;$j < $length; $j++){ // 遍历当前位置以后的数据 if ($arr[$j] < $iTemp) { // 如果有小于当前值的 $iTemp = $arr[$j]; // 暂存最小值 $iPos = $j; // 暂存位置 } } $arr[$iPos] = $arr[$i]; // 把当前值放到算好的位置 $arr[$i] = $iTemp; // 把当前值换成算好的值 } return $arr; } // 调用测试 $arr = [3,1,13,5,7,11,2,4,14,9,150,6,12,10,8]; print_r(selectSort2($arr)); ``` ### 平均时间复杂度:O(n2) 在选择排序中,共需要进行n-1次选择和交换,每次选择需要进行 n-i 次比较(1 <= i <= n-1),而每次交换最多需要3次移动,因此,总的比较次数 C = n (n - 1) / 2。 交换次数为O(n),最好情况是,已经有序,交换0次;最坏情况是,逆序,交换n-1次。交换次数比冒泡排序较少,由于交换所需CPU时间比冒泡排序所需的CPU时间多,n值较小时,选择排序比冒泡排序快。 原地操作几乎是选择排序的唯一优点,当空间复杂度要求较高时,可以考虑选择排序;实际适用的场合非常罕见。 ### 小结 选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个 元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。