排序算法(冒泡,选择,插入,快速)PHP和java实现

这篇博客详细介绍了冒泡排序、选择排序和插入排序三种经典算法的PHP和Java实现,并通过计数循环和交换次数来分析它们的效率。博主探讨了每种排序算法的最坏和最好情况复杂度,并提供了优化思路。文章最后以快速排序为例,展示了更高效的排序方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

php版

<?php
$a = [7,5,3,2,4,8,1,6];
$c=count($a);
$n=1;
$m=1;
//冒泡排序 依次两两比较
//冒泡排序:每次选择两个元素,按照需求进行交换,使小的元素慢慢“浮”到数列的顶端。最坏复杂度 O(n^2) 最好O(n) https://pic4.zhimg.com/v2-33a947c71ad62b254cab62e5364d2813_b.webp (最简单的)
//n=29  m=17
for($i=1;$i<$c;$i++){
    for($j=0;$j<$c-$i;$j++){
        $n++;
        if($a[$j]>$a[$j+1]){
            $tmp = $a[$j];
            $a[$j] = $a[$j+1];
            $a[$j+1] = $tmp;
            $m++;
        }
    }
}

//选择排序 从第一位起在后面所有元素中找出最小的放第一位,然后从第二位起找出剩下元素中最小的放第二位,以此类推
//选择排序:每次选择一个未排序元素与后面所有元素比较选出最小的一个元素与这个元素会换位置。 最坏复杂度 O(n^2) 最好O(n) https://pic1.zhimg.com/v2-1c7e20f306ddc02eb4e3a50fa7817ff4_b.webp
//n=29  m=9或10
for($i=0;$i<$c;$i++){
    $minKey = $i;
    for($j=$i+1;$j<$c;$j++){
        $n++;
        if($a[$minKey]>$a[$j]){
            $minKey = $j;
        }
    }
    $tmp = $a[$minKey];
    $a[$minKey]=$a[$i];
    $a[$i]=$tmp;
    $m++;
}
//插入排序从第2位起与前面元素(已排好)从后到前比较,选择合适的位置插入,
//插入排序:每次选择一个未排序元素,将这个元素和前面已排序的所有元素从后向前比较,插入比它小和比他大的两个数中间。最坏复杂度 O(n^2) 最好O(n)  https://pic3.zhimg.com/v2-8a97a82ab39183f3177e99b5bb74e55e_b.webp
//具体过程:最外层从左到右循环每次循环取出当前值到第二层循环(从i-1到0)中自后向前比较,当j大于tmp时j向后移动一位,tmp补到j的位置,接着移动j指针与tmp比较。
//n=20  m=17
for($i=1;$i<$c;$i++){//外层循环用于从未排序区域中取出待排序元素
    $tmp = $a[$i];  //获取当前需要插入已排序区域的元素值
    for($j=$i-1;$j>=0; $j--){//内层循环用于从已排序区域寻找待排序元素的插入位置
        $n++;
        if($tmp<$a[$j]){//如果$a[$i]比已排序区域的$a[$j]小,就后移$a[$j]
            $a[$j+1]=$a[$j];
            $a[$j]=$tmp;
            $m++;
        }else{
            break;//如果$a[$i]不小于$a[$j],则对已排序区无需再排序
        }
    }
}

echo "循环次数n:".$n."\n";
echo "交换次数m:".$m."\n";
print_r($a);
?>

java版 

