php排序算法(冒泡排序,快速排序)(php冒泡排序和快速排序)
25-01-30
29
本文将为您提供关于php排序算法(冒泡排序,快速排序)的详细介绍,我们还将为您解释php冒泡排序和快速排序的相关知识,同时,我们还将为您提供关于4.1_8种常用排序算法1(交换排序:冒泡排序+快速排序
本文将为您提供关于php排序算法(冒泡排序,快速排序) 的详细介绍,我们还将为您解释php冒泡排序和快速排序 的相关知识,同时,我们还将为您提供关于4.1_8种常用排序算法1(交换排序:冒泡排序+快速排序)、c#冒泡排序算法和快速排序算法、C语言常见排序算法之交换排序(冒泡排序,快速排序)、Go经典算法之 冒泡排序 选择排序 快速排序 归并排序 的实用信息。
本文目录一览:
php排序算法(冒泡排序,快速排序)(php冒泡排序和快速排序) 冒泡排序实现原理
① 首先将所有待排序的数字放入工作列表中。 ② 从列表的第一个数字到倒数第二个数字,逐个检查:若某一位上的数字大于他的下一位,则将它与它的下一位交换。
③ 重复步骤②,直至再也不能交换。
代码实现
PHP function bubbingSort(array $array) { for($i=0,$len=count($array)-1; $i<$len; ++$i) { for($j=$len; $j>$i; --$j) { if($array[$j] < $array[$j-1]) { $temp = $array[$j]; $array[$j] = $array[$j-1]; $array[$j-1] = $temp; } } } return $array; }print ''; print_r(bubbingSort(array(1,4,22,5,7,6,9))); print ' ';
快速排序实现原理 采用分治的思想:先保证列表的前半部分都小于后半部分,然后分别对前半部分和后半部分排序,这样整个列表就有序了。
代码实现
function quickSort(array $array) { $len = count($array); if($len <= 1) { return $array; } $key = $array[0]; $left = array(); $right = array(); for($i=1; $i<$len; ++$i) { if($array[$i] < $key) { $left[] = $array[$i]; } else { $right[] = $array[$i]; } } $left = quickSort($left); $right = quickSort($right); return array_merge($left,array($key),$right); }print ''; print_r(quickSort(array(1,9))); print ' ';
4.1_8种常用排序算法1(交换排序:冒泡排序+快速排序) 【8中排序算法一览】
【算法1:冒泡排序】
【冒泡算法实例】
package com.sort.demo1;
import java.util.Arrays;
/* *
* 冒泡排序
*/
public class BubbleSort {
public static void main(String[] args) {
int [] arr = new int []{1 ,4 ,5 ,7 ,3 ,9 ,8 ,0 ,2 ,6 };
System. out .println(Arrays.toString(arr));
bubbleSort(arr);
System. out .println(Arrays.toString(arr));
}
/* *
* 冒泡排序算法
* 第一个for循环:控制共比较多少轮
* 第二个for循环:控制每次循环中比较的次数
* @param arr
*/
public static void bubbleSort(int [] arr){
for (int i=0 ;i<arr.length-1 ;i++){
for (int j=0 ;j<arr.length-1 -i;j++){
if (arr[j]>arr[j+1 ]){
int temp = arr[j];
arr[j] =arr[j+1 ];
arr[j +1 ]=temp;
}
}
}
}
}
【快速排序算法】
【实例】
package com.sort.demo1;
import java.util.Arrays;
/* *
* 快速排序
*/
public class QuickSort {
public static void main(String[] args) {
int [] arr = new int []{1 ,4 ,5 ,7 ,3 ,9 ,8 ,0 ,2 ,6 };
System. out .println(Arrays.toString(arr));
quickSort(arr, 0 ,arr.length-1 );
System. out .println(Arrays.toString(arr));
}
/* *
* 快速排序算法
* @param arr
* @param start
* @param end
*/
public static void quickSort(int [] arr,int start,int end){
if (start<end){
// 把数组中的第start个数字作为标准数
int stard = arr[start];
// 记录需要排序的下标
int low = start;
int high = end;
// 循环找到比标准数大的数 和 比标准数小的数
while (low<high){
// 如果右边的数字比标准数大,右边的下标-1
while (low<high && stard<=arr[high]){
high --;
}
// 使用右边的数字替换左边的数字
arr[low] = arr[high];
// 如果左边的数字比标准数小,左边的下标+1
while (low<high && stard>arr[low]){
low ++;
}
arr[high] = arr[low];
}
// 把标准数赋值给low低所在的位置的元素(这个时候low=high)
arr[low] = stard;
// 处理所有的小的数字
quickSort(arr,start,low);
// 处理所有的大的数字
quickSort(arr,low+1 ,end);
}
}
}
c#冒泡排序算法和快速排序算法
依次比较相邻的两个数,将小数放在前面,大数放在后面。
第1趟:
首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。至此第一趟结束,将最大的数放到了最后。
第2趟:
仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到倒数第二个数(倒数第一的位置上已经是最大的),第二趟结束,在倒数第二的位置上得到一个新的最大数(其实在整个数列中是第二大的数)。
如此下去,重复以上过程,直至最终完成排序。
由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。
[c-sharp]
view plain
copy
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace 冒泡排序算法
{
/// <summary>
/// 作者:it小金
/// 说明:冒泡排序算法
/// </summary>
class Program
{
static void Main(string[] args)
{
int[] array = {10,6,1,3,4,2,5,9,7,8};
BubbleSort bs = new BubbleSort();
bs.Maopao(array);
for (int i = 0; i < array.Length; i++)
{
Console.Write("{0} ", array[i].ToString());
}
Console.ReadLine();
}
}
public class BubbleSort
{
public void Maopao(int[] items)
{
for (int i = 0; i < items.Length; i++)
{
bool flag = false;//标记用,若已无数据兑换,则证明排序成功退出循环
for (int j = 0; j < items.Length - 1 - i; j++)
{
if (items[j] > items[j + 1])
{
int temp = items[j];
items[j] = items[j + 1];
items[j + 1] = temp;
flag = true;
}
}
if (flag == false)
{
break;
}
}
}
}
快速排序算法
using System;
2
3
public class Sort
4
{ 5 public class Quick_Sort 6 { 7 private static int QuickSort_Once(int[] _pnArray, int _pnLow, int _pnHigh) 8 { 9 int nPivot = _pnArray[_pnLow]; //将首元素作为枢轴 10 int i = _pnLow, j = _pnHigh; 11 12 while (i < j) 13 { 14 //从右到左,寻找首个小于nPivot的元素 15 while (_pnArray[j] >= nPivot && i<j) j--; 16 //执行到此,j已指向从右端起首个小于nPivot的元素 17 //执行替换 18 _pnArray[i] = _pnArray[j]; 19 //从左到右,寻找首个大于nPivot的元素 20 while (_pnArray[i] <= nPivot && i<j) i++; 21 //执行到此,i已指向从左端起首个大于nPivot的元素 22 //执行替换 23 _pnArray[j] = _pnArray[i]; 24 } 25 26 //推出while循环,执行至此,必定是i=j的情况 27 //i(或j)指向的即是枢轴的位置,定位该趟排序的枢轴并将该位置返回 28 _pnArray[i] = nPivot; 29 return i; 30 } 31 32 private static void QuickSort(int[] _pnArray, int _pnLow, int _pnHigh) 33 { 34 if (_pnLow >= _pnHigh) return; 35 36 int _nPivotIndex = QuickSort_Once(_pnArray, _pnLow, _pnHigh); 37 //对枢轴的左端进行排序 38 QuickSort(_pnArray, _pnLow, _nPivotIndex-1); 39 //对枢轴的右端进行排序 40 QuickSort(_pnArray, _nPivotIndex + 1,_pnHigh); 41 } 42 43 public static void Main() 44 { 45 Console.WriteLine("请输入待排序数列(以\",\"分割):"); 46 string _s = Console.ReadLine(); 47 string[] _sArray = _s.Split(",".ToCharArray()); 48 int _nLength = _sArray.Length; 49 int[] _nArray = new int[_nLength]; 50 for (int i = 0; i < _nLength; i++) 51 { 52 _nArray[i] = Convert.ToInt32(_sArray[i]); 53 } 54 QuickSort(_nArray, 0, _nLength-1); 55 Console.WriteLine("排序后的数列为:"); 56 foreach (int _n in _nArray) 57 { 58 Console.WriteLine(_n.ToString()); 59 } 60 } 61 } 62 } 63
C语言常见排序算法之交换排序(冒泡排序,快速排序) 目录 前言 1.交换排序——冒泡排序 1.1 算法思想 1.2 动图演示 1.3 冒泡最好的情况 2. 交换排序——快速排序 2.1 快速排序——挖坑法 2.3 快速排序——左右指针法 2.4 前后指针法
前言
本期为大家带来的是常见排序算法中的交换排序,主要有冒泡排序,快速排序,快排分享了三种算法:挖坑法,左右指针法,前后指针法,以及两种优化方式:解决快排最坏情况的“三数取中”,避免递归次数过多的"小区间优化",
基本思想: 所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位 置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移 动。
1.交换排序——冒泡排序
冒泡排序(Bubble Sort)基本思想: 冒泡排序,类似于水中冒泡,较大的数沉下去,较小的数慢慢冒起来,假设从小到大,即为较大的数慢慢往后排,较小的数慢慢往前排。直观表达,每一趟遍历,将一个最大的数移到序列末尾。也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,将他们之间小的,或者大的值交换过来。遍历数列的工作是重复地进行,直到没有再需要交换的,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。
1.1 算法思想
比较相邻的元素,如果前一个比后一个大,交换之。 第一趟排序第i个和第i+1个比较与交换,随后第i+1个和第i+2个一对比较交换,这样直到倒数第n-1个和最后n个,将最大的数移动到最后一位。 第二趟将第二大的数移动至倒数第二位
……
1.2 动图演示
算法实现:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define N 10
Swap(int *p1, int * p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void Print(int *a)
{
for (int i=0;i<N;i++)
{
printf("%d ",a[i]);
}
}
void BubbleSort(int* a, int n)
{
for (int j=0;j<n;++j)
{
int size = 0;
for (int i=1;i<N-j;++i)
{
if (a[i-1]>a[i])
{
Swap(&a[i-1],&a[i]);
size =1;
}
}
if (size==0)
{
break;
}
}
}
int main()
{
int a[N] = {0};
for (int i=0;i<N;++i)
{
a[i] = rand();
}
BubbleSort(a,N);
Print(a);
return 0;
}
其中有一段优化程序,是定义一个变量判断排序是否在做无效操作,当内循环处于交换状态时,则数据未排序完毕,否则视为,数据已有序,我们就可以break;中止掉程序,避免做无用遍历。
1.3 冒泡最好的情况
待排序数列有序时,时间复杂度是O(N)。外循环只执行一次,内循环N-1,N-2,N-3……
冒泡排序的特性总结:
1. 冒泡排序是一种非常容易理解的排序 2. 时间复杂度:O(N^2) 3. 空间复杂度:O(1) 4. 稳定 性:稳定
总结:
总的来说,冒泡排序是一种可以的排序,比直接选择排序要好,虽然有优化程序,但是,整体算法效率跟其他排序来比,还是差一些,比较适合新手学习。
2. 交换排序——快速排序
快速排序(Quicksort)是Hoare于1962年提出的一种二叉树结构的交换排序方法,有时候也叫做划分交换排序,是一个高效的算法,其基本思想为:任取待排序 元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有 元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所 有元素都排列在相应位置上为止。这是一个分治算法,而且它就在原地交换数据排序。
是目前已知最快的排序算法,会比一般的排序更节省时间。
2.1 快速排序——挖坑法
算法实现:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//打印
void Print(int *a,int n)
{
for (int i=0;i<n;++i)
{
printf("%d ",a[i]);
}
}
//挖坑法
void QuickSort(int* a,int left,int right)//升序
{
if (left < right)
{
int begin = left;
int end = right;
int pivot = begin;//记录坑位的下标
int key = a[begin];//坑值
while (begin < end)
{
//右边找小,放到左边
while (begin < end && a[end] >= key)//与坑值比较
{
--end;
}
//小的放在左边的坑里,自己形成了新的坑位
a[pivot] = a[end];
pivot = end;
//左边找大,放在右边
while (begin < end && a[begin] <= key)//与坑值比较
{
++begin;
}
//大的放在右边的坑里,自己形成了新的坑位
a[pivot] = a[begin];
pivot = begin;
}
//最后将坑值给到坑位
a[pivot] = key;
//[left,right]
//[left,pivot-1] [pivot+1,right]
//左子区间和右子区间有序,我们就有序了,如何让他们有序?分治递归
QuickSort(a, left, pivot - 1);
QuickSort(a, pivot + 1, right);
}
else
{
return;
}
}
int main()
{
int a[10] = {0,9,5,6,3,2,1,7,8,4};
//挖坑法
QuickSort(a,0,sizeof(a)/sizeof(a[0])-1);
//打印
Print(a,sizeof(a) / sizeof(a[0]));
return 0;
}
快排的缺点
根据上面的代码,我们来分析一下快排的缺点:
如何解决快排对有序数据排序效率很差的方法?
三数取中法
所谓三数取中,不是取最大值,最小值,以及他们的中间值,而是取左边(begin)、右边(end)和中间(begin+end)/2;
在有序的情况下中间的值刚好就是二分,将取出的值作为坑位,就不会出现最差的这种情况。我们依旧使用区间的开头作为“坑值”,但是要使用三数取中的逻辑。
选坑位:
int begin = left;
int end = right;
//使用三数取中选“坑值”,用mid存储其下标
int mid = GetMidIndex(a, begin, end);
//将区间首值当作坑位
//坑值与首值交换,避免算法混乱
//一般我们会将区间首值作为坑值
Swap(&a[begin], &a[mid]);//传地址调用
//存储坑值
int key = a[begin];
三数取中 GetMidIndex();
int GetMidIndex(int *a,int left,int right)
{
//二分
int mid = (right - left) / 2;
if (a[left]<a[mid])
{
if (a[left]<a[right])
{
if (a[mid]<a[right])
{
return mid;
}
else //a[mid]>=a[right]
{
return right;
}
}
else //a[left]>=a[right]
{
return left;
}
}
else //a[left]>=a[mid]
{
if (a[mid]<a[right])
{
if (a[left]<a[right])
{
return left;
}
else //a[left]>=a[right]
{
return right;
}
}
else //a[mid]>=a[right]
{
return mid;
}
}
}
交换Swap();
//交换
void Swap(int* p1, int*p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
经过三数取中的处理,就不会出现快排的最坏情况,但也几乎不会成为最好的情况,有利有弊,我们在面试的过程中只需要写基础版的快排即可,以防时间不够。
小区间优化:
关于如果处理数据多,相应的递归次数多,会不会影响操作快排的性能?
当我们在使用快排对大量数据进行排序时,我们可以采用小区间优化,减少递归次数,达到优化程序得到目的。
对当待处理数据大于10的子序列进行快排递归。
对当待处理数据低于10的子序列进行直接插入排序进行排序,避免递归次数过多。
这个10不是固定的,可以根据处理的数据量调整。
//区间[left,right]
//左区间[left,pivot-1] 右区间[pivot+1,right]
//左子区间和右子区间有序,我们就有序了,如何让他们有序?分治递归
// 小区间优化
if (pivot - 1 - left > 10)//对当待处理数据大于于10的子序列进行快排递归排序
{
//快排
QuickSort(a,left,pivot-1);
}
else
{
//采用直接插入排序,对当待处理数据低于10的子序列进行排序,避免递归
InsertSort(a+left,pivot-1-left+1);//为什么最后要加1,例如:区间[0,9]实际上有10个数
}
if (right - (pivot + 1) > 10)
{
QuickSort(a,pivot+1,right);
}
else
{
InsertSort(a + pivot+1, right-(pivot+1)+1);
}
如果大家有想了解直接插入排序可以查看博主的另一篇:C语言常见排序算法之插入排序(直接插入排序,希尔排序)
2.3 快速排序——左右指针法
根据上图的示例我们应该能够理解左右指针法是什么样的逻辑,跟挖坑法是一样的思想,单趟排序完毕实现左边比坑位小,右边比坑位大。但是即使左右指针法跟挖坑法的思想是一样的,但是他们单趟的运算结果是不一样的。
算法实现:
void QuickSort(int* a, int left, int right)
{
if (left < right)
{
int begin = left;
int end = right;
//选坑位
int mid = GetMidIndex(a, begin, end);//三数取中
Swap(&a[begin], &a[mid]);
int key = begin;
while (begin < end)
{
while (begin < end && a[end] <= a[key])
--end;
while (begin < end && a[begin] >= a[key])
++begin;
Swap(&a[begin], &a[end]);
}
Swap(&a[begin], &a[key]);
//分治递归
QuickSort(a, left, begin - 1);
QuickSort(a, begin + 1, right);
}
}
2.4 前后指针法
采用perv记录区间第一个元素的下标,采用cur记录区间第二个元素的下标。 cur找小,每次遇到比key(坑值)小的值就停下来,++prev。 交换prev和cur位置的值
算法实现:
//左右指针法
void QuickSort(int* a, int left, int right)
{
if (left < right)
{
//选坑位
int mid = GetMidIndex(a, left,right);//三数取中
Swap(&a[left], &a[mid]);
int key = left;
//初始化指向
int prev = left, cur = left + 1;
while (cur<=right)
{
if (a[cur] <= a[key])//&&++prev!=cur
{
++prev;
//避免无效操作
if(cur!=prev)
Swap(&a[prev],&a[cur]);
}
++cur;
}
Swap(&a[key], &a[prev]);
//分治递归
QuickSort(a, left, prev - 1);
QuickSort(a, prev + 1, right);
}
}
快速排序的特性总结:
1.快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序 2.时间复杂度:O(N*logN) 3.空间复杂度:O(logN) 4.稳定性:不稳定
总结:
快排是我们一定要掌握的一种排序算法,在面试、笔试中也是很常见的,博主分享的三种方法:挖坑法,左右指针法,前后指针法,只少要掌握一种,但是要其他的方法也要知道算法思想。还有两种优化方式,小区间优化和三数取中,也要知道是什么逻辑,解决什么问题。
到此这篇关于C语言常见排序算法之交换排序(冒泡排序,快速排序)的文章就介绍到这了,更多相关C语言交换排序 内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
您可能感兴趣的文章: C语言中的冒泡排序问题 C语言中qsort函数用法及用冒泡排序实现 C语言深入探究冒泡排序与堆排序使用案例讲解 C语言详解冒泡排序实现 C语言实现冒泡排序算法的示例详解 c语言冒泡排序和选择排序的使用代码 C语言冒泡排序算法代码详解 C语言冒泡排序超全面实现流程
Go经典算法之 冒泡排序 选择排序 快速排序 归并排序 以下是几种经典的排序算法
//选择排序 O(n^2)
func selectSort(nums []int) []int {
for i := 0; i < len(nums)-1; i++ {
for j := i + 1; j < len(nums); j++ {
if nums[i] > nums[j] {
nums[i], nums[j] = nums[j], nums[i]
}
}
}
return nums
}
//冒泡排序 O(n^2)
func buSort(nums []int) []int {
for i := 0; i < len(nums)-1; i++ {
for j := 0; j < len(nums)-1-i; j++ {
if nums[j] > nums[j+1] {
nums[j], nums[j+1] = nums[j+1], nums[j]
}
}
}
return nums
}
//快速排序 nlog2n
func quickSort(nums []int, begin int, end int) {
if begin >= end {
return
}
pivot := partition(nums, begin, end)
quickSort(nums, begin, pivot-1)
quickSort(nums, pivot+1, end)
}
func partition(nums []int, begin int, end int) int {
var pivot = end
var current = begin
for i := begin; i < end; i++ {
if nums[i] < nums[pivot] {
nums[i], nums[current] = nums[current], nums[i]
current++
}
}
nums[current], nums[pivot] = nums[pivot], nums[current]
return current
}
//归并排序 nlog2n
func mergeSort(nums []int, begin int, end int) {
if begin >= end {
return
}
mid := (begin + end)>>1
mergeSort(nums, begin, mid)
mergeSort(nums, mid+1, end)
merge(nums, begin, mid, end)
}
func merge(nums []int, begin int, mid int, end int) {
var temp []int
var i, j = begin, mid + 1
for i <= mid && j <= end {
if nums[i] >= nums[j] {
temp = append(temp, nums[j])
j++
} else {
temp = append(temp, nums[i])
i++
}
}
if i <= mid {
temp = append(temp, nums[i:mid+1]...)
}
if j <= end {
temp = append(temp, nums[j:end+1]...)
}
for i := 0; i < len(temp); i++ {
nums[begin+i] = temp[i]
}
}
//二分查找算法
func binarySearch(nums []int, target int) int {
var left, right = 0, len(nums) - 1
for left <= right {
var mid = (left + right) / 2
if nums[mid] == target {
return mid
} else if nums[mid] > target {
right = mid - 1
} else {
left = mid + 1
}
}
return -1
}
今天关于php排序算法(冒泡排序,快速排序) 和php冒泡排序和快速排序 的介绍到此结束,谢谢您的阅读,有关4.1_8种常用排序算法1(交换排序:冒泡排序+快速排序)、c#冒泡排序算法和快速排序算法、C语言常见排序算法之交换排序(冒泡排序,快速排序)、Go经典算法之 冒泡排序 选择排序 快速排序 归并排序 等更多相关知识的信息可以在本站进行查询。