java八大排序算法实现
2015-10-13 15:30
405 查看
import java.util.Arrays; public class Sort { //排序为从小到大序列 /** * 冒泡排序:一趟一趟的比较,比较相邻元素的大小,每趟有一个元素沉入最后面的位置 * 属于交换类排序 * 稳定的排序算法 * 平均时间复杂度O(n*n) * 最坏时间复杂度O(n*n) * 空间复杂度O(1) * n较小时适用 */ public static void bubbleSort(int[] array, int off, int len) { System.out.println("BubbleSort()"); for (int i=1; i<len; i++ ) {//第i趟比较 boolean isSorted = true;//检测是否有交换 for (int j=off; j<off+len-i ; j++){ if (array[j+1]<array[j]){ swap(array, j, j+1); isSorted = false;//有交换 } } if (isSorted == true)//无交换跳出循环,完成排序 break; } } /** * 直接插入排序:每一轮第i个元素跟前面的i-1个元素从后向前比较,一直比较到合适插入的位置 * 属于插入类排序 * 稳定的排序算法 * 平均时间复杂度O(n*n) * 最坏时间复杂度O(n*n) * 空间复杂度O(1) * 大部分有序时适用 */ public static void insertSort(int[] array, int off, int len) { System.out.println("InsertSort()"); int i,j,current;//current记录当前插入元素 for (i=off+1; i<off+len; i++) {//array[i]待插入元素,j为比较元素的下标 for (j=i-1, current = array[i]; j>=off && array[j]>current; j--) { array[j+1] = array[j]; } array[j+1] = current; } } /** * 直接选择排序:第i轮选择剩余最小的元素放入到第i的位置上 * 属于选择类排序 * 不稳定的排序算法 :如58529第一轮选择交换5和2,破换了原来两个5的顺序 * 平均时间复杂度O(n*n) * 最坏时间复杂度O(n*n) * 空间复杂度O(1) * 当n较小时适用 */ public static void selectSort(int[] array, int off, int len) { for (int i=off; i<off+len-1; i++) { int minIndex = i, min = array[i];//最小元素及下标 for(int j=i; j<off+len; j++) {//j为所有待选择元素 if (array[j] < min) {//array[j]更小 min = array[j]; minIndex = j; } } swap(array, minIndex, i);//选择最小元素放入array[i] } } /** * 快速排序:递归算法,将较大的一组换到后面去,较小的一组在前面,前面和后面的分别再递归调用 * 属于交换类排序 * 不稳定的排序算法 :如35512第一轮时前面的5和后面的2换位置,后面的5和1换位置,位置顺序被破坏 * 平均时间复杂度O(n*log2n) * 最坏时间复杂度O(n*n) * 空间复杂度O(1) * n较大 时适用 */ public static void quickSort(int[] array, int off, int len) { if (len <= 1) return; if (len == 2)//长度大于三才进行划分 if (array[off] > array[off+1]){ swap(array, off, off+1); return; } int start = off + 1, end = off + len - 1;//交换的开始和结束位置 int middleV = array[off];//可以将off和 off+len-1和off+(len-1)/2三个元素中间的赋值 while(start < end) { while (array[start] < middleV && start < end) start++; while (array[end] > middleV && end > start) end--; if (start < end) { swap(array, start, end); start++; end--; } } int mid = off; if (array[off] > array[end]){ swap(array, end, off); mid = end;} quickSort(array, off, mid-off); quickSort(array, mid+1, len-mid+off-1); } /** * 希尔排序:分组交换的思想,先分组,后交换排序 * 属于交换类排序 * 不稳定的排序算法 :分组之后交换打破了稳定性 * 平均时间复杂度O(n*log2n) * 最坏时间复杂度O(n^s) 1<s<2 * 空间复杂度O(1) * n较大时适用 */ public static void shellSort(int[] array, int off, int len){ int d = len / 2;//组内元素的间隔 while(d >= 1) {//直到退化到bubble为止 shellSortDivision(d,array, off, len); d /= 2; } } private static void shellSortDivision(int d, int[] array, int off, int len) { // TODO Auto-generated method stub for (int i = 0; i < d ; i++) {//第i个分组 for (int j=1; j<=(len-1-i)/d; j++) {//分组内bubble boolean isSorted = true; for(int k=off+i; k+d<=off+len-(j-1)*d-1; k+=d){ if (array[k] > array[k+d]) { swap(array, k, k+d); isSorted = false; } } if (isSorted == true) break; } } } /** * 归并算法:分而治之的思想 * 属于归并类排序 * 稳定的排序算法 * 平均时间复杂度O(n*log2n) * 最坏时间复杂度O(n*log2n) * 空间复杂度O(n) * n较大时适用 */ public static void MergeSort(int[] array, int off, int len) { if (len < 2) return; else if (len == 2){ if (array[off] > array[off+1]) swap(array, off, off+1); return; } else { int middle = off + (len-1)/2; MergeSort(array, off, middle-off+1); MergeSort(array, middle+1, len-middle+off-1); Merge(array,off,middle,off+len-1); } } public static void Merge(int[] array, int left, int middle, int right) { int l = left, r = middle+1, count = 0; int[] newArray = new int[right-left+1]; while(l <= middle && r <= right) { if (array[l] < array[r]) newArray[count++] = array[l++]; else newArray[count++] = array[r++]; } while (l <= middle) newArray[count++] = array[l++]; while (r <= right) newArray[count++] = array[r++]; for(int i=left,j=0; i<=right; i++) { array[i] = newArray[j++]; } // array = newArray; } /** * 堆算法:大根堆a[i] > a[2*i],a[i] > a[2*i+1],先建大根堆,然后不断的:取最大的,调整 * 属于选择类排序 * 不稳定的排序算法:在调整位置时打破了稳定性 * 平均时间复杂度O(n*log2n) * 最坏时间复杂度O(n*log2n) * 空间复杂度O(1) * n较大时适用,选择前i大时适用 */ public static void heapSort(int[] array, int off, int len) { buildHeap(array,off, len); for (int i = 0;i < len; i++) { swap(array,off,off+len-i-1);//将大根堆最大元素与最后面的位置做交换 shiftDown(array, off, len-i-1, 0);//始终调整第一个元素 } } private static void buildHeap(int[] array, int left, int len) { int pos= len/2 - 1;//从第一个非叶子节点开始 for(int i=pos;i>=0;i--) { shiftDown(array,left,len,i); //调整第i个非叶子节点 } } private static void shiftDown(int[] array, int left, int len, int pos) { // TODO Auto-generated method stub int tmp = array[left+pos]; int indexLC = pos*2 + 1, index;//左孩子 while(indexLC < len) {//判断孩子是否存在 if (indexLC+1 < len && array[left+indexLC]<array[left+indexLC+1]) index = indexLC + 1;//右孩子大 else index = indexLC;//左孩子大 if(tmp < array[left+index]) {//交换 array[left+pos] = array[left+index]; pos = index;//交换后大值继续跟孩子比较 indexLC = pos*2 + 1; }else break; } array[left+pos] = tmp;//跟目标交换完成 } /** * 基数排序 * 稳定的排序算法 * 最差时间复杂度是 O(k·n) * 空间复杂度O(k·n) * 多个刻度指标时适用 * @param array * @param radix 基数 * @param distance 几遍 */ private static void radixSort(int[] array,int radix, int distance) { //array为待排序数组 //radix,代表基数 //代表排序元素的位数 int length = array.length; int[] temp = new int[length];//用于暂存元素 int[] count = new int[radix];//用于统计基数内元素个数 int divide = 1; for (int i = 0; i < distance; i++) { System.arraycopy(array, 0,temp, 0, length); Arrays.fill(count, 0); for (int j = 0; j < length; j++) { int tempKey = (temp[j]/divide)%radix; count[tempKey]++; //基数选中计数 } for (int j = 1; j < radix; j++) { count [j] = count[j] + count[j-1];//累计计数 } for (int j = length - 1; j >= 0; j--) { int tempKey = (temp[j]/divide)%radix; count[tempKey]--;//从后往前赋值 array[count[tempKey]] = temp[j]; } divide = divide * radix; } } //交换两个元素 private static void swap(int[] array, int a, int b) { int t = array[a]; array[a] = array[b]; array[b] = t; } //打印数组 private static void printArray(String s, int[] array, int off, int len) { System.out.print(s); for(int i=off; i<off+len; i++) { if (i == off) System.out.print("[" + array[i] + ","); else if (i == off+len-1) System.out.print(array[i]); else System.out.print(array[i] + ","); } System.out.println("]"); } private static int getMiddleIndexOfThreeElement(int[] array,int a, int b, int c) { if (array[a] < array[b]) { if (array[b] < array[c]) return b; else if (array[c] < array[a]) return a; else return c; }else { if (array[a] < array[c]) return a; else if (array[c] < array[b]) return b; else return c; } } public static int getMiddle(int[] list, int low, int high) { int tmp = list[low]; //数组的第一个作为中轴 while (low < high) { while (low < high && list[high] > tmp) { high--; } list[low] = list[high];//比中轴小的记录移到低端 while (low < high && list[low] <= tmp) { low++; } list[high] = list[low]; //比中轴大的记录移到高端 } list[low] = tmp; //中轴记录到尾 return low; //返回中轴的位置 } public static void quickSort2(int[] array, int low, int high) { if (low < high) { int middle = getMiddle(array, low, high); //将list数组进行一分为二 quickSort2(array, low, middle - 1); //对低字表进行递归排序 quickSort2(array, middle + 1, high); //对高字表进行递归排序 } }
相关文章推荐
- java.lang.OutOfMemoryError: PermGen space
- 运行Java的基础
- 通过java api 读取sql 中数据(查询)
- java中接口的定义与实现
- 在java中实现access数据库的远程访问
- java入门第一季2
- spring学习笔记---第三方SDK(Rest API)和Jaskson的巧用
- java匿名类
- [leetcode-44]Wildcard Matching(java)
- Java读写大文本文件(2GB以上)
- java 线程池
- javaEE学习笔记【03】XML操作
- Spring mvc 将请求后缀改成.htm 后ajax无法返回json的问题
- Struts2.2.1简单配制
- Eclipse/MyEclipse 添加src JAVA DOC XML提示
- Eclipse使用Maven构建web项目
- java参数的传递方式
- JAVA中处理ASCII 160 的char
- Spring security oauth2最简单入门环境搭建--二、干货
- Spring security oauth2最简单入门环境搭建--一、OAuth简介