没有独立的文字说明,因为是边回忆,边写,边查经典,所以所有的文字说明都在代码中。呵呵
package org.acooly.datastructure.sort; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.math.RandomUtils; /** * 排序算法回顾和学习 <br> * <li>先回忆下算法,然后根据普通逻辑思维,写my排序算法()。 * <li>翻开经典《JAVA数据结构和算法第二部》,学习经典排序算法,然后对比学习 * * @author zhangpu * */ public abstract class JavaBaseSort { // { 3, 21, 46, 75, 56, 39, 7, 95, 93, 1 }; public static void main(String[] args) { int dataSize = 10; int[] randomData = new int[dataSize]; for (int i = 0; i < randomData.length; i++) { int member = RandomUtils.nextInt(dataSize * 10); if (!ArrayUtils.contains(randomData, member)) { randomData[i] = member; } else { i--; } } long start = 0; int[] data = randomData.clone(); System.out.println("我的冒泡排序:"); printArray("原始数据: ", data = new int[]{6,5,4,67,23,3,12,32,30,1}); start = System.currentTimeMillis(); myBubbleSort(data); System.out.println("排序时间: " + (System.currentTimeMillis() - start) + "ms"); printArray("排序数据:", data); System.out.println(); System.out.println("经典冒泡排序:"); printArray("原始数据: ", data = randomData.clone()); start = System.currentTimeMillis(); bubbleSort(data); System.out.println("排序时间: " + (System.currentTimeMillis() - start) + "ms"); printArray("排序数据: ", data); System.out.println(); System.out.println(); System.out.println("我的选择排序:"); printArray("原始数据: ", data = randomData.clone()); start = System.currentTimeMillis(); mySelectSort(data); System.out.println("排序时间: " + (System.currentTimeMillis() - start) + "ms"); printArray("排序数据: ", data); System.out.println(); System.out.println("经典选择排序:"); printArray("原始数据: ", data = randomData.clone()); start = System.currentTimeMillis(); selectSort(data); System.out.println("排序时间: " + (System.currentTimeMillis() - start) + "ms"); printArray("排序数据: ", data); System.out.println(); System.out.println(); System.out.println("我的插入排序:"); printArray("原始数据: ", data = randomData.clone()); start = System.currentTimeMillis(); myInsertSort(data); System.out.println("排序时间: " + (System.currentTimeMillis() - start) + "ms"); printArray("排序数据: ", data); System.out.println(); System.out.println("经典插入排序:"); printArray("原始数据: ", data = randomData.clone()); start = System.currentTimeMillis(); insertSort(data); System.out.println("排序时间: " + (System.currentTimeMillis() - start) + "ms"); printArray("排序数据: ", data); } /** * 我的写法 * 逐个与开始位置的比较,小的向左边沉 * @param data */ public static void myBubbleSort(int[] data) { int swapCount = 0; int loopCount = 0; for (int j = 0; j < data.length - 1; j++) { for (int i = j+1; i < data.length; i++) { if (data[j] > data[i]) { swap(data, j, i); swapCount++; } loopCount++; } } System.out.println("交换次数:" + swapCount); System.out.println("比较次数:" + loopCount); } /** * JAVA数据结构和算法第二版的写法 <br> * 书中算法有小BUG,原书中out > 1,应该是大于0,或in < out修改为in <= out * * @param data */ public static void bubbleSort(int[] data) { int swapCount = 0; int loopCount = 0; for (int out = data.length - 1; out > 0; out--) { for (int in = 0; in < out; in++) { if (data[in] > data[in + 1]) { swap(data, in, in + 1); swapCount++; } loopCount++; } } System.out.println("交换次数:" + swapCount); System.out.println("比较次数:" + loopCount); } /** * 我的选择排序 <br> * <li>还是经典的厉害,虽然效果一样,思路一样,但是我就是多了个min变量来保存每次循环的最小值。实际这个值对排序是无意义的。 * <li>但是,我没有想到,经过测试(10000个数字),我这个写法比经典的要快进40%左右。可能是,经典算法每次要定位然后在比较,我少了定位这一步。 * * <li>选择排序与冒泡比较来说,主要是少了交换次数,控制在N-1交换,比较次数一样。算法效率有提升(10000个数排序测试)。 <br> * <li>如果交换时间比比较时间更耗时,那么选择排序会比冒泡优越很多。 * * @param data */ public static void mySelectSort(int[] data) { int swapCount = 0; int loopCount = 0; for (int i = 0; i < data.length - 1; i++) { int min = data[i]; int minIndex = i; for (int j = i; j < data.length; j++) { if (min > data[j]) { min = data[j]; minIndex = j; } loopCount++; } swap(data, i, minIndex); swapCount++; } System.out.println("交换次数:" + swapCount); System.out.println("比较次数:" + loopCount); } /** * 选择排序(书中经典写法) * * @param data */ public static void selectSort(int[] data) { int swapCount = 0; int loopCount = 0; int out, in, min; for (out = 0; out < data.length - 1; out++) { min = out; for (in = out; in < data.length; in++) { if (data[min] > data[in]) { min = in; } loopCount++; } swap(data, out, min); swapCount++; } System.out.println("交换次数:" + swapCount); System.out.println("比较次数:" + loopCount); } /** * 我的插入排序<br> * <li>只能一个郁闷了得,我只是理解了算法的思路,写法太龌龊了。不加注释估计看不懂。</li> * <li>还是经典的看起舒服。可读性强,好理解。</li> * * <li>插入排序在原始数据完全无序的情况下比较和复杂和冒泡,选择排序无限接近O(N^2) * <li>原始数据基本有序或部分有序的情况下,因为内层循环判断会减少,所有无限接近O(N) * * @param data */ public static void myInsertSort(int[] data) { int swapCount = 0; int loopCount = 0; for (int i = 1; i < data.length; i++) { // 从第2个元素开始向前比较 int flag = data[i]; // 开始比较的基准元素 int targetIndex = 0; // 默认没有找到插入位置,则插入到第1个 // 从开始比较的元素前面一个开始比较,找到比基准元素小的元素, // 以该元素的前面个位置作为插入点,其它元素依次后移。 // 如果查到到起点都没有比基准元素小的值,则插入到第1个元素的为位置 for (int j = i - 1; j >= 0; j--) { if (flag >= data[j]) { // 找到比基准元素小的值,保持插入点,退出循环 targetIndex = j + 1; break; } else { // 没有找到比基准元素小的值,则向后移动 data[j + 1] = data[j]; swapCount++; } loopCount++; } // 插入 data[targetIndex] = flag; swapCount++; } System.out.println("交换次数:" + swapCount); System.out.println("比较次数:" + loopCount); } /** * 经典插入算法 * * @param data */ public static void insertSort(int[] data) { int swapCount = 0; int loopCount = 0; for (int out = 1; out < data.length; out++) { int flag = data[out]; int in = out; while (in > 0 && data[in - 1] >= flag) { data[in] = data[in - 1]; in--; loopCount++; swapCount++; } data[in] = flag; swapCount++; } System.out.println("交换次数:" + swapCount); System.out.println("比较次数:" + loopCount); } /** * 交换数组中两个元素的值 * * @param data * @param i * @param j */ private static void swap(int[] data, int i, int j) { int temp = data[i]; data[i] = data[j]; data[j] = temp; } private static void printArray(String message, int[] data) { System.out.println(message + ArrayUtils.toString(data)); } }