经典排序算法(PHP语言实现)

目录

1.1冒泡排序(BubbleSort)

1.2鸡尾酒排序(CocktailSort)

2.选择排序(SelectionSort)

3.1插入排序——直接插入排序(StraightInsertionSort)

3.2插入排序——二分查找排序(BinarySearchSort)

3.3插入排序——希尔排序(ShellSort)

4.归并排序(MergeSort)

5.堆排序(HeapSort)

6.快速排序(QuickSort)

7.计数排序(CountingSort)

8.基数排序(RadixSort)

9.桶排序(BucketSort)


参考:http://www.cnblogs.com/eniac12/p/5329396.html

1.1冒泡排序(BubbleSort)

原理

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
 $arr[$j + 1]) {	        // 比较相邻两个元素,较大的后移
				$t = $arr[$j];
				$arr[$j] = $arr[$j + 1];
				$arr[$j + 1] = $t; 
			}
		}
	}
	return $arr;
}

print_r(BubbleSort($arr));

1.2鸡尾酒排序(CocktailSort)

鸡尾酒排序也就是定向冒泡排序, 鸡尾酒搅拌排序, 搅拌排序 (也可以视作选择排序的一种变形), 涟漪排序, 来回排序 or 快乐小时排序, 是冒泡排序的一种变形。此演算法与冒泡排序的不同处在于排序时是以双向在序列中进行排序。

原理:数组中的数字本是无规律的排放,先找到最小的数字,把他放到第一位,然后找到最大的数字放到最后一位。然后再找到第二小的数字放到第二位,再找到第二大的数字放到倒数第二位。以此类推,直到完成排序。

 $arr[$i + 1]) {
				$t = $arr[$i];
				$arr[$i] = $arr[$i + 1];
				$arr[$i + 1] = $t;
			}
		}
		$right--;                                        // 右边界缩小
		for ($i = $right; $i > $left; $i--) {            // 从右向左,将最小元素放在前面
			if ($arr[$i-1] > $arr[$i]) {
				$t = $arr[$i -1];
				$arr[$i - 1] = $arr[$i];
				$arr[$i] = $t;
			}
		}
		$left++;                                        // 左边界增大
	}
	return $arr;
}

print_r(CocktailSort($arr));

2.选择排序(SelectionSort)

原理:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完.。

3.1插入排序——直接插入排序(StraightInsertionSort)

原理

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复步骤2~5
= 0 && $arr[$j] > $get) {  // 当指针指向的元素比要比较的元素大
			$arr[$j + 1] = $arr[$j];	// 则将指针指向的元素向后移动一位
			$j--;				// 指针前移
		}
		$arr[$j + 1] = $get;			// 直到指针指向的元素与要比较元素小或者相等,则要比较元素插入到指针指向元素后
	}
	return $arr;
}

print_r(StraightInsertionSort($arr));

3.2插入排序——二分查找排序(BinarySearchSort)

原理:首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

 $get) {		// 如果中间数大于比较元素,则比较元素属于前半段
				$right = $mid -1;		// 右边界左移
			} else {				// 否则比较元素属于后半段
				$left = $mid + 1;		// 左边界右移
			}
		}
		for ($j = $i -1; $j >= $left; $j--) {	       // 最后的$left就是待插入位置
			$arr[$j + 1] = $arr[$j];		// 将待插入位置的右边整体向右移动一个单位
		}		
		$arr[$left] = $get;				// 将比较元素插入该空位
	}
	return $arr;
}

print_r(BinarySearchSort($arr));

3.3插入排序——希尔排序(ShellSort)

希尔排序,也叫递减增量排序,是插入排序的一种更高效的改进版本。希尔排序是不稳定的排序算法。

原理:希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。

增量序列:由Knuth提出,递归表达式为:h = 3 * h + 1;减小增量:h = (h - 1) / 3;此公式产生的逆置序列为:..., 314, 121, 40, 13, 4, 1。

= 1) {
		for ($i = $h; $i < $length; $i++) {			
			$j = $i - $h;
			$get = $arr[$i];			// 暂存要比较的元素
			while ($j >= 0 && $arr[$j] > $get) {	// 组内判断,若组内元素大于该元素
				$arr[$j + $h] = $arr[$j];	// 则两者位置互换
				$j = $j - $h;			// 指针继续向前移动增量的距离,继续比较
			}
			$arr[$j + $h] = $get;
		}
		$h = ($h - 1) / 3;				// 递减增量
	}
	return $arr;
}

