常用排序算法,java描述
来源:互联网 发布:神马软件 编辑:程序博客网 时间:2024/05/17 23:10
本文总结常见排序算法的java语言写法,希望加深自己对各个排序算法思路的理解,同时方便初学者阅览。
题目:
1. 冒泡排序
2. 插入排序
3. 选择排序
4. 快速排序
5. 希尔排序
6. 归并排序,递归与迭代
7. 堆排序
几种排序的算法的各种指标对比:
Arrays.sort()
方法底层对数组进行排序所采用的方法:
1. 基本数据类型数组进行排序采用的是快速排序
2. 对象类型数组采用的是归并排序
辅助方法:
//交换数组中指定的两个元素 public static void swap(int[] arr, int a, int b) { int tmp = arr[a]; arr[a] = arr[b]; arr[b] = tmp; }
1.冒泡排序
/** * 冒泡排序 * 平均和最坏时间复杂度O(n^2) * 最好时间复杂度O(n) * 稳定 */ public static int[] bubbleSort(int[] arr) { if(arr.length <= 1) return arr; //需要arr.length-1次循环,每一次循环找出当前循环中最大的数 for(int i = 0; i < arr.length-1; i++) { //每次找到的最大的数沉到最末尾以后不再比较这个数 for(int j = 0; j < arr.length-i-1; j++) { if(arr[j] > arr[j+1]) { swap(arr, j, j+1); } } } return arr; }
2.插入排序
/** * 插入排序 * 平均和最坏时间复杂度O(n^2) * 最好时间复杂度O(n) * 稳定 */ public static int[] insertSort(int[] arr) { if(arr.length <= 1) return arr; for(int i = 0; i < arr.length-1; i++) {// if(arr[i] > arr[i+1]) {// swap(arr, i, i+1); //如果当前比较的两个数需要交换,则交换后较小的数需要继续和前面的数比较 for(int j = i+1; j > 0; j--) { //j=i if(arr[j-1] > arr[j]) { swap(arr, j, j-1); } else break; }// } } return arr; }
3.选择排序
以下摘自知乎选择排序究竟属于稳定排序还是不稳定排序?
关于选择排序,有些书说是稳定的,有些书说是不稳定的.
在我看来,不同的实现方法有不同的结果.
如果是在数组中交换,那么就有可能不稳定,如{5,5,2}
如果是链表或者开一个新的数组,那么又是稳定的了.
在我看来选择排序应该属于不稳定排序,不管是用数组也好,链表也好,只是实现的方式不一样,选择排序算法里面包括了交换,即每次从未排序的数中选择最小的与未排序的第一个交换,破坏了相对顺序,所以不是稳定的排序。至于开一个新的数组,这样的排序貌似就变成了插入排序了,插入排序是一种稳定的排序算法。
/** * 选择排序 * 最好、最坏、平均时间复杂度都是O(n^2) * 稳定 */ public static int[] selectSort(int[] arr) { if(arr.length <= 1) return arr; for(int i = 0; i < arr.length-1; i++) { //每次循环固定最前面的一个数 //每次循环都取第一个元素与后面所有元素比较,如果有比第一个元素小的就交换, //再用这个小的继续与后面的元素比较 for(int j = i+1; j < arr.length; j++) { if(arr[i] > arr[j]) { swap(arr, i, j); } } } return arr; }
4.快速排序
/** * 快速排序 * 利用递归的思想 * 最好、平均时间复杂度O(nlogn),最差时间复杂度O(n^2) * 不稳定 */ public static int[] QuickSort(int[] arr) { return QSort(arr, 0, arr.length-1); } private static int[] QSort(int[] arr, int low, int high) { int mid; if(low < high) { mid = partition(arr, low, high); QSort(arr, low, mid-1); //对低子表递归排序 QSort(arr, mid+1, high); //对高子表递归排序 } return arr; } private static int partition(int[] arr, int low, int high) { int pivotkey = arr[low]; //用子表的第一个值作为枢轴值 while (low < high) { //从表的两端交替向中间扫描 while (low < high && arr[high] >= pivotkey) high--; swap(arr, low, high); //将比枢轴小的数据交换到低端 while (low < high && arr[low] <= pivotkey) low++; swap(arr, low, high); //将比枢轴大的数据交换到高端 } return low; //返回枢轴所在位置 }
5.希尔排序
/** * 希尔排序 * 平均时间复杂度O(nlogn)~O(n^2) * 最好时间复杂度O(n^1.3) * 最坏时间复杂度O(n^2) * 不稳定 */ public static int[] shellSort(int[] arr) { int i, j; int increment = 0; while (increment < arr.length/3) { increment = increment * 3 + 1; } for (; increment > 0; increment/=3) { for(i = increment; i < arr.length; i++) { int tmp = arr[i]; for(j = i-increment; j >= 0 && tmp < arr[j]; j -= increment) { arr[j+increment] = arr[j]; } arr[j+increment] = tmp; } } return arr; }
6.归并排序
/** * 归并排序,递归解法 * 时间复杂度O(nlogn) * 空间复杂度O(n) * 稳定 */ public static int[] MergeSort(int[] arr) { if(arr.length <= 1) { return arr; } return MSort(arr, 0, arr.length-1); } private static int[] MSort(int[] arr, int start, int end) { if(arr.length <= 1) { return arr; } if(start >= end) { return arr; } int mid = (start + end)/2; int start2 = mid+1; MSort(arr, start, mid); //递归归并前半段序列 MSort(arr, start2, end); //递归归并后半段序列 //将前面排好序的两段序列合并 int[] tmp = new int[arr.length]; //辅助空间,存放排好序的序列 int index = start; int temp = start; //保存序列初始值 while (start <= mid && start2 <= end) { //两个指针同时往后走,较小的先走 if(arr[start] <= arr[start2]) { tmp[index++] = arr[start++]; } else { tmp[index++] = arr[start2++]; } } //如果前半段序列还没有走到最后,证明后面的数都比前面的数大,直接复制到辅助空间中 while (start <= mid) { tmp[index++] = arr[start++]; } //原理同上 while (start2 <= end) { tmp[index++] = arr[start2++]; } //将两个有序序列重新合并成一个有序序列后再存回数组中 for (int i = temp; i < end+1; i++) { arr[i] = tmp[i]; } return arr; }
/** * 归并排序,迭代解法 */ public static int[] mergeSort2(int[] arr) { if(arr.length <= 1) { return arr; } int window = 1; int[] tmp = new int[arr.length]; for (; window < arr.length; window*=2) { for(int start = 0; start < arr.length; start += 2*window) { int start1 = start; int end1, end2; if(start1+window < arr.length) { end1 = start1+window; } else { end1 = arr.length; } int start2 = end1; if(start1+2*window < arr.length) { end2 = start1+2*window; } else { end2 = arr.length; } int index = start1; while (start1 < end1 && start2 < end2) { if(arr[start1] < arr[start2]) { tmp[index++] = arr[start1++]; } else { tmp[index++] = arr[start2++]; } } while (start1 < end1) { tmp[index++] = arr[start1++]; } while (start2 < end2) { tmp[index++] = arr[start2++]; } for(int i = start; i < end2; i++) { arr[i] = tmp[i]; } } } return arr; }
7.堆排序
/** * 堆排序 * 时间复杂度O(nlogn) * * 二叉堆的数组从下标1开始存储,而不是0,若当前节点为i,则左子节点为2i,右子节点为2i+1,父节点为i/2 * * 思路: * 1、构建大顶堆maxHeap(下标从0开始,所以和二叉堆有细微差别,节点i的左子节点为2i+1) * 2、大顶堆的0位置元素显然是最大的,将这个数沉到数组最末端 * 3、重复步骤1、2 */ public static int[] heapSort(int[] arr) { if(arr.length <= 1) { return arr; } for (int i = 0; i < arr.length; i++) { maxHeap(arr, arr.length-1-i); swap(arr, 0, arr.length-1-i); } return arr; } //构建大顶堆 public static void maxHeap(int[] arr, int lastIndex) { for (int i = (lastIndex-1)/2; i >= 0; i--) { int k = i; //保存当前正在判断节点的索引 //如果当前节点存在子节点(判断依据是其左子节点索引在lastIndex范围内) while (2*k+1 <= lastIndex) { int biggerIndex = 2*k + 1; //biggerIndex总是记录值较大的节点的索引,初始值为左子节点索引 if(biggerIndex < lastIndex) { //如果右子节点存在,否则会有biggerIndex=lastIndex if(arr[biggerIndex] < arr[biggerIndex+1]) { //如果右子节点比左子节点的值大,则biggerIndex记录的是右子节点的索引 biggerIndex++; } } if(arr[k] < arr[biggerIndex]) { //如果当前节点值小于其所有子节点中值最大的那个值,那么交换,//将当前节点索引设置为biggerIndex swap(arr, k, biggerIndex); k = biggerIndex; } else break; } } }
0 0
- 常用排序算法,java描述
- 常用排序算法(C描述)
- java常用排序算法
- Java 常用排序算法
- java常用排序算法
- java常用排序算法
- java 常用排序算法
- 常用Java排序算法
- Java常用排序算法
- Java常用排序算法
- Java常用排序算法
- Java 常用排序算法
- java常用排序算法
- java常用排序算法
- java 常用排序算法
- java常用排序算法
- Java常用排序算法
- Java常用排序算法
- 安装完MySQL数据库,在服务列表里找不到MySQL的解决办法
- Hadoop伪分布式安装(Centos7)
- SAP HANA SLT在表中隐藏字段并传入HANA的方法
- HDU 2078复习时间
- Python3的列表list和元组tuple初学总结(未完)
- 常用排序算法,java描述
- 18.输入和输出函数
- 5种创建型模式之:原型模式(Prototype)
- 三大框架面试题
- Python入门教程(一)Python简介
- java
- iOS多线程网络之GCD进阶
- Spring依赖注入之@Inject,@Autowired,@Resource
- 1046. Shortest Distance (20)