冒泡排序C,java,js实现及其三种优化方法

冒泡排序(Bubble Sort)是基本的交换排序算法之一

  • 定义:通过相邻之间的元素比较大小,进行交换。

  • 基本思想:若前一个比后一个大,则交换,第一趟会把最大的放到最后。

  • 时间复杂度:O(n^2)

  • 稳定性:稳定(若元素相同,稳定即表示通过排序之后获得的数组中,相同元素的位置不会发生改变)

1. 实现(下面分别用C语言,Java,和JavaScript 实现)
(1)C语言
#include<stdio.h>
int main()
{
	int i,j;
    int a[10] = {34,65,2,43,54,64,23,49,78,89};
    for(i=0;i<10-1;i++){
        for(j = 0;j<10-i-1;j++){
            if(a[j]>a[j+1]){
                int temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
            }
        }
    }
    for(i=0;i<10;i++)
    {
    	printf("%5d",a[i]);
    }
    printf("\n");
	return 0;
} 

运行结果如下在这里插入图片描述

(2)Java
public class Bubble_Sort {
	public static void main(String[] args){
		int i,j;
	    int [] a = {34,65,2,43,54,64,23,49,78,89};
	    for(i=0;i<10-1;i++){
	        for(j = 0;j<10-i-1;j++){
	            if(a[j]>a[j+1]){
	                int temp = a[j];
	                a[j] = a[j+1];
	                a[j+1] = temp;
	            }
	        }
	    }
	    for(i=0;i<10;i++)
	    {
	    	System.out.print(a[i]+"  ");
	    }
	}
}

运行结果如下
在这里插入图片描述

(3)JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
    var i,j;
    var a = [34,65,2,43,54,64,23,49,78,89];
    for(i=0;i<a.length-1;i++){
        for(j = 0;j<a.length-i-1;j++){
            if(a[j]>a[j+1]){
                var temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
            }
        }
    }
   console.log(a);
    </script>
</body>
</html>

运行结果如下:
在这里插入图片描述

2. 优化(3种优化,JavaScript实现)
(1)设置标志位(适用于连片有序,但整体无序数据)

在排序过程中,如果有一趟没有进行交换,则表示已完成排序,即不必继续比较后面的元素,所以我们在交换处设置flag标志位,若flag值没有发生变化,则说明排序完成,跳出循环。

上面的js代码若每一趟输出数组a,则结果如下:
进行了9次排序。
在这里插入图片描述
优化代码如下(js)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
    var i,j,flag = 0;
    var a = [34,65,2,43,54,64,23,49,78,89];
    for(i=0;i<a.length-1;i++){
        flag = 0;
        for(j = 0;j<a.length-i-1;j++){
            if(a[j]>a[j+1]){
                flag = 1;
                var temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
            }
        }
        if(flag == 0){//表示这一趟没有进行交换,即排序完成
            break;
        }
        console.log(a);
    }
    </script>
</body>
</html>

优化之后进行了5次排序,运行结果如下:
在这里插入图片描述

(2)每次交换记录最后一次的位置(适用于前面无序,但是后面有序)

记录每趟交换的最后位置作为下趟比较的结束位置,到0时停止。因为没有交换,说明后面的数据已经有序,所以不做无效比较,下次直接比较到上次交换的最后位置即可。

一般的冒泡排序比较次数都是逐次少1,如图:
数字为每趟的比较次数,数组a为每次的排序结果
在这里插入图片描述

但是优化会减少它的比较次数(代码及结果如下)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
    var i,j,end,t,c = 0;
    var a = [34,65,2,43,54,64,23,49,78,89];
    end = a.length-1;
    for(i=0;i<a.length-1;i++){
        t = 0;
        c = 0;//记录比较次数,看是否优化
        for(j = 0;j<end;j++){
            c++;
            if(a[j]>a[j+1]){
                t = j;//记录比较的位置
                var temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
            }
        }
        console.log(c);
        end = t;//把比较的最后位置作为下次比较的结束位置
        console.log(a);
        if(t == 0){
            break;
        }
    }
    </script>
</body>
</html>

在这里插入图片描述

(3)双向冒泡排序

每次既从左往右找最大值,又从右往左找最小值,把最大值放最后,最小值放前面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
    var a = [34,65,2,43,54,64,23,49,78,89];
    var i,j,end,t,c = 0,flag;
    var left = 0;//左边界的初始值
    var right = a.length-1;//右边界的初始值
    var before = 0,after = 0;//记录左右边界的最后一次位置
    for(i=0;i<a.length-1;i++){
        flag = 0;c = 0;
        //正向寻找最大值
        for(j = left;j<right;j++){
            if(a[j]>a[j+1]){
                c++;
                after = j;//记录比较的位置
                var temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
                flag = 1;
            }
        }
        //反向寻找最小值
        for(j = right;j>left;j--){
            if(a[j]<a[j+1]){
                c++;
                before = j;//记录比较的位置
                var temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
                flag = 1;
            }
        }
        if(flag == 0){
            break;
        }
        left = before;
        right = after;
        console.log(c);
        console.log(a);
    }
    </script>
</body>
</html>

运行结果如下:(数字表示比较次数,数组为每趟比较结果)
在这里插入图片描述

最后说一下稳定性。

一般来说,冒泡排序是稳定的,但是一个排序的稳定性主要还是由具体算法决定,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种条件下也可以变为不稳定的算法。比如今天所分享的冒泡排序,将元素交换的条件改成a[j]>=a[j+1],则两个相等的元素就会交换位置,即不稳定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章