排序算法-冒泡排序

冒泡排序总结

c 代码

#include <stdio.h>

void print_array(int *a, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

void bubbleSort(int *a, int size) {
    for ( int i = 0; i < size-1; i++ ) {
        for ( int j = 0; j < size-1-i; j++ ) { // 从右到左,每次把最大值放到最后一个元素
            if (a[j] > a[j+1]) {
                a[j] += a[j+1];
                a[j+1] = a[j] - a[j+1];
                a[j]  = a[j] - a[j+1];
            }
        }
        print_array(a, size-i);
    }
}

void bubbleSortEnhance(int *a, int size) {
    int exchange = 1;
    for ( int i = 0; i < size-1 && exchange; i++ ) {
        exchange = 0;
        for ( int j = 0; j < size-1-i; j++ ) { // 从右到左,每次把最大值放到最后一个元素
            if (a[j] > a[j+1]) {
                a[j] += a[j+1];
                a[j+1] = a[j] - a[j+1];
                a[j]  = a[j] - a[j+1];
                exchange = 1;
            }
        }
        print_array(a, size-i);
    }
}

void bubbleSortSuper(int *a, int size) {
    int l = 0, h = size, last;

    while (l < h) {
        last = l; //初始化上一次交换位置
        while (++l < h) {
            if (a[l] < a[l-1]) {
                a[l] += a[l-1];
                a[l-1] = a[l] - a[l-1];
                a[l] = a[l] - a[l-1];
                last = l; //记录上一次交换位置
            }
        }
        h = last; //把扫描一趟最后的一次交换位置变为h
        l = 0; //继续下一趟扫描
        printf("l=%d, h=%d last=%d\n", l, h, last);
        print_array(a, h+1);
    }
}

int main() {
    int a[8] = {0, 3, 4, 2, 5, 1, 6, 7};

    //printf("\nbubbleSort\n");
    //bubbleSort(a, 8);
    printf("\nbubbleSortEnhance\n");
    bubbleSortEnhance(a, 8);

    return 0;
}

/*
执行结果:
bubbleSort
0 3 2 4 1 5 6 7 
0 2 3 1 4 5 6 
0 2 1 3 4 5 
0 1 2 3 4 
0 1 2 3 
0 1 2 
0 1 

看上边的执行结果,交换次数执行过程发现是一个倒三角形。 执行7趟扫描交换。

bubbleSortEnhance
0 3 2 4 1 5 6 7 
0 2 3 1 4 5 6 
0 2 1 3 4 5 
0 1 2 3 4 
0 1 2 3

加上标志位,执行过程变成了倒梯形。执行5趟扫描交换。

bubbleSortSuper
l=0, h=5 last=5
0 3 2 4 1 5 
l=0, h=4 last=4
0 2 3 1 4 
l=0, h=3 last=3
0 2 1 3 
l=0, h=2 last=2
0 1 2 
l=0, h=0 last=0
0

把标志位替换为上一趟扫描的最后一次交换的位置,执行过程变成了倒梯形里的间接部分。执行4趟扫描交换。

*/

bubbleSort 算法的复杂度为O(n2),bubbleSortEnhance 与 bubbleSortSuper 这两种算法的复杂度 介于 O(n) 与 O(n2)。

php代码

<?php

function bubbleSort($a) {
     $len = count($a);
     $count = 0;

     for ($i = 0; $i < $len; $i++) { //进行$len次扫描交换
         $count++;
         for ($j = 1; $j < $len - $i; $j++) {
             if ($a[$j] < $a[$j-1]) { //从右到左把最大值放到末尾元素
                list($a[$j], $a[$j-1]) = [$a[$j-1], $a[$j]];
             }
         }
     }

     print_r("bubbleSort-count={$count}\n");

     return $a;
 }

function bubbleSort1($a) {
    $len = count($a);
    $count = 0;
    for ($i = 0; $i < $len; $i++) { //进行$len次扫描交换
        $count++;
        for ($j = $i+1; $j < $len; $j++) {
            if ( $a[$i] > $a[$j] ) { //从左到右把最小的放置到数组首个元素
                list($a[$i], $a[$j]) = [$a[$j], $a[$i]];
            }
        }
    }
    
    print_r("bubbleSort1-count={$count}\n");

    return $a;
}

/**
 * 把最后一次发生交换的标志记录下来,直到没有交换标志了
 * 改进版2
 */
function bubbleSort2($a) {
    $len = count($a);
    // $count = 0;
    for ( $sort = false; $sort = ! $sort; $len--) {
        // $count++;
        for ($i = 1; $i < $len; $i++) {
            if ( $a[$i] < $a[$i-1] ) {
                list($a[$i], $a[$i-1]) = [$a[$i-1], $a[$i]];
                $sort = false; //有变化,说明仍为无需,还行继续下一趟排序
            }
        }
    }
    // print_r("bubbleSort2-count={$count}\n");

    return $a;
}

/**
 * 把最后一次发生交换的标志记录下来,直到没有交换标志了
 * 改进版3(交换标志易理解代码版)
 */
function bubbleSort3($a) {
    $len = count($a);
    $sort = false;
    // $count = 0;
    while (!$sort) {
        // $count++;
        $sort = true;
        $i = 0;
        while (++$i < $len) {
            if ($a[$i] < $a[$i-1]) {
                list($a[$i], $a[$i-1]) = [$a[$i-1], $a[$i]];
                $sort = false; //有变化,说明仍为无需,还行继续下一趟排序
            }
        }
    }
    // print_r("bubbleSort3-count={$count}\n");

    return $a;
}

/**
 * 把最后一次比较的位置记录下来的优化的冒泡算法
 * 改进版4
 */
function bubbleSort4($a) {
    $l = 0;
    $h = count($a);
    // $count = 0;
    while ($l < $h) { //直到$h == $l 则停止
        // $count++;
        $last = $l;
        while (++$l < $h) {
            if ($a[$l] < $a[$l-1]) { //从小到大
                list($a[$l], $a[$l-1]) = [$a[$l-1], $a[$l]]; //交换数据
                $last = $l; //始终记录右侧发生最后一次交换
            }
        }
        $h = $last; //下次比较内容仅从上一次发生交互的左边进行
    }

    // print_r("bubbleSort4-count={$count}\n");

    return $a;
}

$a = [1, 5, 4, 6, 9, 7, 8];
print_r($a);
// $A = bubbleSort($a);
// print_r($A);
// $b = bubbleSort1($a);
// print_r($b);
// $c = bubbleSort2($a);
// print_r($c);
// $d = bubbleSort3($a);
// print_r($d);
$e = bubbleSort4($a);
print_r($e);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值