Java排序算法(二)
java排序算法(二)
二、改进排序算法
2.1希尔排序
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
常用的h序列(增量)由Knuth提出,该序列从1开始,通过如下公式产生:h = 3 * h +1
反过来程序需要反向计算h序列,应该使用h=(h-1)/3
2.2快速排序
定义:快速排序(Quicksort)是对冒泡排序的一种改进,是一种非稳定排序。
快速排序通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
2.3归并排序
定义:归并排序(MergeSort)是建立在归并操作上的一种有效的排序算法,该算法是分治法的典型应用。是稳定排序。
归并排序假设初始序列(数据)有n个记录,看作n个子序列,每个子序列长度为一,然后进行两两归并,得到n/2个长度为2的子序列;让后再两两归并,...,重复操作,最后得到一个长度为n的有序序列,这种方法称为2路归并排序。
代码如下
1 public class Sort 2 { 3 //实现从小到大排序 4 public static void main(String[] args) 5 { 6 int[] arr1 = {9,1,5,8,3,7,4,6,2}; 7 //quickSort(arr1,0,8); 8 mergeSort(arr1); 9 //shellSort(arr1); 10 for(int i=0;i<arr1.length;i++) 11 { 12 System.out.println(arr1[i]); 13 } 14 } 15 /*---------------------------------希尔排序--------------------------------------------- 16 *希尔排序(缩小增量排序),对直接插入排序的改进 17 *通过加大插入排序中元素之间的间隔,并在这些有间隔的元素中进行插入排序,从而使数据项大框度的移动 18 *当这些数据项排过一趟序之后,希尔排序算法见效数据项的间隔再进行排序,依次进行下去 19 *哦爱心时的数据项之间的间隔被称为增量,习惯上用h表示 20 *常用h序列由Knuth剔除,序列从1开始,通过公式产生h=3*h+1; 21 *反过来程序反向计算h=(h-1)/3 22 ---------------------------------------------------------------------------------------*/ 23 public static void shellSort(int[] data) 24 { 25 int h=1; 26 while(h<=data.length/3) 27 { 28 h=h*3+1; 29 } 30 while(h>0) 31 { 32 for (int i = h; i < data.length; i += h) 33 { 34 if (data[i] < data[i - h]) 35 { 36 int tmp = data[i]; 37 int j = i - h; 38 while (j >= 0 && data[j] > tmp) 39 { 40 data[j + h] = data[j]; 41 j -= h; 42 } 43 data[j + h] = tmp; 44 //print(data); 45 } 46 } 47 // 计算出下一个h值(增量) 48 h = (h - 1) / 3; 49 } 50 } 51 /*---------------------------------快速排序--------------------------------------------- 52 -----------------------------------------------------------------------------------*/ 53 public static void quickSort(int[] arr,int low,int high) 54 { 55 if(low<high) 56 { 57 int mid = getMid(arr,low,high); 58 quickSort(arr,0,mid-1); //递归排序 59 quickSort(arr,mid+1,high); 60 } 61 } 62 //取中值 63 public static int getMid(int[] arr,int low,int high) 64 { 65 int key = arr[low]; //基准元素 66 while(low<high) 67 { 68 while(low<high&&arr[high]>=key) //从high开始找比基准小的元素,如果找到,则互换位置 69 { 70 high--; 71 } 72 arr[low] = arr[high]; 73 while(high>low&&arr[low]<=key) //从low开始找比基准大的,放到之前high空出的位置上 74 { 75 low++; 76 } 77 arr[high]=arr[low]; 78 } 79 arr[low]=key; //此时low=high是基准元素的位置,也是空出来的那个位置 80 return low; 81 } 82 83 /*--------------------------------归并排序------------------------------------ 84 -------------------------------------------------------------------------------*/ 85 public static void mergeSort(int[] data) 86 { 87 sort(data,0,data.length-1); 88 } 89 public static void sort(int[] data,int left,int right) 90 { 91 if(left>=right) 92 { 93 return; 94 } 95 int center = (left + right) / 2; // 找出中间索引 96 sort(data, left, center); // 对左边数组进行递归 97 sort(data, center + 1, right); // 对右边数组进行递归 98 merge(data, left, center, right); // 合并 99 } 100 /** 101 * 将两个数组进行归并,归并前面2个数组已有序,归并后依然有序 102 * 103 * @param data 数组对象 104 * @param left 左数组的第一个元素的索引 105 * @param center 左数组的最后一个元素的索引,center+1是右数组第一个元素的索引 106 * @param right 右数组最后一个元素的索引 107 */ 108 public static void merge(int[] data, int left, int center, int right) { 109 // 临时数组 110 int[] tmpArr = new int[data.length]; 111 // 右数组第一个元素索引 112 int mid = center + 1; 113 // third 记录临时数组的索引 114 int third = left; 115 // 缓存左数组第一个元素的索引 116 int tmp = left; 117 while (left <= center && mid <= right) { 118 // 从两个数组中取出最小的放入临时数组 119 if (data[left] <= data[mid]) { 120 tmpArr[third++] = data[left++]; 121 } else { 122 tmpArr[third++] = data[mid++]; 123 } 124 } 125 // 剩余部分依次放入临时数组(实际上两个while只会执行其中一个) 126 while (mid <= right) { 127 tmpArr[third++] = data[mid++]; 128 } 129 while (left <= center) { 130 tmpArr[third++] = data[left++]; 131 } 132 // 将临时数组中的内容拷贝回原数组中 133 // (原left-right范围的内容被复制回原数组) 134 while (tmp <= right) { 135 data[tmp] = tmpArr[tmp++]; 136 } 137 } 138 }