算法刚刚入门,每次记录下自己所学的知识总结以及理解,希望能够帮助大家,如有内容有错误或可改进的地方,欢迎一起探讨,一起进步,在此也要感谢WYSCODER学长给我的学习建议
目录
一、基本概念
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。(查自百度百科)
二、动画演示
三、具体操作
思路
/*
思路:
遍历无序数组,
嵌套循环,外层循环从头到尾遍历这个无序数组,轮数就为数组长度-1,内层循环也是从头到尾遍历这个无序数组,
将第一个与第二个进行比较,如果>则进行交换,以此类推,那么内层遍历了一轮之后,这个无序数组的最后一位一定是最大值
那么下一次的内层循环是不是就不用再遍历全部的数组了,每次内层循环全部遍历一次都会确定一个数的位置,
所以内层循环的次数是逐步递减的,外层循环是每次递增的
例如:
1 3 7 3 8 4 5
经过第一次的内层排序,最后一位是8,那么下一次内层循环索引值仅需要遍历到5就可以了
因此,内层循环次数就为:无序数组长度-1-每次的外层循环的索引值
*/
初始代码
package 排序问题;
import java.io.*;
public class 冒泡排序 {
static StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter output = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] ^ arr[j + 1];//step1
arr[j + 1] = arr[j] ^ arr[j + 1];//step2
arr[j] = arr[j] ^ arr[j + 1];//step3
/*
想一想为什么交换值要用异或,而不开一个变量来保存交换?
我们知道,异或操作符功能是:两个数对应而二进制数的各个位进行比较,相同为0,不相同1
一个数如果异或自己,那么结果就为零,再异或另一个数那么结果就为另一个数
并且运用异或,能减短运行时间,提高效率,因为是直接对计算机底层进行操作
因此:
再交换两个数时,推荐用异或运算符
*/
}
}
}
/*
for (Integer value : arr) {
output.print(value + " ");
output.flush();
}
这是foreach循环,他不需要索引值,Integer是你的数组元素的数据类型,value是你给你的元素所命名的名称,arr就是你要遍历的数组或是集合的名称
如果对输出样式有要求的话就不推荐这个,其他情况下推荐使用,他不会出现数组越界,其他循环有时手误或掌握不牢可能会数组越界
*/
/*
有些题可能对空格会有要求,比如输出一堆数,每个数之间有空格,但最后一个数后没有空格
想一想该怎么满足
那么我们只需要第一个数只输出,剩下的数每次输出空格+下一个数就能轻易解决了
*/
for (int i = 0; i < arr.length; i++) {
if (i==0){
output.print(arr[i]);
output.flush();
}else {
output.print(" "+arr[i]);
output.flush();
}
}
}
public static void main(String[] args) {
int[] example = {8, 5, 1, 4, 7, 5, 7, 3};
sort(example);
}
}
优化思路
/*
优化思路:
如果我们队一组无序数组进行排序
2 1 3 4 5 6 7
我们发现只有前两个是无序的,剩下的数字都是有序的,如果还用上一个方式进行操作,
那么即使后面是有序的,但还是要进行判断,很浪费时间
因此我们要对外层循环进行改动
每次在内层循环的外面创建一个布尔变量=true,表示这轮数组是否为有序,如果无序,布尔变量就为false
如果一轮下来结果为true那么后面的就已经排序好了,我们就不需要轮数再排了,因此直接break循环
内层循环的次数也可以改动,有必要每次都执行arr.length()-1-i吗?
以 2 1 3 4 5 6为例
外层循环次数我们已经控制了,内层循环呢
我们可以发现 3 4 5 6已经是有序的了,但内层循环次数还是每次逐渐递减,实际循环到1就可以了
因此我们需要刷新内层循环次数,这样只需要每次遍历无序数组就可以了,
先设置一个变量来保存最后一次交换的位置,那么他之后的就已经是有序的
再设置一个变量来保存内层循环的刷新次数,最开始为arr.length()-1
每次内层循环之后让他等于保存最后一次交换位置的变量
*/
代码优化
package 排序问题;
import java.io.*;
public class 冒泡排序优化 {
static StreamTokenizer input = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter output = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void sortImprove(int[] arr) {
int lastBored = 0;
int everySort = arr.length - 1;
for (int i = 0; i < arr.length - 1; i++) {
boolean f = true;
for (int j = 0; j < everySort; j++) {
if (arr[j] > arr[j + 1]) {
arr[j] = arr[j] ^ arr[j + 1];
arr[j + 1] = arr[j] ^ arr[j + 1];
arr[j] = arr[j] ^ arr[j + 1];
f = false;
lastBored = j;
}
}
everySort = lastBored;
if (f) break;
}
for (Integer value : arr) {
output.print(value + " ");
output.flush();
}
}
public static void main(String[] args) {
int[] example = {6, 4, 2, 3, 4, 5};
sortImprove(example);
}
}