java排序冒泡排序_Java 排序算法之冒泡排序

冒泡排序,英文称为:Bubble Sort。

该算法名称的由来是因为数据会经由交换慢慢“浮”到数列的顶端。

冒泡排序的基本思想

冒泡排序的基本思想是多次比较和交换:

(1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。

(2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

(3)针对所有的元素重复以上的步骤,除了最后一个。

(4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

冒泡排序示例

以从小到大排序为例:从左向右排序,小的在左边,大的在右边

初始数据:[67, 60, 55, 50, 45]

一轮排序:[60, 55, 50, 45, 67]

二轮排序:[55, 50, 45, 60, 67]

三轮排序:[50, 45, 55, 60, 67]

四轮排序:[45, 50, 55, 60, 67]

排序结果:[45, 50, 55, 60, 67]

(1)第 1 轮排序:从数组的头部开始向尾部依次排序。

首先比较 67 和 60 ,由于 67 比 60 大,两者需要交换位置,交换位置后 [60, 67, 55, 50, 45];

继续比较 67 和 55 ,由于 67 比 55 大,两者需要交换位置,交换位置后 [60, 55, 67, 50, 45];

继续比较 67 和 50 ,由于 67 比 50 大,两者需要交换位置,交换位置后 [60, 55, 50, 67, 45];

继续比较 67 和 50 ,由于 67 比 45 大,两者需要交换位置,交换位置后 [60, 55, 50, 45, 67];

(2)第 2 轮排序:从数组的头部开始向尾部依次排序。

首先比较 60 和 55 ,由于 60 比 55 大,两者需要交换位置,交换位置后 [55, 60, 50, 45, 67];

继续比较 60 和 50 ,由于 60 比 50 大,两者需要交换位置,交换位置后 [55, 50, 60, 45, 67];

继续比较 60 和 45 ,由于 60 比 45 大,两者需要交换位置,交换位置后 [55, 50, 45, 60, 67];

继续比较 60 和 67 ,由于 60 比 67 小,两者不需要交换位置;

(3)第 3 轮排序:从数组的头部开始向尾部依次排序。

首先比较 55 和 50 ,由于 55 比 50 大,两者需要交换位置,交换位置后 [50, 55, 45, 60, 67];

继续比较 55 和 45 ,由于 55 比 45 大,两者需要交换位置,交换位置后 [50, 45, 55, 60, 67];

继续比较 55 和 60 ,由于 55 比 60 小,两者不需要交换位置;

(4)第 4 轮排序:从数组的头部开始向尾部依次排序。

首先比较 50 和 45 ,由于 55 比 45 大,两者需要交换位置,交换位置后 [45, 50, 55, 60, 67];

继续比较 50 和 55 ,由于 50 比 55 小,两者不需要交换位置;

升序排序:1

2

3

4

5

6

7

8

9

10

11

12

13

14public static int[] bubbleAscSort(int[] arr) {

int size = arr.length;

int temp;

for (int i = 1; i < size; i++) {

for (int j = 0; j < size - i; j++) {

if (arr[j] > arr[j + 1]) {

temp = arr[j];

arr[j] = arr[j + 1];

arr[j + 1] = temp;

}

}

}

return arr;

}

降序排序:只需要更换一下比较运算符即可1

2

3

4

5

6

7

8

9

10

11

12

13

14public static int[] bubbleDescSort(int[] arr) {

int size = arr.length;

int temp;

for (int i = 1; i < size; i++) {

for (int j = 0; j < size - i; j++) {

if (arr[j] < arr[j + 1]) {

temp = arr[j];

arr[j] = arr[j + 1];

arr[j + 1] = temp;

}

}

}

return arr;

}

冒泡排序的优化

常规冒泡排序采用双层循环的方式,单向循环,通过比较相邻数据,进行交换实现排序,优化方向就两点:冒泡排序优化之减少无用循环轮数

假设初始数据是:[67, 45, 50, 55, 60],那么实际上有效的排序只需要一轮,数据就已经排序完毕。但是默认还是会进行 4 轮排序。

可以设置一个标志,标记本轮排序是否存在数据交换,若没有交换则不需要进行下一轮排序,反之则需要继续下一轮排序

以升序排序为例:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17public static int[] bubbleAscSort(int[] arr) {

boolean isAscSorted = false;

int size = arr.length;

int temp;

for (int i = 1; !isAscSorted && i < size ; i++) {

isAscSorted = true;

for (int j = 0; j < size - i; j++) {

if (arr[j] > arr[j + 1]) {

isAscSorted = false;

temp = arr[j];

arr[j] = arr[j + 1];

arr[j + 1] = temp;

}

}

}

return arr;

}

那么,在第 2 轮排序时,因为没有数据交换,则标志被标记为已排序,第 3 轮排序 和 第 4 轮排序则不必进行,这样可以减少排序轮数。冒泡排序优化之减少无用轮内循环比较

假设初始数据是:[45, 55, 67, 50, 60]

以带标记的升序排序为例:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21public static int[] bubbleAscSort(int[] arr) {

boolean isAscSorted = false;

int size = arr.length;

int maxSwapIndex = size - 1;

int temp;

int lastSwapIndex = 0;

for (int i = 1; !isAscSorted && i < size ; i++) {

isAscSorted = true;

for (int j = 0; j < maxSwapIndex; j++) {

if (arr[j] > arr[j + 1]) {

isAscSorted = false;

temp = arr[j];

arr[j] = arr[j + 1];

arr[j + 1] = temp;

lastSwapIndex = j;

}

}

maxSwapIndex = lastSwapIndex;

}

return arr;

}

一轮排序:[45, 55, 50, 60, 67]

二轮排序:[45, 50, 55, 60, 67]

三轮排序:[45, 50, 55, 60, 67]

排序结果:[45, 50, 55, 60, 67]

开始排序:

标记单轮最大的数据交换位置 maxSwapIndex :size - 1

标记最后一次数据交换位置 lastSwapIndex : 0

(1)第 1 轮排序:从数组的头部开始向尾部依次排序:[45, 55, 67, 50, 60]

首先比较 45 和 55 ,由于 45 比 55 小,两者不需要交换位置,数据:[45, 55, 67, 50, 60];

继续比较 55 和 67 ,由于 55 比 67 小,两者不需要交换位置,数据:[45, 55, 67, 50, 60];

继续比较 67 和 50 ,由于 67 比 50 大,两者需要交换位置,交换位置后 [45, 55, 50, 67, 60],以本次数据交换位置标记为最后一次数据交换位置,lastSwapIndex = 2;

继续比较 67 和 60 ,由于 67 比 60 小,两者需要交换位置,交换位置后 [45, 55, 50, 60, 67],以本次数据交换位置标记为最后一次数据交换位置,lastSwapIndex = 3;

标记下一轮最大的数据交换位置 maxSwapIndex = 3;即后续位置的元素顺序已经排序完毕。

(2)第 2 轮排序:从数组的头部开始向尾部依次排序:[45, 55, 50, 60, 67]

首先比较 45 和 55 ,由于 45 比 55 小,两者不需要交换位置;

继续比较 55 和 50 ,由于 55 比 50 大,两者需要交换位置,交换位置后 [45, 50, 55, 60, 67],以本次数据交换位置标记为最后一次数据交换位置,lastSwapIndex = 2;

继续比较 55 和 60 ,由于 55 比 60 小,两者不需要交换位置;

j 自增后已经是 3 ,不小于 maxSwapIndex ,结束本轮排序

标记下一轮最大的数据交换位置 maxSwapIndex = 2;即后续位置的元素顺序已经排序完毕。

(3)第 3 轮排序:从数组的头部开始向尾部依次排序,数据:[45, 50, 55, 60, 67]

首先比较 45 和 50 ,由于 45 比 50 小,两者不需要交换位置;

继续比较 50 和 55 ,由于 50 比 55 小,两者不需要交换位置;

j 自增后已经是 2 ,不小于 maxSwapIndex ,结束本轮排序

且 isAscSorted 被标记为 已排序,结束排序冒泡排序优化之双向冒泡

以升序排序为例:

双向冒泡即结合上述升序排序和降序排序,在一轮排序内先正向升序排序一次,然后从最后交换数据的位置往前再进行一次反向的降序排序1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33public static int[] bubbleAscSort(int[] arr) {

int size = arr.length;

int maxSwapIndex = size - 1;

int minSwapIndex = 0;

int temp;

int lastSwapIndex = 0;

while (maxSwapIndex > minSwapIndex) {

for (int i = minSwapIndex; i < maxSwapIndex; i++) {

if (arr[i] > arr[i + 1]) {

temp = arr[i];

arr[i] = arr[i + 1];

arr[i + 1] = temp;

lastSwapIndex = i;

}

}

maxSwapIndex = lastSwapIndex;

for (int j = maxSwapIndex; j > minSwapIndex; j--) {

if (arr[j] < arr[j - 1]) {

temp = arr[j];

arr[j] = arr[j - 1];

arr[j - 1] = temp;

lastSwapIndex = j;

}

}

minSwapIndex = lastSwapIndex;

}

return arr;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值