冒泡排序最经典:
public void BubbleSort1(){
for (int i = nElement - 1; i > 0; i--) { for (int j = 0; j < i; j++) { if(arr[j] > arr[j+1]){ swap(j,j+1); } } } } private void swap(int a,int b){ arr[a] = arr[a] + arr[b]; arr[b] = arr[a] - arr[b]; arr[a] = arr[a] - arr[b]; }
以下是冒泡排序排序的改进版本:
/**(优化后的冒泡排序) * 双向冒泡排序 * ps: 获取最大的数放在最右边后,回头获取最小的数放在最左边。以此类推,外层循环次数 n / 2,貌似比单向冒泡快一点。 */ public void BubbleSort2(){ int i,j,k,left = 0,right = nElement - 1; for (i = nElement/2; i > 0; i--) { for (j = left; j < right; j++) { if(arr[j] > arr[j+1]){ swap(j,j+1); } } for (k = right - 1; k > left; k--) { if(arr[k] < arr[k - 1] ){ swap(k,k - 1); } } left++; right--; } } /**(优化后的冒泡排序) * ps:如果 有一次比较没有做任何数据移动,说明已经排好序了,可以结束比较了。 */ public void BubbleSort3(){ boolean isSorted = false; for (int i = nElement - 1; i > 0 && !isSorted; i--) { isSorted = true;//假设已经排好序 for (int j = 0; j < i; j++) { if(arr[j] > arr[j + 1]){ swap(j,j + 1); isSorted = false; } } } } /**(优化后的冒泡排序) * ps:记录最后一次交换位置,这样就可以确定到底那些区域还没有排好序,缩小比较范围。 */ public void BubbleSort4(){ int lastIndex = nElement - 1,j=0; while(lastIndex > 0){ for (int i = j = 0; i < lastIndex; i++) { if(arr[i] > arr[i + 1]){ swap(i, i+1); j = i; } } lastIndex = j; } }
其中BubbleSort2减少了每次比较的次数,提高了效率。而3,4这两个方法也是同样的原理,减少了可能会做的无用功。
下面是选择排序,这个排序是通过减少移动数组的次数来提高效率的。
public void selectSort() { for (int i = 0; i < nElement - 1; i++) { int k = i; for (int j = i + 1; j < nElement; j++) { if (arr[k] > arr[j]) { k = j; } } if (k != i) { swap(k, i); } } }
最后是选择排序,这个排序比冒泡排序应该要快一倍,比选择排序要快一点。如果是倒序排序的话,则可能没有优势,在基本有序的情况下还是可以的。
public void insertSort(){ int repeat = 0,t = 0; for (int i = 1; i < nElement; i++) { int j = i; while (j > t && arr[i] <= arr[j - 1]){ //发现重复值 设置为-1 if(arr[i]==arr[j - 1]){ arr[i] = -1; repeat++; } --j; } t = repeat; if(j < i){ int temp = arr[i]; for (int k = i; k > j; k--) { arr[k] = arr[k - 1]; } arr[j] = temp; } } if(repeat > 0){ nElement = nElement - repeat; for (int i = 0; i < nElement; i++) { arr[i] = arr[i + repeat]; } } }
上面这个排序还加了个删除重复值的功能。
另外一种实现,感觉没有上面的效率高
public void insertSort2(){ for (int i = 1; i < nElement; i++) { int j = i; int temp = arr[i]; while(j > 0 && temp < arr[j - 1]){ arr[j] = arr[--j]; } arr[j] = temp; } }
效率没有第一种高的环境是在倒序的情况下,因为这个环境下移动的次数比较多,原来分开移动没有一次性移动快。其他情况下是差不多的。
下面贴出所有的代码
package sort; public class Sort { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Sort o = new Sort(10000); for (int i = 10; i > 0; i--) { o.insert(i); } o.insert(9); o.insert(8); /*for (int i = 0; i < 10000; i++) { o.insert(i); }*/ long begin = System.currentTimeMillis(); o.insertSort(); long end = System.currentTimeMillis(); System.out.println("time="+(end - begin)); o.display(); } private int[] arr = null; private int nElement = 0;//当前数组的实际长度 public Sort(int size){ this.arr = new int[size]; this.nElement = 0; } public int[] getArr(){return this.arr;} /**插入 * @param c */ public void insert(int c){ arr[nElement++] = c; } public void BubbleSort1(){ for (int i = nElement - 1; i > 0; i--) { for (int j = 0; j < i; j++) { if(arr[j] > arr[j+1]){ swap(j,j+1); } } } } /**(优化后的冒泡排序) * 双向冒泡排序 * ps: 获取最大的数放在最右边后,回头获取最小的数放在最左边。以此类推,外层循环次数 n / 2,貌似比单向冒泡快一点。 */ public void BubbleSort2(){ int i,j,k,left = 0,right = nElement - 1; for (i = nElement/2; i > 0; i--) { for (j = left; j < right; j++) { if(arr[j] > arr[j+1]){ swap(j,j+1); } } for (k = right - 1; k > left; k--) { if(arr[k] < arr[k - 1] ){ swap(k,k - 1); } } left++; right--; } } /**(优化后的冒泡排序) * ps:如果 有一次比较没有做任何数据移动,说明已经排好序了,可以结束比较了。 */ public void BubbleSort3(){ boolean isSorted = false; for (int i = nElement - 1; i > 0 && !isSorted; i--) { isSorted = true;//假设已经排好序 for (int j = 0; j < i; j++) { if(arr[j] > arr[j + 1]){ swap(j,j + 1); isSorted = false; } } } } /**(优化后的冒泡排序) * ps:记录最后一次交换位置,这样就可以确定到底那些区域还没有排好序,缩小比较范围。 */ public void BubbleSort4(){ int lastIndex = nElement - 1,j=0; while(lastIndex > 0){ for (int i = j = 0; i < lastIndex; i++) { if(arr[i] > arr[i + 1]){ swap(i, i+1); j = i; } } lastIndex = j; } } /** * 奇偶排序 * 第一次比较奇数对,第二次比较偶数对。 * 听说如果是多处理器这样排序效率高 */ public void OddEvenSort(){ boolean isSorted = false;int i=0; while(!isSorted){ i++; isSorted = OddOrEventSort(0) || OddOrEventSort(1); } System.out.println(i); } private boolean OddOrEventSort(int i){ boolean isSorted = true; for (int j = i; j < nElement - 1; j+=2) { if(arr[j] > arr[j+1]){ swap(j, j+1); isSorted = false; } } return isSorted; } public void insertSort(){ int repeat = 0,t = 0; for (int i = 1; i < nElement; i++) { int j = i; while (j > t && arr[i] <= arr[j - 1]){ //发现重复值 设置为-1 if(arr[i]==arr[j - 1]){ arr[i] = -1; repeat++; } --j; } t = repeat; if(j < i){ int temp = arr[i]; for (int k = i; k > j; k--) { arr[k] = arr[k - 1]; } arr[j] = temp; } } if(repeat > 0){ nElement = nElement - repeat; for (int i = 0; i < nElement; i++) { arr[i] = arr[i + repeat]; } } } public void insertSort2(){ for (int i = 1; i < nElement; i++) { int j = i; int temp = arr[i]; while(j > 0 && temp < arr[j - 1]){ arr[j] = arr[--j]; } arr[j] = temp; } } public static void insertSort(int[] elements){ for(int i = 1;i <elements.length; i++){ int j = -1; while(j <= i && elements[i] > elements[++j]);//找到element[i]应该摆放的位置,此处可以利用查找算法进行优化 if(j < i){ //将j之后的数据移动一位,然后把elements[i]移动到j处 int temp = elements[i]; for(int k = i-1;k >= j;k--){ elements[k+1] = elements[k]; } elements[j] = temp; } } } public void selectSort() { for (int i = 0; i < nElement - 1; i++) { int k = i; for (int j = i + 1; j < nElement; j++) { if (arr[k] > arr[j]) { k = j; } } if (k != i) { swap(k, i); } } } public void display(){ for (int i = 0; i <nElement; i++) { System.out.println(arr[i]); } } private void swap(int a,int b){ arr[a] = arr[a] + arr[b]; arr[b] = arr[a] - arr[b]; arr[a] = arr[a] - arr[b]; } }