使用PHP实现几个基本的排序算法

近几日有空,发现自己对一些基本的排序算法已经忘记,遂使用PHP来实现,复习一下。代码和注释如下:

class class_sort{
	/**
	 * 直接选择排序
	 */
	public static function directSelectSort(&$data){
		echo "直接选择排序开始:"."<br />";
		$length=count($data);
		for($i=0;$i<$length;$i++){
			for($j=$i+1;$j<$length;$j++){
				if ($data[$i]>$data[$j]) {
					//$temp=$data[$i];
					//$data[$i]=$data[$j];
					//$data[$j]=$temp;
					self::swap($data, $i, $j);
				}
			}
			echo self::array2string($data).$i."<br />";
		}
		echo "直接选择排序结束"."<br />";
	}
	/**
	 * 改良的直接选择排序
	 */
	public  static  function directSelectSortEx(&$data){
		echo "改良直接选择排序开始:"."<br />";
		$length=count($data);
		for($i=0;$i<$length;$i++){
			$min=$i;
			for($j=$i+1;$j<$length;$j++){
				if ($data[$min]>$data[$j]) {
					$min=$j;
				}
			}
			if($min!=$i){
				self::swap($data, $i, $min);
			}
			echo self::array2string($data).$i."<br />";
		}
		echo "改良直接选择排序结束"."<br />";
	}
	
	/**
	 * 堆排序
	 */
	public static function heapSort(&$data){
		echo "堆排序开始:"."<br />";
		$len=count($data);
		//循环建堆
		for($i=0;$i<$len-1;$i++){
			self::buildHeap($data,$len-1-$i);
			self::swap($data,0,$len-1-$i);
			echo self::array2string($data).$i."<br />";
		}
		echo "堆排序结束"."<br />";
	}
	
	//建堆
	private static function buildHeap(&$data,$lastIndex){
		//从$lastIndex的父节点开始
		if($lastIndex%2!=0){
			$lastIndex++;
		}
		for ($j=$lastIndex/2;$j>=0;$j--){
			//如果当前节点存在子节点
			while ($j*2+1<=$lastIndex) {
				//较大值的索引
				$biggerIndex=$j*2+1;
				//如果右子节点存在
				if($biggerIndex<$lastIndex-1){
					//比较左右子节点的大小
					if($data[$biggerIndex]<$data[$biggerIndex+1]){
						//较大值的索引总是指向较大的值
						++$biggerIndex;
					}
				}
				
				//如果$k节点的值小于其较大的字节点,交换
				if ($data[$j]<$data[$biggerIndex]) {
					self::swap($data, $j, $biggerIndex);
				}else{
					break;
				}
			}
			
		}
	}
	
	/**
	 * 冒泡排序
	 * @param unknown $data
	 */
	public static function bubbleSort(&$data){
		echo "冒泡排序开始:"."<br />";
		$length=count($data);
		for($i=0;$i<$length-1;$i++){
			for ($j = $i+1; $j < $length; $j++) {
				if($data[$j]<$data[$i]){
					self::swap($data, $i, $j);
				}
			}
			echo self::array2string($data).$i."<br />";
		}
		echo "冒泡排序结束"."<br />";
	} 
	
	/**
	 * 快速排序[递归方法实现]
	 * @param unknown $data
	 */
	public static function quickSortRecursive(&$data){
		echo "快速排序开始[递归]:"."<br />";
		$length=count($data);
		self::subQuickSortRecursive($data, 0, $length);
		echo "快速排序结束[递归]"."<br />";
	}
	
	//用于递归的快速排序
	private static function subQuickSortRecursive(&$data,$start,$end){
		//需要排序
		if($start<$end){
			$low=$start;
			$high=$end-1;
			//以第一个元素作为分界值
			$key=$data[$low];
			while ($low<$high){
				//从后往前找出小于关键数据的索引
				while ($low<$high&&$data[$high]>=$key){
					$high--;
				}
				//移动找出的值到低部
				$data[$low]=$data[$high];
				//从前往后找出大于关键值的索引
				while ($low<$high&&$data[$low]<=$key){
					$low++;
				}
				//交换到高部
				$data[$high]=$data[$low];
			}
			//放入关键值
			$data[$low]=$key;
			echo self::array2string($data).$low."<br />";
			self::subQuickSortRecursive($data, $start, $low);
			self::subQuickSortRecursive($data, $low+1, $end);
		}
	}
	
