/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** *折半插入排序 * @author NC * @version 1.0 */ public class BInsertSorter extends Sorter { @Override public void sort(SortArray array, boolean order) { int n = array.length; int i, j, low, high, m; for (i = 2; i <= n; i++) { array.setKey(i); //保存关键字 low = 1;//设定比较区间 high = i - 1; while (low <= high) { m = (low + high) / 2; if (array.compareToKey(m, !order)) { high = m - 1;//插入点在低半区 } else { low = m + 1;//插入点在后半区 } } //找到插入点,开始移动,插入 for (j = i - 1; j >= high + 1; j--) { array.setElement(j + 1, array.getElement(j)); array.addMoveCount(); } array.addInsertCount(); array.setElement(high + 1, array.getKey()); //插入正确的位置 } } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 冒泡排序 * 方法:相邻两元素进行比较,如有需要则进行交换,每完成一次循环就将最大元素排在最后(如从小到大排序),下一次循环是将其他的数进行类似操作。 * 性能:比较次数O(n^2),n^2/2;交换次数O(n^2),n^2/4 * @author NC * @version 1.0 */ public class BubbleSorter extends Sorter { @Override public void sort(SortArray array, boolean order) { int n = array.length; int i, j, flag = 1; for (i = n; i > 1 && flag == 1; i--) {//该趟最后一个数为关键字,假定为最大的;要求当一趟冒泡过程中不再有数据交换,则排序结束 flag = 0; for (j = 1; j <= i - 1; j++) { if (array.compare(j, j + 1, !order)) { //关键字前面的数相邻(注意是相邻)两两比较,大的就往后冒 array.swap(j, j + 1); flag = 1; } } } } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** *桶排序的思想就是把区间[0,1)划分成n个相同大小的子区间,或称桶,然后将n个输入数分布到各个桶中去。 * 因为输入数均匀分布在[0,1)上,所以一般不会有很多数落在 一个桶中的情况。为得到结果,先对各个桶中的数进行排序,然后按次序把各桶中的元素列 出来即可。 * @author NC */ public class BucketSorter extends Sorter { //这个方法只设正序的 @Override public void sort(SortArray array, boolean order) { sort(array.getArray(),0,array.length,array.length*2); //SortArray的随机数据是1到两倍数组长度之间 } public void sort(int[] array, int from, int len, int max) { int[] temp = new int[len]; int[] count = new int[max]; //分配到各个桶里面 for (int i = 0; i < len; i++) { count[array[from + i]]++; } //对每个桶排序 for (int i = 1; i < max; i++) { count[i] = count[i] + count[i - 1]; } //按顺序把每个桶中的元素列出来 System.arraycopy(array, from, temp, 0, len); for (int k = len - 1; k >= 0; k--) { array[--count[temp[k]]] = temp[k]; } } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 计数排序 * @author NC * @version */ public class CountSorter extends Sorter { @Override public void sort(SortArray array, boolean order) { int n = array.length; int[] ds = new int[n]; //分配临时空间 int i, j, count = 0; for (j = 1; j <= n; j++) { count = 0; for (i = 1; i <= n; i++) { if (i != j)//关键字与其他数比较 { if (array.compare(i, j, order)) { count++; } else if (array.equal(i, j) && j < i) { //j<i保证排序的稳定性,去掉时当数据有一样大时会出错 count++; } } } ds[count] = array.getElement(j); } array.setArray(ds); } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 堆排序 * @author NC * @version 1.0 */ public class HeapSorter extends Sorter { private static int heapAdjust(SortArray array, int start, int end, boolean order) { int flag = 0; int left = 0; int right = 0; int max = 0; left = start * 2; right = start * 2 + 1; while (left <= end) { max = left; if (right <= end) { if (array.compare(left, right, order)) { max = right; } else { max = left; } } if (array.compare(start, max, order)) { array.swap(start, max); flag = 1; start = max; } else { break; } left = start * 2; right = start * 2 + 1; } return flag; } private static void buildHeap(SortArray array, boolean order) { int n = array.length; int i; for (i = n / 2; i > 0; i--) { heapAdjust(array, i, n, order); } } @Override public void sort(SortArray array, boolean order) { int n = array.length; int i; buildHeap(array, order); for (i = n; i > 1; i--) { array.swap(1, i); heapAdjust(array, 1, i - 1, order); } } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 插入排序 * 方法:将一个记录插入到已排好序的有序表(有可能是空表)中,从而得到一个新的记录数增1的有序表。 * 性能:比较次数O(n^2),n^2/4 * 复制次数O(n),n^2/4 * 比较次数是前两者的一般,而复制所需的CPU时间较交换少,所以性能上比冒泡排序提高一倍多,而比选择排序也要快。 * @author NC * @version 1.0 */ public class InsertSorter extends Sorter { @Override public void sort(SortArray array, boolean order) { int n = array.length; int i, j; for (i = 2; i <= n; i++) { if (array.compare(i, i - 1, order)) {//比关键字大的话 array.setKey(i); //暂存关键字 array.setElement(i, array.getElement(i - 1)); //比关键字大,后移(前面已经比较过了) array.addMoveCount(); for (j = i - 1; j >= 1 && array.compareToKey(j, !order); j--) {//比关键字大,后移;比关键字小的话,就退出,找到要插入的位置了 array.setElement(j + 1, array.getElement(j)); array.addMoveCount(); } array.setElement(j + 1, array.getKey()); //插入正确的位置 array.addInsertCount(); } } } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 归并排序 * @author NC * @version 1.0 */ public class MergeSorter extends Sorter { //非递归归并排序 @Override public void sort(SortArray array, boolean order) { int n = array.length; int beforeLen = 1; //合并前序列的长度 int afterLen = 1;//合并后序列的长度 for (beforeLen = 1; afterLen <= n; beforeLen = afterLen) { afterLen = beforeLen << 1; //合并后序列的长度是合并前的两倍 int i = 1;//开始合并时第一个序列的起始位置下标,每次都是从1开始 while (i + afterLen - 1 <= n) {//足够分成两个子表 Merge(array, i, i + beforeLen - 1, i + afterLen - 1, order); i += afterLen; } if (i + beforeLen <= n) { Merge(array, i, i + beforeLen - 1, n, order); } } } //递归归并排序 public void mergeSort2(SortArray array, boolean order) { mergeSort(array, 1, array.length, order); } //递归归并排序 public void mergeSort2(SortArray array) { mergeSort(array, 1, array.length, Sorter.POSITIVE); } private void mergeSort(SortArray array, int left, int right, boolean order) { if (left < right) { int center = (left + right) / 2; mergeSort(array, left, center, order); mergeSort(array, center + 1, right, order); Merge(array, left, center, right, order); } } private void Merge(SortArray array, int left, int center, int right, boolean order) { //[1,2,3,4] left=1,ceter=2,right=4 int[] temp = new int[right - left + 1];//存放被合并后的元素 int i = left; int j = center + 1; int k = 0; while (i <= center && j <= right) { array.addInsertCount(); if (array.compare(i, j, order)) { temp[k++] = array.getElement(i++); } else { temp[k++] = array.getElement(j++); } } while (i <= center) { array.addInsertCount(); temp[k++] = array.getElement(i++); } while (j <= right) { array.addInsertCount(); temp[k++] = array.getElement(j++); } //把t[]的元素复制回a[] for (i = left, k = 0; i <= right; i++, k++) { array.setElement(i, temp[k]); } } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 奇偶交换排序 * @author NC * @version */ public class ParitySorter extends Sorter { @Override public void sort(SortArray array, boolean order) { int n = array.length; int i = 0, j = 0, tag = 1; for (j = 0; j < n; j++) { for (i = j % 2 + 1; i <= n - 1; i += 2) { //每次仅对奇数或偶数下标处理,步长为2 if (array.compare(i, i + 1, !order)) { array.swap(i, i + 1); tag = 0;//记录比较趟数 } } tag++; if (tag == 3) { break; } /*如果待排序列本身已经有序, 则只需执行再次内层循环即对奇偶下标元素分别扫描一次 就可判断出序列已经有序*/ } } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 快速排序 * 快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。 * 步骤为: * 1. 从数列中挑出一个元素,称为 "基准"(pivot), * 2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。 * 在这个分割之后,该基准是它的最后位置。这个称为分割(partition)操作。 * 3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。 * 递回的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。 * 虽然一直递回下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。 * @author NC * @version 1.0 */ public class QuickSorter extends Sorter { private int partition(SortArray array, int low, int high, boolean order) { int key = array.getElement(low); //用子表的第一个记录作为枢轴记录 while (low < high) {//从表的两端交替地向中间扫描 while (low < high && array.compareNotMoreThan(array.getElement(high), key, !order)) { high--; } array.setElement(low, array.getElement(high)); while (low < high && array.compareNotMoreThan(array.getElement(low), key, order)) { low++; } array.setElement(high, array.getElement(low)); array.addExchangeCount(); } array.setElement(low, key); array.addInsertCount(); return low; } private void qSort(SortArray array, int low, int high, boolean order) { int pivotloc; if (low < high) {//保证长度大于1,递归的出口 pivotloc = partition(array, low, high, order); //将表low-high一分为2,用枢轴位置来分 qSort(array, low, pivotloc - 1, order); //对低子表递归排序 qSort(array, pivotloc + 1, high, order); //对高子表递归排序 } } @Override public void sort(SortArray array, boolean order) { int n = array.length; qSort(array, 1, n, order); } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 选择排序 * 方法:每一趟从待排序的数据元素中选出最小(或最大)的一个元素, 顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 * 性能:比较次数O(n^2),n^2/2 * 交换次数O(n),n * 交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CUP时间多,所以选择排序比冒泡排序快。 * 但是N比较大时,比较所需的CPU时间占主要地位,所以这时的性能和冒泡排序差不太多,但毫无疑问肯定要快些。 * @author NC * @version 1.0 */ public class SelectSorter extends Sorter { @Override public void sort(SortArray array, boolean order) { int n = array.length; int x, k, i, j; for (i = 1; i < n; i++) { k = i; //暂时定为最小的关键字 for (j = i + 1; j <= n; ++j) { if (array.compare(j, k, order)) { k = j; //与i之后的n-i个数依次比较,记录小值下标 } } if (k != i) {//k值改变,原先定的不是最小。找到最小的,交换 array.swap(i, k); } } } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package nc.norman.sorter; /** * 希尔排序 * @author NC * @author 1.0 */ public class ShellInsertSorter extends Sorter { @Override public void sort(SortArray array, boolean order) { int n = array.length; int k = n / 2; while (k > 0) { shellInsert(array, k, order); k = k / 2; //分配增量 } } private void shellInsert(SortArray array, int dk, boolean order) { int n = array.length; //dk为增量 int i, j; for (i = dk + 1; i <= n; i++) { //共n-(dk+1)+1个子序列,分别进行直接插入排序 if (array.compare(i, i - dk, order)) {//比关键字大的话 array.setKey(i); //暂存关键字 for (j = i - dk; j > 0 && array.compareToKey(j, !order); j = j - dk) {//比关键字小的就退出,找到位置了。j<=0说明方序列已经是有序的 array.setElement(j + dk, array.getElement(j)); //记录后移,找到插入位置时退出 array.addMoveCount(); } array.setElement(j + dk, array.getKey()); //插入关键字 array.addInsertCount(); } } } }
源码请见上一篇的附件