排序算法终结总结<Java实现>

来源:互联网 发布:php copy 编辑:程序博客网 时间:2024/06/05 23:06
/** * 排序算法学习之希尔排序 * 实现方法: * 希尔排序是特殊的插入排序 * 插入排序按照处理的子数组长度递增分为多趟插入操作 * 而每一趟插入操作处理的子数组元素索引间隔都是1(即步长) * 希尔排序每趟处理的子数组元素索引间隔是动态的。 */package 排序算法.shellSort;public class ShellSort {/** * 对输入数组进行希尔排序 * @param a 待排序数组,索引有效范围从0开始 */@SuppressWarnings({ "rawtypes", "unchecked" })public static void shellSort(Comparable[] a) {int incr = a.length / 2;//初始步长while (incr >= 1) {for (int i = incr; i < a.length; i++) {Comparable insertElement = a[i];int j;for (j = i - incr; j >= 0 &&                                           insertElement.compareTo(a[j]) < 0; j -= incr)a[j + incr] = a[j];a[j + incr] = insertElement;}if (incr == 2)incr = 1; elseincr = (int) (incr / 2.2);}}}


 

/** * 排序算法学习之选择排序 * 实现方法: * 每次选择子数组中最大的元素依次排列在子数组末尾, * 子数组的长度依次递减。 */package 排序算法.selectionSort;public class SelectionSort {@SuppressWarnings({ "rawtypes", "unchecked" })/** * 查找指定长度的数组中最大元素的索引 * @param a 指定数组 * @param n 数组长度 * @return 最大元素的索引 */public static int max(Comparable[] a, int n) {if (n < 0)throw new IllegalArgumentException("数组为空");int positionOfCurrentMax = 0;for (int i = 1; i <= n; i++)if (a[positionOfCurrentMax].compareTo(a[i]) < 0)positionOfCurrentMax = i;return positionOfCurrentMax;}/** * 交换指定数组中指定索引的元素 * @param a 指定数组 * @param i 第一个索引 * @param j 第二个索引 */public static void swap(Object[] a, int i, int j) {Object temp = a[i];a[i] = a[j];a[j] = temp;}/** * 对输入数组执行一般选择排序 * @param a 输入数组 */@SuppressWarnings("rawtypes")public void selectionSort(Comparable[] a) {//按照子数组长度递减的顺序进行每趟的选择操作for (int size = a.length; size > 1; size--) {int j = max(a, size - 1);swap(a, j, size - 1);}}/** * 对输入数组执行早结束版本的选择排序 * @param a 输入数组,数组索引有效范围从0开始 */@SuppressWarnings({ "rawtypes", "unchecked" })public  void selectionSort2(Comparable[] a) {boolean sorted = false;//当前子数组是否有序的标志for (int size = a.length; !sorted && (size > 1); size--) {int pos = 0;sorted = true;for (int i = 1; i < size; i++)if (a[pos].compareTo(a[i]) <= 0)pos = i;elsesorted = false;swap(a, pos, size - 1);}}}


 

/** * 秩排序实现2 * @author Sking */package 排序算法.rankSort;public class RankSort2 {/** * 对指定数组执行秩排序 * @param a 待排序数组 */@SuppressWarnings("rawtypes")private  void rankSort2(Comparable[] a) {int[] r = new int[a.length];rank(a, r);//求数组元素的秩rearrange(a, r);//移动元素到索引为其秩的位置}/** * 交换指定数组中的两个元素 * @param a 指定数组 * @param i 第一个元素的索引值 * @param j 第二个元素的索引值 */  @SuppressWarnings("rawtypes")private static void swap(Comparable[] a, int i, int j)   {  Comparable temp = a[i];      a[i] = a[j];      a[j] = temp;   }  /** * 交换秩数组中的两个元素 * @param a 指定的秩数组 * @param i 第一个元素的索引值 * @param j 第二个元素的索引值 */  private static void swap(int[] a, int i, int j)//重载交换方法   {      int temp = a[i];      a[i] = a[j];      a[j] = temp;   }   /**  * 根据秩数组对待排序数组进行排序  * @param a 待排序数组  * @param r 待排序数组的秩数组  */@SuppressWarnings("rawtypes")private static void rearrange(Comparable[] a, int[] r) {for (int i = 0; i < a.length; i++)//依次检查位置i,如果有i=r[i]则表示元素i位置正确//否则交换位置i和位置r[i]上的元素(r[i]指出索引i位置//上的元素在排序数组中药位于r[i]的位置。while (r[i] != i) {int t = r[i];swap(a, i, t);swap(r, i, t);}}/** * 求指定数组元素的秩,存放在给定数组中 * @param a 待排序数组 * @param r 给定的存放元素秩的数组 */@SuppressWarnings({ "rawtypes", "unchecked" })private static void rank(Comparable[] a, int[] r) {if (r.length < a.length)throw new IllegalArgumentException("秩数组长度异常!");for (int i = 0; i < a.length; i++)r[i] = 0;for (int i = 1; i < a.length; i++)for (int j = 0; j < i; j++)//当左边的元素小于等于右边的元素时,右边元素的秩加1if (a[j].compareTo(a[i]) <= 0)r[i]++;else//当左边的元素不小于右边的元素时,左边的元素的秩加1r[j]++;}}


 

/** * 排序算法学习之秩排序 *@author Sking 秩的定义: 一个序列中元素的秩被定义为序列中小于该元素的的元素  个数加上出现在其左边的相等元素的个数。则可知一个元素在排序序列  中的位置索引就是它们的秩。   实现方法: 1.计算待排序数组元素的秩 2.将数组元素移动到索引值为他们的秩的位置   */package 排序算法.rankSort;public class RankSort1 {/** * 对指定数组执行秩排序 * @param a 待排序的数组 */@SuppressWarnings("rawtypes")public  void rankSort(Comparable[] a) {int[] r = new int[a.length];rank(a, r);//求待排序数组元素的秩rearrange(a, r);//移动元素到索引为他们秩的位置,实现排序}/** * 使用数组元素的秩数组对数组进行排序 * @param a 待排序数组 * @param r 待排序数组元素的秩数组 */@SuppressWarnings("rawtypes")private static void rearrange(Comparable[] a, int[] r) {Comparable[] u = new Comparable[a.length];for (int i = 0; i < a.length; i++)//移动元素到索引为他们秩的位置,实现排序u[r[i]] = a[i];for (int i = 0; i < a.length; i++)a[i] = u[i];}/** * 求指定数组元素的秩,存放在给定数组中 * @param a 待排序数组 * @param r 给定的存放元素秩的数组 */@SuppressWarnings({ "rawtypes", "unchecked" })private static void rank(Comparable[] a, int[] r) {if (r.length < a.length)throw new IllegalArgumentException("秩数组长度异常!");for (int i = 0; i < a.length; i++)r[i] = 0;for (int i = 1; i < a.length; i++)for (int j = 0; j < i; j++)//当左边的元素小于等于右边的元素时,右边元素的秩加1if (a[j].compareTo(a[i]) <= 0)r[i]++;else  //当左边的元素不小于右边的元素时,左边的元素的秩加1r[j]++;}}


 

/** * 排序算法学习之快速排序的非递归实现,使用辅助栈 * @author Sking */package 排序算法.quickSort;import 栈.ArrayStack;public class QuickSort2 {/** * 使用子数组的首个元素作为枢纽,划分子数组 划分后, * 枢纽左边的元素均小于枢纽,右边的元素均大于枢纽  * 并返回划分的位置索引,是快速排序的核心方法 *  * @param a 待排序数组 * @param p 子数组的开始索引 * @param r 子数组的结束索引 * @return 划分的索引位置 */@SuppressWarnings({ })private int partition(int[] a, int p, int r) {int i = p, j = r + 1;int x = a[p];// 使用子数组的首个元素作为枢纽while (true) {// 从左边开始找到大于枢纽的元素索引while (a[++i] < x && i < r);// 同时从右边开始找到小于枢纽的元素索引while (a[--j]> x);if (i >= j)break;// 交换大于枢纽的元素到右边,小于枢纽的元素导左边swap(a, i, j);}// a[i]>=枢纽,a[j]<=枢纽,i>=j的时候表示已经划分完毕a[p] = a[j];// 交换枢纽索引位置所在元素和枢纽a[j] = x;return j;// j为枢纽索引}/** * 交换指定数组中的两个元素 * @param a 指定数组 * @param i  第一个元素的索引 * @param j  第二个元素的索引 */public static void swap(int[] a, int i, int j) {int temp = a[i];a[i] = a[j];a[j] = temp;}/** * 快速排序算法的非递归实现,使用辅助栈 * @param a 待排序的数组段 * @param p  数组段的左端索引 * @param r 数组段的右端索引 */@SuppressWarnings({ "unused" })private void qSort(int[] a, int p, int r) {ArrayStack stack = new ArrayStack();// 栈if (p < r) {int mid = partition(a, p, r);if (p < mid - 1) {stack.push(p);stack.push(mid - 1);}if (mid + 1 < r) {stack.push(mid + 1);stack.push(r);}while (!stack.empty()) {int m = (int) stack.pop();int n = (int) stack.pop();int l = partition(a, n, m);if (n < l - 1) {stack.push(n);stack.push(l - 1);}if (l + 1 < m) {stack.push(l + 1);stack.push(m);}}}}}


 

/** * 排序算法学习之快速排序 * @author Sking 实现方法:通过把一个数组递归的划分为两个子数组。 递归的基本步骤:1. 把数组划分成以一个元素为枢纽的左右两个子数组。 2. 调用自身的左边和右边以步骤1递归。 性能障碍:对枢纽数据的选择是影响排序的效率。  性能: 最坏时间复杂度:O(n^2) 平均时间复杂度:O(n*log(n)) 辅助空间:O(n)或O(log(n)) 稳定性:不稳定 时间复杂度是O(n*log(n)) */package 排序算法.quickSort;public class QuickSort {@SuppressWarnings("rawtypes")/** * 递归划分子数组a[p....r] * @param a 指定数组,索引有效范围从0开始 * @param p 子数组的开始索引 * @param r 子数组的结束索引 */private void qSort(Comparable[] a,int p, int r) {if (p < r) {int q = partition(a,p, r);//划分的位置索引qSort(a,p, q - 1);//递归划分qSort(a,q + 1, r);}}/** * 使用子数组的首个元素作为枢纽,划分子数组 * 划分后,枢纽左边的元素均小于枢纽,右边的元素均大于枢纽 * 并返回划分的位置索引,是快速排序的核心方法 * @param a 待排序数组 * @param p 子数组的开始索引 * @param r 子数组的结束索引 * @return 划分的索引位置 */@SuppressWarnings({ "rawtypes", "unchecked" })private int partition(Comparable[] a,int p, int r) {int i = p, j = r + 1;Comparable x = a[p];//使用子数组的首个元素作为枢纽while (true) {//从左边开始找到大于枢纽的元素索引while (a[++i].compareTo(x) < 0 && i < r);//同时从右边开始找到小于枢纽的元素索引while (a[--j].compareTo(x) > 0);if (i >= j)break;//交换大于枢纽的元素到右边,小于枢纽的元素导左边swap(a,i, j);}//a[i]>=枢纽,a[j]<=枢纽,i>=j的时候表示已经划分完毕a[p] = a[j];//交换枢纽索引位置所在元素和枢纽a[j] = x;return j;//j为枢纽索引}/** * 交换指定数组中的两个元素 * @param a 指定数组 * @param i 第一个元素的索引 * @param j 第二个元素的索引 */@SuppressWarnings("rawtypes")public static void swap(Comparable[] a,int i, int j) {Comparable temp = a[i];a[i] = a[j];a[j] = temp;}}


 

/** * 排序算法学习之一般合并排序 * @author Sking实现方法:将待排序数组分为大小大致相等的2个子数组分别对两个子数组进行排序,如此递归划分排序最后将排序号的子数组再递归合并为更大的已排序数组直到整个数组已排序为止。 */package 排序算法.mergeSort;public class MergeSort2 {/** * 对指定数组的指定范围执行一般合并排序 *  * @param a *            指定数组 * @param left *            指定范围的左边索引 * @param right *            指定范围的右边索引 */@SuppressWarnings("rawtypes")public void mergeSort2(Comparable[] a, int left, int right) {Comparable[] b = new Comparable[a.length];if (left < right) {int i = (left + right) / 2;mergeSort2(a, left, i);//左子段递归排序mergeSort2(a, i + 1, right);//右子段递归排序merge(a, b, left, i, right);//合并子段到新数组中copy(a, b, left, right);//复制排序后的元素到原数组}}/** * 合并已排序子数组c[l...m]和c[m+1,r]到新数组中,新数组保持有序 *  * @param c存放两个已排序数组的数组 * @param d *            新数组,用于存放合并后的数组 * @param l *            左边子数组的起始索引 * @param m *            左边子数组的结束索引 * @param r *            右边子数组的结束索引 */@SuppressWarnings({ "rawtypes", "unchecked" })private static void merge(Comparable[] c, Comparable[] d, int l, int m,int r) {int i = l;int j = m + 1;int k = l;while ((i <= m) && (j <= r))if (c[i].compareTo(c[j]) <= 0)d[k++] = c[i++];elsed[k++] = c[j++];if (i > m)for (int q = j; q <= r; q++)d[k++] = c[q];elsefor (int q = i; q <= m; q++)d[k++] = c[q];}/** * 复制源数组中指定索引范围内的元素到目标数组 *  * @param a *            源数组 * @param b *            目标数组 * @param left *            指定范围的左边索引 * @param right *            指定范围的右边索引 */@SuppressWarnings("rawtypes")private static void copy(Comparable[] a, Comparable[] b, int left, int                                           right) {int i = left;int j = left;while (i <= right)a[i++] = b[j++];}}


 

/** * 排序算法学习之合并排序 * @author Sking  实现方法:将待排序数组中相邻元素两两配对作为子数组,排序各个子数组, 构成n/2组长度为2的排序好的子数组;然后将长度为2的子排序 子数组再两两配对,并排序,构成长度为4的已排序子数组。如此递归 直到整个数组是已排序为止。   最坏时间复杂度:O(n*log(n))  平均时间复杂度:O(n*log(n))  辅助空间:O(n)  稳定性:稳定 */package 排序算法.mergeSort;public class MergeSort {@SuppressWarnings("rawtypes")/** * 对输入数组执行合并排序 * @param a 指定数组,索引有效位置从0开始 */public void mergeSort(Comparable[] a) {Comparable[] b = new Comparable[a.length];// 辅助空间int s = 1;// 初始子数组长度设置为1while (s < a.length) {mergePass(a, b, s);s += s;mergePass(b, a, s);s += s;}}/** * 合并相邻的已排序子数组为更大的已排序子数组 *  * @param x *            包含了已排序子数组的数组 * @param y *            包含更大的已排序子数组的数组 * @param s *            已排序子数组的长度 */@SuppressWarnings("rawtypes")public static void mergePass(Comparable[] x, Comparable[] y, int s) {int i = 0;while (i <= x.length - 2 * s) {// 合并两相邻的长度为s的已排序子数组merge(x, y, i, i + s - 1, i + 2 * s - 1);i = i + 2 * s;}// 当i>x.length-2*s的时候退出while循环// 处理剩下的部分,可以是s长度的已排序数组+“零片”// 也可能只是“零片“,此时不需要合并。if (i + s < x.length) {// 合并相邻的长度s的已排序子数组和长度小于s的“零片”merge(x, y, i, i + s - 1, x.length - 1);} else// 处理”零片“for (int j = i; j < x.length; j++)y[j] = x[j];}/** * 合并已排序子数组c[l...m]和c[m+1,r]到新数组中,新数组保持有序 *  * @param c存放两个已排序数组的数组 * @param d *            新数组,用于存放合并后的数组 * @param l *            左边子数组的起始索引 * @param m *            左边子数组的结束索引 * @param r *            右边子数组的结束索引 */@SuppressWarnings({ "unchecked", "rawtypes" })static void merge(Comparable[] c, Comparable[] d, int l, int m, int r) {int i = l;// 第一个子数组的索引指针int j = m + 1;// 第二个子数组的索引指针int k = l;// 新数组的索引指针while ((i <= m) && (j <= r))if (c[i].compareTo(c[j]) <= 0)d[k++] = c[i++];elsed[k++] = c[j++];if (i > m)// 将右边子数组剩下的元素添加到新数组中for (int q = j; q <= r; q++)d[k++] = c[q];else// 将左边子数组剩下的元素添加到新数组中for (int q = i; q <= m; q++)d[k++] = c[q];}}


 

/** * 排序算法学习之插入排序 * @author Sking */package 排序算法.insertionSort;public class InsertionSort {@SuppressWarnings({ "rawtypes", "unchecked" })/** * 一次元素插入的实现,在n长度的子数组中插入元素x到合适位置 * @param a 带排序数组,索引有效范围从0开始 * @param n 子数组元素个数 * @param x 待插入的元素 */public static void insert(Comparable[] a, int n, Comparable x) {if (a.length < n + 1)//数组已满,不可插入throw new IllegalArgumentException("数组不够大");int i;//当前被比较元素索引for (i = n - 1; i >= 0 && x.compareTo(a[i]) < 0; i--)a[i + 1] = a[i];//比x大的元素后移,寻找x插入的位置a[i + 1] = x;//插入x}/** * 对输入数组执行插入排序 * @param a 待排序数组,索引有效位置从0开始 */@SuppressWarnings("rawtypes")public static void insertionSort(Comparable[] a) {//i表示一次元素插入步骤所考虑的子数组长度,大小递增for (int i = 1; i < a.length; i++)insert(a, i, a[i]);}}


 

/** * 排序算法学习之冒泡排序 * 使用时,将Comparable类型替换为指定类型,必要时,要定义比较方法 * @author Sking */package 排序算法.bubbleSort;public class BubbleSort {/** * 交换数组元素方法 * @param a 指定数组 * @param i 第一个索引 * @param j 第二个索引 */@SuppressWarnings("rawtypes")public static void swap(Comparable[] a, int i, int j) {Comparable t = a[i];a[i] = a[j];a[j] = t;}/** * 一次冒泡迭代,分别比较相邻元素选择单趟的最大元素 * @param a 指定数组 * @param n 冒泡子序列的长度 */@SuppressWarnings({ "rawtypes", "unchecked" })private static void bubble(Comparable[] a, int n) {for (int i = 0; i < n - 1; i++)if (a[i].compareTo(a[i + 1]) > 0)swap(a, i, i + 1);}/** * 一般冒泡排序 * @param a 指定数组 */@SuppressWarnings("rawtypes")public static void bubbleSort(Comparable[] a) {for (int i = a.length; i > 1; i--)bubble(a, i);}/** * 早结束版本的冒泡排序方法的一次迭代 * @param a 指定数组 * @param n 冒泡子序列的长度 * @return 如果该次迭代中进行了元素交换位置,则返回true,否则返回false */@SuppressWarnings({ "rawtypes", "unchecked" })private static boolean haveBubble(Comparable[] a,int n){boolean swapped=false;//标志一次冒泡是否进行交换for(int i=0;i<n-1;i++)if(a[i].compareTo(a[i+1])>0){swap(a,i,i+1);swapped=true;}return swapped;}/** * 早结束版本的冒泡排序 * @param a 指定排序的数组 */@SuppressWarnings("rawtypes")public static void bubbleSort2(Comparable[] a){for(int i=a.length;i>1&&haveBubble(a,i);i--);}}


 

原创粉丝点击