int[] arr=new int[]{8,4,5,9,10,3,7,4,0};
        int n = arr.length;
        int count = 0;//循环次数
        //冒泡排序:相邻的两个元素两两比较一轮走下来最大的一个排到了最后,再一轮比较前n-1个,以此类推比较n轮,每一轮比较的元素逐渐递减
        /*思考冒泡排序的优化:如果内层循环一遍后元素无任何移动说明已经排好不需要再继续循环
        优化前count=8+7+6+5+4+3+2+1=36
        优化后count=33
        */
        boolean flag = false;//是否终止外层循环
        for (int i = 0; i < n ; i++) {
            boolean f = false;
            for (int j = 0; j < n-i-1; j++) {
                count++;
                if (arr[j]>arr[j+1]){
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1]=tmp;
                    f = true;
                }
                if (j==n-i-2 && !f){
                    //说明整轮内循环下来都没移动元素,已排好不用继续循环,跳出所有循环
                    flag=true;
                }
            }
            if (flag) {
                break;
            }
        }

        //?:从第一个元素开始和后面所有元素比较,选出最小一个交换位置,一轮下来最小的元素排到了第一个,第二轮拿第二个元素和它后面所有元素比较,将第二小的元素排到第二位,以此类推n轮
        for (int i = 0; i < n; i++) {
            for (int j = i+1; j < n ; j++) {
                if (arr[i]>arr[j]){
                    int tmp = arr[i];
                    arr[i]=arr[j];
                    arr[j]=tmp;
                    count++;
                }
            }
        }
        //选择排序:每次选择一个未排序元素与后面所有元素比较选出最小的一个元素与这个元素会换位置, 上一个方法的优化
        for (int i = 0; i < n; i++) {
            int minKey = i;
            for (int j = i+1; j < n ; j++) {
                if (arr[minKey]>arr[j]){
                    minKey = j;
                }
            }
            if (minKey!=i){
                int tmp = arr[minKey];
                arr[minKey] = arr[i];
                arr[i]=tmp;
            }
        }
        //插入排序:每次选择一个未排序元素,将这个元素和前面已排序的所有元素从后向前比较,插入比它小和比他大的两个数中间
        for (int i = 1; i < n; i++) {
            int f = arr[i];
            for (int j = i-1; j >= 0; j--) {
                if (f<arr[j]){
                    arr[j+1]=arr[j];
                    arr[j]=f;
                }else{
                   break;
                }
            }
        }

    //或者
    for (i = 1; i < n; i++) {
        int tmp = arr[i];
        for (j = i; j > 0 && arr[j - 1] > tmp; j--) {
            n++;
            arr[j] = arr[j - 1];
        }
        arr[j] = tmp;
    }

        System.out.println(Arrays.toString(arr));
        System.out.println(count);

快速排序

public static void main(String[] args) {
        //快速排序:选择一个坐标值,将这个数组分成比此值大和比此值小两部分,再分别选出新的坐标值以此类推
        //Arrays.sort(arr);
        int[] arr=new int[]{8,4,9,10,3,7};
//        int[] arr=new int[]{8,4,5,9,10,3,7,-4,0,11};
        quickSort(arr, 0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quickSort(int[] arr, int start, int end){
        //start end 是调整区域的开始和结束位置
        //l,r指针起点相同且同向移动,分别识别比pivot小和比pivot大的元素
        if (start<=end){
            int pivot=arr[start];  //将开始点做为中心点pivot
            int l=start+1, r=start+1;
            while (r<=end){
                if (arr[r]<pivot){
                    swap(arr, l, r);
                    l++;
                }
                r++;
            }
            swap(arr, start, l-1);//最后交换 pivot 和 第 l-1 个
            quickSort(arr, start, l-2); //递归左侧区域元素,重复以上操作
            quickSort(arr, l, r-1);//递归右侧区域元素,重复以上操作
        }

    }
    public static void quickSort1(int[] arr, int start, int end){
        //left, right 分别在数组的两端相向移动,分别识别比pivot小和比pivot大的元素
        if (start<end){
            int pivot = arr[start];
            int left = start+1;
            int right = end;
            while (left<=right){
                while (left<end && arr[left]<pivot) left++;
                while (right>start && arr[right]>pivot) right--;
                if (left<=right){
                    swap(arr, left, right);
                }
            }
            swap(arr, start, left-1); //交换中心点和left-1
            //quickSort1(arr, start, left-2);
            quickSort1(arr, left, end);
        }
    }

    public static void quickSort3(int[] data, int start, int end) {
        if (start < end) {
            int base = data[start];
            int i = start;
            int j = end + 1;
            while (true) {
                while (i < end && data[++i]<=base)
                    ;
                while (j > start && data[--j]>=base)
                    ;
                if (i < j) {
                    swap(data, i, j);
                } else {
                    break;
                }
            }
            swap(data, start, j);
            quickSort3(data, start, j - 1);
            quickSort3(data, j + 1, end);
        }
    }

    public static void swap(int[] arr, int low, int high){
        if (low != high){
            int tmp = arr[low];
            arr[low] = arr[high];
            arr[high] = tmp;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值