简单排序——冒泡排序(bubble sort)
我们的目的是按照从小到大排序一组数,过程是两两进行交换,如果前者比后者大就交换两个元素的位置,直到最大的元素被换到最后一个位置,则第一趟结束。 每一趟都有一个最大值归到最后一位。重复即可实现全部元素从小到大的排列。
分析;
时间复杂度;如果是正序,则时间复杂度最好的情况为O(n),逆序的话,最坏是O(n^2),平均是O(n^2)
空间复杂度;O(1),当一个算法的空间复杂度为一个常量,即不被处理数据量n的大小而改变时,可表示为O(1);
稳定性;稳定!因为如果两个元素相等,则不交换;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换。
public class BubbleSort {
//
private long[] arr;
//
private int elems;
/**
* 无参构造
*/
public BubbleSort() {
arr = new long[50];
}
/**
* 带参构造
*/
public BubbleSort(int max) {
arr = new long[max];
}
/**
* 插入
*/
public void insert(long value) {
arr[elems] = value;
elems++;
}
/**
* 打印
*/
public void display() {
for (int i = 0; i < elems; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
/**
* 查找
*/
public int find(long searchKey) {
int i;
for (i = 0; i < elems; i++) {
if (arr[i] == searchKey) {
break;
}
}
if (i == arr.length) {
return -1;
} else {
return i;
}
}
/**
* 删除
*/
public void delete(long deleteKey) {
if (find(deleteKey) == -1) {
System.out.println("error");
} else {
//
for (int i = find(deleteKey); i < elems; i++) {
arr[i] = arr[i + 1];
}
// 0 1 2 3 5 6 7 8 9 9
//
// intArray[intArray.length - 1] = 0;
}
elems--;
}
/**
* 修改
*
* @param oldValue
* @param newValue
*/
public void change(long oldValue, long newValue) {
if (find(oldValue) == -1) {
System.out.println("error");
} else {
arr[find(oldValue)] = newValue;
}
}
/**
* 冒泡排序(升序)
*/
public void bubbleSort() {
// 声明在循环外面,效率高
long temp = 0L;
// 控制排序趟数
for (int i = 0; i < elems; i++) {
// 控制每趟的比较次数,每计较一趟都有一个数到最终位置(不再参与比较),所以比较了i趟,出现i个最终位置,则长度减i,
for (int j = 0; j < elems - i - 1; j++) {
// 这里之所以减去i还要减去1是因为是两两交换,后面用的i+1和i比较,则elems - i - 1
if (arr[j] > arr[j + 1]) {
// 递增排序
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
注意;
1、理论上,每一趟都要产生一个最终位置(最值在最后面去,仿佛咕嘟咕嘟的水泡一个个的升到了水面上,故起名字叫起泡排序),也就是每一个待排序元素都要有一个最终位置,那么我们的外层循环,就是控制排序趟数,n个元素,那么就理论上是n个最终位置,走上n趟,同理,走了i趟,那么就是长生了i个最终位置,都特么的上后面(冒出去了),肯定就不用再比较了,故内部循环需要控制比较次数,长度 - i 是必要的。
2、注意效率,把声明放到循环体的外部。
3、内部循环控制每一趟的比较次数,因为是两两进行比较,肯定最后剩余一个和空位比较,那样的话就错了,所以我们要 elems - i - 1 处理。
到此,一个简单的冒泡(又名起泡)排序算法,就算写完了,为了更好理解,用eclipse进行断点调试看看过程,先写一个测试类test.java
public class Test {
public static void main(String[] args) {
BubbleSort bubbleSort = new BubbleSort();
//SimpleSelectionSort simpleSelectionSort = new SimpleSelectionSort();
bubbleSort.insert(0);
bubbleSort.insert(5326);
bubbleSort.insert(512);
bubbleSort.insert(754);
bubbleSort.insert(4);
bubbleSort.insert(856);
bubbleSort.insert(1);
bubbleSort.display();
// 冒泡排序
bubbleSort.bubbleSort();
bubbleSort.display();
// simpleSelectionSort.insert(231);
// simpleSelectionSort.insert(3);
// simpleSelectionSort.insert(11);
// simpleSelectionSort.insert(4124);
// simpleSelectionSort.insert(52352);
// simpleSelectionSort.insert(51345136);
// simpleSelectionSort.display();
// //简单选择排序
// simpleSelectionSort.SimpleSelectSort();
// simpleSelectionSort.display();
}
}
打印;
0 5326 512 754 4 856 1
0 1 4 512 754 856 5326
进行断点调试查看运行过程;
在红线出,双击即可,或者右键添加断点,然后程序空白处右键,选择调试方法(Debug as),调试java应用程序。
如图所示;
点击单步运行
然后开始观测即可!这是第一趟排序中,前两个不用交换,紧着着下一对比较的过程。
连续点击下一步step into即可观测;
通过调试,我们可以及时的发现算法的错误,帮助我们改进!