	/**
	 * 快速排序[非递归实现][借用递归实现的原理,使用栈来实现]
	 * @param unknown $data
	 */
	public static function quickSort(&$data){
		echo "快速排序开始[非递归]:"."<br />";
		$stack=array();
		$length=count($data);
		$low=0;
		$high=$length-1;
		if ($low<$high) {
			$mid=self::subQuickSort($data, $low, $high);
			if ($low<$mid-1) {
				array_push($stack, $low);
				array_push($stack,$mid-1);
			}
			if ($mid+1<$high) {
				array_push($stack, $mid+1);
				array_push($stack,$high);
			}

			while (!empty($stack)) {
				$q=end($stack);
				array_pop($stack);
				$p=end($stack);
				array_pop($stack);
				$mid=self::subQuickSort($data, $p, $q);
				if ($p<$mid-1) {
					array_push($stack, $p);
					array_push($stack,$mid-1);
				}
				if ($mid+1<$q) {
					array_push($stack,$mid+1);
					array_push($stack,$q);
				}
			}
		}
		echo "快速排序结束[非递归]"."<br />";		
	}
	
	//非递归
	private static function subQuickSort(&$data,$start,$end){
		$i=$start;
		$j=$end;
		//以第一个元素作为分界值
		$key=$data[$i];
		while ($i<$j){
			//从后往前找出小于关键数据的索引
			while ($i<$j&&$data[$j]>=$key){
				$j--;
			}
			//移动找出的值到低部
			$data[$i]=$data[$j];
			//从前往后找出大于关键值的索引
			while ($i<$j&&$i<$j&&$data[$i]<=$key){
				$i++;
			}
			//交换到高部
			$data[$j]=$data[$i];
		}
		//放入关键值
		$data[$i]=$key;
		echo self::array2string($data).$i."<br />";
		return $i;
	}
	
	/**
	 * 插入排序
	 * @param unknown $data
	 */
	public static function insertSort(&$data){
		echo "插入排序开始:"."<br />";
		$length=count($data);
		for ($i = 1; $i < $length; $i++) {
			//保存索引$i处的值,防止整体后移时丢失
			$temp=$data[$i];
			if ($temp<$data[$i-1]) {
				/*for ($j=$i-1;$j>=0&&$data[$j]>$temp;$j--){
					$data[$j+1]=$data[$j];
				}*/
				$j=$i-1;
				while ($j>=0&&$data[$j]>$temp) {
					$data[$j+1]=$data[$j];;
					$j--;
				}
				$data[$j+1]=$temp;
			}
			echo self::array2string($data).$i."<br />";
		}
		echo "插入排序结束"."<br />";
	}
	
	
	/**
	 * 折半插入排序[插入排序改良]
	 * @param unknown $data
	 */
	public static function binaryInsertSort(&$data){
		echo "折半插入排序开始:"."<br />";
		$length=count($data);
		for ($i = 1; $i < $length; $i++) {
			//保存索引$i处的值,防止整体后移时丢失
			$temp=$data[$i];
			$low=0;
			$high=$i-1;
			while ($low<=$high) {
				if(($low+$high)%2==0){
					$mid=($low+$high)/2;
				}else{
					$mid=($low+$high+1)/2;
				}
				if($data[$mid]<$temp){
					$low=$mid+1;
				}else{
					$high=$mid-1;
				}
			}
			
			//整体向后移yiwei
			for ($j = $i; $j > $low; $j--) {
				$data[$j]=$data[$j-1];
			}
			$data[$low]=$temp;
			echo self::array2string($data).$i."<br />";
		}
		echo "折半插入排序结束"."<br />";		
	}
	
	
	/**
	 * 交换
	 */
	private static function swap(&$data,$i,$j){
		$tmp=$data[$i];
		$data[$i]=$data[$j];
		$data[$j]=$tmp;
	}
	
	/**
	 * 数组转字符串输出
	 */
	public static function array2string($array){
		$str="[";
		foreach ($array as $value) {
			$str.=$value.",";
		}
		$str=mb_substr($str, 0,(mb_strlen($str)-1))."]";
		return $str;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值