算法初体验--冒泡排序


最近由于在忙着准备秋招,所以赶紧把之前学的稀烂的算法抓起来,正好也分享一下我对这些算法的理解。

算法的基本概念

如何判断一个算法的好坏程度呢,主要从两个方面来判断:一是这个算法消耗的时间,二是这个算法消耗的空间。

所以这个时候就有了时间复杂度和空间复杂度的概念了,这里我就不把百度百科拿出来了,我就通俗的讲下时间复杂度和空间复杂度的概念。

时间复杂度

就是用来描述算法运行时间的一个名词,那么如何描述它呢,这时候就要引入大O表示法了,这样讲的话也比较抽象呢。我们还是引入一个例子来理解大O表示法。
通常我们喜欢写这样的for循环

for(int i=0;i<n;i++){
  //TODO
}

这个时候这个时间复杂度就是N,那么我们如果里面还有一个for循环呢,那么就是这样

for(int i=0;i<n;i++){
	for(int j=0;j<n;j++){
	//TODO
	}
}

这个时候时间复杂度就是N²了,如果有三个这个呢,那么时间复杂度是不是3N²呢,这个时候我们就会忽略这个系数,所以它的时间复杂度还是N²。这里为什么要忽略系数呢?因为数据很大的时候,这个系数起到作用远远小于后面的N的三次方带来的影响,所以我们可以忽略掉
如果这个算法是这样的

for(int i=0;i<n;i++){
	for(int j=0;j<n;j++){
		for(int k=0;k<n;k++){
			//TODO
			}
	}
}

for(int i=0;i<n;i++){
	for(int j=0;j<n;j++){
		//TODO
	}
}

这个时候就不要以为这个算法的时间复杂度是N³+N²了,这个时候我们就只看最高阶忽略低阶项。同理也是上面那个原因,当数据量很大的时候,N²带来的影响远远小于N³带来的影响,所以它的时间复杂度就是N³了。这时候我们也可以感受到N的时间复杂度是远远好于N²的。所以这时候就有个时间复杂度的简单排名:

O(1)<O(logN)<O(N)<O(N*logN)<O(N²)<O(N³)<O(2的N次方)<O(N!)
空间复杂度

空间复杂度就是该算法需要消耗的存储空间,一般由于现在对于时间的要求更为严格,所以大家愿意花费空间去换取时间,所以这里先不做过多讨论,因为后面的算法会陆续加深空间复杂度的理解。

冒泡排序

讲了这么久,终于来到了重点,冒泡排序。那么什么是冒泡排序呢,其实我们可以根据名字来理解这个排序算法。冒泡嘛,就有点像鱼儿吐泡泡,一直一直往水面上冒。

可能这样讲还是有点模糊,哈哈,当时我自己也是理解了很久,其实生活中很多冒泡排序的例子,之前小学的时候,大家应该都要做广播体操嘛,于是就涉及到站队的问题了,其实冒泡排序就和最开始的站队很像,那么这个过程是怎么样呢?我们来探讨一下

一群人乱糟糟的站在一起,这样肯定不行,于是老师便来帮我们来排序,老师肯定首先看到最高的那个人,所以最高的那个人先出来了,然后又在一堆人中找,然后和这个最高的人进行比,慢慢的选出第二高的人,最后排好序。那么这个过程要比多少次,这就得我们慢慢来探索了。

 1 9 0 8 6 6 4 7

假设上面数字代表着一群人,我们是不是第一眼就看到了最高的9呢,其实这时我们默默的在心中把9和其他的数字都比了一下,这时候比较的次数是7,这个不要忽略掉。于是我们把9放在最后面

1 0 8 6 6 4 7 9

然后我们又来找第二个高的,这时候我们看到了8,其实8是不用和9进行比较的,因为之前9已经和8比较了一次呢。所以这个时候比较的次数是6,我们将8放到了最后面

1 0 6 6 4 7 8 9

同理慢慢往前面比,就是7+6+5+4+3+2+1,这个就是比较的总次数。这时候我们一看这不就是等差数列嘛,如果有N个数,那么就是(1+(N-1))* N / 2,所以就是N²/2,但是我们要忽略前面的系数。所以最终时间复杂度就是N²

那么接下来用代码演示一下冒泡排序(由于我主要搞java,所以下面代码是用java写的,不过算法跟语言的影响不大,如果实在觉得java看不习惯,最下面我还写了C++代码)

Java代码

public void BubbleSort(int[] arr){
        if (arr == null || arr.length<2){
            return ;
        }
        //i 为比较的次数,也是最末位置的下标
        for (int i=arr.length-1;i>0;i--) {
            for (int j = 0; j < i; j++)
                    if (arr[j]>arr[j+1]) //若a[j]大于a[j+1],则交换a[j]与a[j+1]
                         swap(arr,j,j+1);
        }
    }
   

    //交换两个数,这个是位运算其实就是交换两个数,看不习惯可以看下面这个swap
    public static void swap(int[] arr, int i, int j) {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }
    
	//交换两个数
	 public static void swap(int[] arr, int i, int j) {
		int temp;
		temp = arr[i] ;
        arr[i] = arr[j] ;
        arr[j] = temp;
	}

如果上面代码看得不是很明白,那么我再来啰嗦一下,哈哈。想当初自己也是看了这代码好几次,没关系,多写几次就熟悉了这个过程。因为最重要的还是练习的过程

我们来看第一个for循环,i=arr.length-1这个条件我们第一次不管找的是哪个数,都要和除了自己以外的其他数进行比较,所以这个就是数组的长度减去1,然后每次循环都要减少一个数进行比较。所以这是第一个for循环的意义。

再来看第二个for循环,最开始的条件是j=0,这其实就是数组第一个数,这第一个数和谁进行比较呢,和第二个数进行比较,这时候是不是两个数中最大的数就到了第二的位置,然后***j++***,这个时候是不是就是第二个位置和第三个位置进行比较,两个数中最大的数就到了第三个位置,就这样j循环完一直到最后一个也就是***数组的长度-1***,由于最后一个位置已经是最大的了,所以这又回应了第一个for循环。

C++代码

//交换两个数位运算,同理看不习惯的话下面有普通交换两个数
void swap(int arr[], int i, int j)
{
	 arr[i] = arr[i] ^ arr[j];
     arr[j] = arr[i] ^ arr[j];
     arr[i] = arr[i] ^ arr[j];
}

//交换两个数
void swap(int array[], int i, int j)
{
	int temp = array[i];
	array[i] = array[j];
	array[j] = temp;
}


void BubbleSort1(int array[], int n)
{
	for (int i = 0; i < n-1; i++)
	{
		for (int j = i + 1; j < n-1; j++)
		{
			if (array[i]>array[j])
				swap(array, j, i);//每次i后面的元素比array[i]小就交换。
		}
	}
}

后面还会有更多的排序,以及其他的算法,也会把更多的内容补充完整,敬请期待

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值