PHP数据结构(二十三) ——快速排序
PHP数据结构(二十三)——选择排序
(原创内容,转载请注明来源,谢谢)
一、概述
选择排序的基本思想,是每一趟在n-i+1(i=1,2…n-1)个记录中选取关键字最小的记录作为第i个记录。选择排序分为简单选择排序、树形选择排序、堆排序。
二、简单选择排序
简单选择排序,即完全按照上述的说法进行排序。时间复杂度O(n2)。由于比较简单,不具体描述。
1、算法
1)遍历整个数组,找到最小值放置于第一个位置。
2)遍历从第二个位置至末尾的数组,找到最小值放在第二个位置。
3)重复上述操作直到排序完成。
2、实现源码如下
//简单选择排序
public function simpleSelectSort(array$arr = array()){
$arr= $this->_checkNeedSort($arr);
if(!$arr){
return$arr;
}
//长度只有1直接返回
if(1== count($arr)){
return$arr;
}
//遍历数组,第i次取第i小值放置于第i-1的位置
//由于n-1次已经可以遍历完,故不需要第n次遍历
for($i=0;$i<count($arr)-1;$i++){
//暂存临时最小值与关键字
$min= $arr[$i];
$minIndex= $i;
for($j=$i+1;$j<count($arr);$j++){
//如果最小值比暂存小,则更新暂存
if($arr[$j]<$min){
$min= $arr[$j];
$minIndex= $j;
}
}
//将暂存的最小值替换到第i个位置
$tmp= $arr[$i];
$arr[$i]= $arr[$minIndex];
$arr[$minIndex]= $tmp;
}
return$arr;
}
三、树形选择排序
树形选择排序是利用简单选择排序在每一次排序的结果进行的排序,又被称为锦标赛排序。两两进行排序,小的值再两两排序,直至选出最小值。再进行第二轮的排序选择次小值。树形选择排序时间复杂度是O(nlogn)。
1、算法
1)构造一棵满二叉树,其叶子节点都在同一层,且叶子节点包含了所有的待排序数组。
2)两两节点进行比较,关键字对应的值小的那一个进入父节点,叶子节点的位置值置成无穷大。
3)直至比出根节点。则为最小值。
4)再次遍历此树,直至构造完成全部的值。
实际实现中,由于树形选择排序必须用完全二叉树,而完全二叉树的父节点和其子节点的编号关系是确定的,可以用数组来表达。
数组表达的方式,假设根节点为0,从左往右、从上往下编号,则第一层为0,第二层为1、2(父节点都是0),第三层为3、4、5、6(父节点3、4的是1,5、6的是2)。
依次类推,两两一组,可以确定,父节点编号=(左节点编号-1)/2,或父节点编号=右节点编号/2-1。因此可以两两一组进行遍历。
2、树形选择排序如下图所示(图片来自网络):
3、实现源码如下
//树形选择排序
publicfunction treeSelectSort(array $arr = array()){
$arr= $this->_checkNeedSort($arr);
if(!$arr){
return$arr;
}
//长度只有1直接返回
if(1== count($arr)){
return$arr;
}
//确定数组长度,即完全二叉树叶子节点的个数
$arrLength= count($arr);
//完全二叉树
$arrTreeNodes= array();
//完全二叉树节点总数为叶子节点个数*2-1
$treeNodesLength= 2 * $arrLength -1;
//倒序将数组放置于完全二叉树数组的末尾,构造叶子节点
for($i=$arrLength-1,$j=0;$i>=0;$i--,$j++){
$arrTreeNodes[$treeNodesLength-1-$j]= $arr[$i];
}
//补全完全二叉树叶子节点以外的节点。i每两个进行比较,从最后一个节点起,相当于每次都在右节点,因此其父节点位置为i/2-1
for($i=$treeNodesLength-1;$i>0;$i=$i-2){
//取小的值为父节点的值
$arrTreeNodes[$i/2-1]= $arrTreeNodes[$i] < $arrTreeNodes[$i-1] ? $arrTreeNodes[$i] :$arrTreeNodes[$i-1];
}
//从0起生成最终的数组
$low= 0;
while($low< $arrLength){
//每次生成树后,其当前的第一个值(下标是0)即为最小值
$curMin= $arrTreeNodes[0];
//最小值放入最终的数组
$arr[$low++]= $curMin;
//从最后一个元素起,找结果为最小值的下标
$curMinIndex= $treeNodesLength - 1;
//相等时找到下标
while($curMin!= $arrTreeNodes[$curMinIndex]){
$curMinIndex--;
}
//将结果最小的值设置成无穷大
$arrTreeNodes[$curMinIndex]= INF;
//找其父节点即父节点的父节点,直至根节点
while(0< $curMinIndex){
//如果是偶数,说明是右节点,父节点是i/2-1,要比较的是i和i-1
if(0== $curMinIndex%2){
$arrTreeNodes[$curMinIndex/2-1]= $arrTreeNodes[$curMinIndex] < $arrTreeNodes[$curMinIndex-1] ?$arrTreeNodes[$curMinIndex] : $arrTreeNodes[$curMinIndex-1];
$curMinIndex= $curMinIndex / 2 - 1;
}else{
//如果是奇数,说明是左节点,父节点是(i-1)/2,要比较的是i和i+1
$arrTreeNodes[($curMinIndex-1)/2]= $arrTreeNodes[$curMinIndex] < $arrTreeNodes[$curMinIndex+1] ?$arrTreeNodes[$curMinIndex] : $arrTreeNodes[$curMinIndex+1];
$curMinIndex= ($curMinIndex - 1) / 2;
}
}
}
return$arr;
}
4、评价
树形选择排序由于需要额外的空间较多,而且有大量的INF(PHP中表示无穷大的值),浪费空间较多,实际中不常用,而往往使用优化版的树形选择排序——堆排序。
堆排序的内容见下文。
——written by linhxx 2017.07.20
相关阅读:
PHP数据结构(二十二) ——快速排序
PHP数据结构(二十一) ——希尔排序
PHP数据结构(二十) ——其他插入排序
PHP数据结构(十九) ——B+树
PHP数据结构(十八) ——直接插入排序
PHP数据结构(十七) ——内部排序综述
PHP数据结构(十六) ——B树
PHP数据结构(十五) ——哈希表
PHP数据结构(十四) ——键树(双链树)
PHP数据结构(十三) ——动态查找表(二叉排序树)
PHP数据结构(十二) ——静态查找表
PHP数据结构(十一) ——图的连通性问题与最小生成树算法(2)
PHP数据结构(十一) ——图的连通性问题与最小生成树算法(1)
PHP数据结构(十) ——有向无环图与拓扑算法
PHP数据结构(九) ——图的定义、存储与两种方式遍历
PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践2)
PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践1)
PHP数据结构(八) ——赫夫曼树实现字符串编解码(理论)
PHP数据结构(七) ——串与实现KMP算法
PHP数据结构(六) ——树与二叉树之概念及存储结构
PHP数据结构(六) ——数组的相乘、广义表
PHP数据结构(五) ——数组的压缩与转置
PHP数据结构(四) ——队列
PHP数据结构(三)——运用栈实现括号匹配
PHP数据结构(二)——链式结构线性表
PHP数据结构(一)——顺序结构线性表
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Linux环境下快速搭建ftp服务器方法介绍
- Linux通过匿名管道进行进程间通信
- shell判断一个变量是否为空方法总结
- 基于ubuntu16 Python3 tensorflow(TensorFlow环境搭建)
- Linux中的iostat命令使用教程
- 深入解读Linux进程函数fork(),vfork(),execX()
- Linux centos下设置定时备份任务的方法步骤
- Linux 中如何切换相同程序的不同版本
- Linux中查看指定文件夹内各个子文件夹内的文件数量
- Linux系统中 /etc/fstab 文件的深入解读
- bash命令使用详解
- 实例详解Linux 中的命令链接操作符
- Python 为什么不支持 switch 语句?
- centos安装jdk1.8时出现没有/lib/ld-linux.so.2:这个文件的原因分析
- Linux多线程编程快速入门