博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
排序算法(1)-冒泡排序,选择排序,插入排序,希尔排序,快速排序
阅读量:4059 次
发布时间:2019-05-25

本文共 10833 字,大约阅读时间需要 36 分钟。

一些基本的排序算法:

package tenSortingMethods;/** * @author zhangdi * @description 排序算法 * @Date 20180531 */public class Sort {
public static void main(String[] args) { int[] arr = {
6,1,2,7,9,3,4,5,10,8};//{ 26, 88, 45, 57, 12, 31, 12, 2, 64, 32, 20, 99, 1 }; int[] arr1 = { 2, 1, 3, 5, 4 };// {6,1,2,7,9,3,4,5,10,8}; // System.out.println(arr.getClass()); System.out.println(" arr before sorting: " + IntArrtoString(arr)); // BubbleSort(arr); // BubbleSort2(arr); // BubbleSort1_better(arr); // SelectSort(arr); // InsertionSort(arr); // ShellSort(arr); // ShellSort2(arr); // int[] quickSort = new Sort().QuickSort(arr, 0, arr.length - 1); // System.out.println(" quickSort after sorting: " + // IntArrtoString(quickSort)); int[] quickSort2 = new Sort().QuickSort2(arr, 0, 9); // System.out.println(" quickSort2 after sorting: " + // IntArrtoString(quickSort2)); System.out.println(" arr after sorting: " + IntArrtoString(arr)); } /** * @description 冒泡排序 * @param arr * @description : 两两比较,大的往后放; 每一次比较完成之后,下一次就少比较一个元素 * 第一次比较有0个元素不比较;第二次有一个元素不需要比较;第三次有两个元素不需要比较; * 共需要比较arr.length-1次 */ public static void BubbleSort(int[] arr) { int temp;// 临时变量 if (arr == null || arr.length == 0) return; for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。 for (int j = arr.length - 1; j > i; j--) { if (arr[j] < arr[j - 1]) { temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } } } } /** * @description 冒泡排序-2 * @param arr * */ public static void BubbleSort2(int[] arr) { int temp;// 临时变量 if (arr == null || arr.length == 0) return; for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。 for (int j = 0; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } /** * @description 冒泡排序-1-优化 * @param arr * * 针对问题:数据的顺序排好之后,冒泡算法仍然会继续进行下一轮的比较,直到arr.length-1次,后面的比较没有意义的。 * 方案: 设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。 * 这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。 * */ public static void BubbleSort1_better(int[] arr) { int temp;// 临时变量 boolean flag; if (arr == null || arr.length == 0) return; for (int i = 0; i < arr.length - 1; i++) { // 表示趟数,一共arr.length-1次。 flag = false; for (int j = arr.length - 1; j > i; j--) { if (arr[j] < arr[j - 1]) { temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } } if (!flag) break; } } /** * @description 选择排序 * @param arr * 在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换; * 第二次遍历n-2个数,找到最小的数值与第二个元素交换; 。。。 * 第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。 */ public static void SelectSort(int[] arr) { int len = arr.length; int temp;// 临时变量 if (arr == null || len == 0) return; for (int i = 0; i < len - 1; i++) { int minIndex = i;// 假定此时i位置元素为最小数值 for (int j = i + 1; j < arr.length; j++) { if (arr[j] < arr[minIndex]) { // 如果i+1后的元素值小于i位置的元素,那么改变minIndex值.当内层循环走完,此时数组最小值得小标就确定了 minIndex = j; } } if (minIndex != i) { // 最小值下标改变,交换元素 temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } } } /** * @description 插入排序 * @param arr * @description : 在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。 * 如此反复循环,直到全部排好顺序。 位于表中后面的元素依次与表中前面的元素比较,若比之小,则还需继续和更前面的元素比较, * 直至遇到一个比它大的元素或者比较到第一个元素(哨兵)了。 */ public static void InsertionSort(int[] arr) { int len = arr.length; int temp;// 临时变量 if (arr == null || len == 0) return; for (int i = 0; i < len - 1; i++) {
// 趟数n-1趟 for (int j = i + 1; j > 0; j--) { if (arr[j] < arr[j - 1]) { temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } else { break; } } } } /** * @description 希尔排序 (最小增量排序) * @param arr * @description: 我们选择增量gap=length/2,缩小增量继续以gap = * gap/2的方式,这种增量选择我们可以用一个序列来表示,{n /2,(n/2)/2...1},称为增量序列。 * 希尔排序的增量序列的选择与证明是个数学难题, 我们选择的这个增量序列是比较常用的,也是希尔建议的增量, * 称为希尔增量,但其实这个增量序列不是最优的。 此处我们做示例使用希尔增量。 * 比如原始数组8917235460,初始增量为gap =length/5;即数组被分为五组 * [8,3],[9,5],[1,4],[7,6],[2,0] ,对五组分别进行插入排序;第一次排序后: * 3514089472,缩小增量为gap =gap/2 = * 2;分为两组[3,5,1,4,0],[8,9,4,7,2],插入排序 -->[0214357698], * 再缩小增量gap = gap/ = 1,[0214357698] -->插入排序. * * */ public static void ShellSort(int[] array) { int temp = 0; int incre = array.length; while (true) { incre = incre / 2; for (int k = 0; k < incre; k++) { // 根据增量分为若干子序列 for (int i = k + incre; i < array.length; i += incre) { for (int j = i; j > k; j -= incre) { if (array[j] < array[j - incre]) { temp = array[j - incre]; array[j - incre] = array[j]; array[j] = temp; } else { break; } } } } if (incre == 1) { break; } } } /** * @description 希尔排序 (最小增量排序) * @param arr * 在希尔排序的理解时,我们倾向于对于每一个分组,逐组进行处理,但在代码实现中, * 我们可以不用这么按部就班地处理完一组再调转回来处理下一组( 这样还得加个for循环去处理分组)比如[5,4,3,2,1,0] * ,首次增量设gap=length/2=3,则为3组[5,2] [4,1] * [3,0],实现时不用循环按组处理,我们可以从第gap个元素开始,逐个跨组处理。同时,在插入数据时, * 可以采用元素交换法寻找最终位置, 也可以采用数组元素移动法寻觅。 * */ /** * 希尔排序 针对有序序列在插入时采用交换法 见图 * * @param arr */ public static void ShellSort2(int[] arr) { System.out.println("ShellSort2 start........."); // 增量gap,并逐步缩小增量 for (int gap = arr.length / 2; gap > 0; gap /= 2) { // 从第gap个元素,逐个对其所在组进行直接插入排序操作 System.out.println("1 gap:" + gap + " arr:" + IntArrtoString(arr)); for (int i = gap; i < arr.length; i++) { int j = i; while (j - gap >= 0 && arr[j] < arr[j - gap]) { // 插入排序采用交换法 swap(arr, j, j - gap); j -= gap; } System.out.println("2 gap:" + gap + " i:" + i + " arr:" + IntArrtoString(arr)); } } System.out.println("ShellSort2 end..........."); } /** * 希尔排序 针对有序序列在插入时采用移动法。 * * @param arr */ public static void ShellSort3(int[] arr) { // 增量gap,并逐步缩小增量 for (int gap = arr.length / 2; gap > 0; gap /= 2) { // 从第gap个元素,逐个对其所在组进行直接插入排序操作 for (int i = gap; i < arr.length; i++) { int j = i; int temp = arr[j]; if (arr[j] < arr[j - gap]) { while (j - gap >= 0 && temp < arr[j - gap]) { // 移动法 arr[j] = arr[j - gap]; j -= gap; } arr[j] = temp; } } } } /** * 交换数组元素 * * @param arr * @param a * @param b */ public static void swap(int[] arr, int a, int b) { arr[a] = arr[a] + arr[b]; arr[b] = arr[a] - arr[b]; arr[a] = arr[a] - arr[b]; } /** * @param arr * @description 快速排序 基本思想:(分治) 先从数列中取出一个数作为key值; * 将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边; 对左右两个小数列重复第二步,直至各区间只有1个数。 * @ses http://developer.51cto.com/art/201403/430986.htm * https://blog.csdn.net/morewindows/article/details/6684558 */ // 快速排序 public int[] QuickSort(int[] a, int l, int r) { if (l < r) { int i = l, j = r, v = a[l];// i:左边开始活动坐标,j:右边开始活动坐标,v:基数,用于对比的值,一般取第一个 while (i < j) {
// 只要左边游标和游标不重叠的话那么就继续遍历 System.out.println("i:" + i + " j:" + j + " arr:" + IntArrtoString(a)); // 每一轮遍历的时候只进行一轮,把右边的一个比基数小的数移动到左边,把左边比基数大的数移动到右边 while (i < j && a[j] > v) // 找出右边比左边小的坐标 j--; if (i < j) a[i++] = a[j];// 进行移动,左边坐标移动一个数 System.out.println("i:" + i + " j:" + j + " arr:" + IntArrtoString(a)); while (i < j && a[i] < v) // 找出左边比右边大的坐标 i++; if (i < j) a[j--] = a[i];// 进行移动,右边坐标移动一个数 System.out.println("i:" + i + " j:" + j + " arr:" + IntArrtoString(a)); } a[i] = v;// 当游标重叠时填入基数 this.QuickSort(a, l, i - 1); this.QuickSort(a, i + 1, r); return a; } return a; } /** * @param a * @param left * @param right * @return QuickSort2在一轮对比基准数的过程中不移动基准数,减少移动次数 */ public int[] QuickSort2(int[] a, int left, int right) { //校验要初始化变量之前;不校验易报错:java.lang.ArrayIndexOutOfBoundsException if (left>right ) { return a; } int i = left, j = right, s = a[left]; int temp; while (i < j) { //System.out.println("1--------i:" + i + " j:" + j + " arr:" + IntArrtoString(a)); while (a[j] >= s && j > i) { j--; //System.out.println("2--------i:" + i + " j:" + j + " arr:" + IntArrtoString(a)); } while (a[i] <= s && j > i) { i++; //System.out.println("3--------i:" + i + " j:" + j + " arr:" + IntArrtoString(a)); } if (i < j) { temp = a[j]; a[j] = a[i]; a[i] = temp; //System.out.println("4---------i:" + i + " j:" + j + " arr:" + IntArrtoString(a)); } } a[left] = a[i]; a[i] = s; QuickSort2(a, left, i - 1); QuickSort2(a, i + 1, right); return a; }}
你可能感兴趣的文章
大数据入门:Hive和Hbase区别对比
查看>>
大数据入门:ZooKeeper工作原理
查看>>
大数据入门:Zookeeper结构体系
查看>>
大数据入门:Spark RDD基础概念
查看>>
大数据入门:SparkCore开发调优原则
查看>>
大数据入门:Java和Scala编程对比
查看>>
大数据入门:Scala函数式编程
查看>>
Remove Duplicates from Sorted List II
查看>>
Spiral Matrix
查看>>
Sudoku Solver
查看>>
Bitwise AND of Numbers Range
查看>>
Happy Number
查看>>
Count Primes
查看>>
Isomorphic Strings
查看>>
Reverse Linked List
查看>>
Android面试题整理【转载】
查看>>
【opencv学习笔记】010之图像非线性滤波原理与操作(中值滤波、双边滤波)
查看>>
【opencv学习笔记】011之基本形态学操作(膨胀与腐蚀)
查看>>
【CryptoZombies - 1 Solidity 教程】010 msg.sender
查看>>
【opencv学习笔记】012之形态学操作(开闭操作,形态学梯度,顶帽与黑帽)
查看>>