print_r(ShellSort($arr));

4.归并排序(MergeSort)

原理:归并排序的实现分为递归实现非递归(迭代)实现。递归实现的归并排序是算法设计中分治策略的典型应用,我们将一个大问题分割成小问题分别解决,然后用所有小问题的答案来解决整个大问题。非递归(迭代)实现的归并排序首先进行是两两归并,然后四四归并,然后是八八归并,一直下去直到归并了整个数组。

归并排序算法主要依赖归并(Merge)操作。归并操作指的是将两个已经排序的序列合并成一个序列的操作,归并操作步骤如下:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  4. 重复步骤3直到某一指针到达序列尾
  5. 将另一序列剩下的所有元素直接复制到合并序列尾

5.堆排序(HeapSort)

原理:

  1. 由输入的无序数组构造一个最大堆,作为初始的无序区
  2. 把堆顶元素(最大值)和堆尾元素互换
  3. 把堆(无序区)的尺寸缩小1,并调用heapify(A, 0)从新的堆顶元素开始进行堆调整
  4. 重复步骤2,直到堆的尺寸为1
 $arr[$max]) {
		$max = $left_child;
	}
	if ($right_child < $heap_size && $arr[$right_child] > $arr[$max]) {
		$max = $right_child;
	}
	if ($max != $i) {
		Swap($arr, $i, $max);	// 当前结点与最大值进行交换
		Heapify($arr, $max, $heap_size);	// 递归,继续调整
	}

}
// 建堆,时间复杂度O(n)
function BuildHeap(&$arr, $len)
{
	$heap_size = $len;
	for ($i = floor($heap_size / 2) - 1; $i >= 0; $i--) {	// 从每一个非叶子结点开始向下进行堆调整
		Heapify($arr, $i, $heap_size);
	}
	return $heap_size;
}
// 堆排序
function HeapSort($arr, $len)
{
	$heap_size = BuildHeap($arr, $len);		// 建立最大堆(无序区)

	while ($heap_size > 1) {				// 堆(无序区)元素大于1,未完成排序
		Swap($arr, 0, --$heap_size);		// 将堆定元素沉到堆底(成为有序区),堆(无序区)-1
		Heapify($arr, 0, $heap_size);		// 从新的栈顶元素开始向下调整
	}
	return $arr;
}

print_r(HeapSort($arr, $len));

6.快速排序(QuickSort)

快速排序使用分治策略(Divide and Conquer)来把一个序列分为两个子序列。

原理:

  1. 从序列中挑出一个元素,作为"基准"(pivot)
  2. 把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面(相同的数可以到任一边),这个称为分区(partition)操作
  3. 对每个分区递归地进行步骤1~2,递归的结束条件是序列的大小是0或1,这时整体已经被排好序了
= $right)
		return;
	$pivot_index = Partition($arr, $left, $right);	// 基准的索引
	QuickSort($arr, $left, $pivot_index - 1);
	QuickSort($arr, $pivot_index + 1, $right);

	return $arr;
}
print_r(QuickSort($arr, 0, $len - 1));

7.计数排序(CountingSort)

计数排序适合排序一定范围内的数,例如0-99之间的排序

原理:

  1. 统计数组A中每个值A[i]出现的次数,存入C[A[i]]
  2. 从前向后,使数组C中的每个值等于其与前一项相加,这样数组C[A[i]]就变成了代表数组A中小于等于A[i]的元素个数
  3. 反向填充目标数组B:将数组元素A[i]放在数组B的第C[A[i]]个位置(下标为C[A[i]] - 1),每放一个元素就将C[A[i]]递减
= 0; $i--) {		// 从后向前扫描保证排序稳定性
		// 把每个元素A[$i]放到它在输出数组B中的正确位置上
		// 当遇到重复元素时,会被放到当前的前一个位置上保证稳定性
		$arrB[--$arrC[$arrA[$i]]] = $arrA[$i];	
	}
	for ($i = 0; $i < $len; $i++) {	// 把B中的数据拷贝回A
		$arrA[$i] = $arrB[$i];
	}
	return $arrA;
}

print_r(CountingSort($arrA, $len));

8.基数排序(RadixSort)

9.桶排序(BucketSort)

你可能感兴趣的:(算法)