排序算法
参考:http://easense2009.iteye.com/blog/1568614
http://www.cnblogs.com/morewindows/archive/2011/08/13/2137415.html
http://www.cnblogs.com/morewindows/archive/2011/08/13/2137415.html
1 package com.test; 2 3 public class Sort { 4 public static void main(String[] args) { 5 Sort p = new Sort(); 6 p.Sort_Quick(p.array, 0, p.array.length); 7 p.print(p.array); 8 9 } 10 11 public int[] array = { 3, 2, 19, 7, 6, 20 }; 12 13 public void print(int[] array) { 14 for (int i = 0; i < array.length; i++) { 15 System.out.print(array[i] + ","); 16 } 17 System.out.println(); 18 } 19 20 /*** 21 * 选择排序的基本思想是遍历数组的过程中,以 i 代表当前需要排序的序号,则需要在剩余的 [i…n-1] 中找出其中的最小值,然后将找到的最小值与 i 22 * 指向的值进行交换。因为每一趟确定元素的过程中都会有一个选择最大值的子流程,所以人们形象地称之为选择排序。 23 * 24 * @param array 25 * @return 26 */ 27 public int[] Sort_xuanze(int[] array) { 28 for (int i = 0; i < array.length; i++) { 29 for (int j = i + 1; j < array.length; j++) { 30 if (array[i] > array[j]) { 31 int tmp = array[j]; 32 array[j] = array[i]; 33 array[i] = tmp; 34 } 35 } 36 } 37 return array; 38 } 39 40 /*** 41 * 冒泡排序可以算是最经典的排序算法了,记得小弟上学时最先接触的也就是这个算法了,因为实现方法最简单,两层 for 42 * 循环,里层循环中判断相邻两个元素是否逆序 43 * ,是的话将两个元素交换,外层循环一次,就能将数组中剩下的元素中最小的元素“浮”到最前面,所以称之为冒泡排序。 44 * 45 * 大值元素放后边 46 * 47 * @param array 48 * @return 49 */ 50 public int[] Sort_maopao(int[] array) { 51 for (int i = 0; i < array.length; i++) {// 次数 52 for (int j = 0; j < array.length - i - 1; j++) {// 两两比较大的放后边 53 int a1 = array[j]; 54 int a2 = array[j + 1]; 55 if (a1 > a2) { 56 int tmp = array[j]; 57 array[j] = array[j + 1]; 58 array[j + 1] = tmp; 59 } 60 } 61 } 62 return array; 63 } 64 65 /*** 66 * 插入排序的基本思想是在遍历数组的过程中,假设在序号 i 之前的元素即 [0..i-1] 都已经排好序,本趟需要找到 i 对应的元素 x 的正确位置 67 * k ,并且在寻找这个位置 k 的过程中逐个将比较过的元素往后移一位,为元素 x “腾位置”,最后将 k 对应的元素值赋为 x 68 * ,插入排序也是根据排序的特性来命名的。 69 * 70 * @param array 71 * @return 72 */ 73 public int[] Sort_Insert(int[] array, int start, int len) { 74 for (int i = start + 1; i < len; i++) { 75 int k = -1; 76 for (int j = start; j < i; j++) { 77 if (array[i] < array[j]) { 78 k = j; 79 break; 80 } 81 } 82 // k为插入位置 83 if (k >= 0) {// 移位 84 int tmp = array[i]; 85 for (int p = i - 1; p >= k; p--) { 86 array[p + 1] = array[p]; 87 } 88 array[k] = tmp; 89 } 90 91 } 92 return array; 93 } 94 95 /*** 96 * 希尔排序的诞生是由于插入排序在处理大规模数组的时候会遇到需要移动太多元素的问题。希尔排序的思想是将一个大的数组“分而治之”,划分为若干个小的数组, 97 * 以 gap 来划分,比如数组 [1, 2, 3, 4, 5, 6, 7, 8] ,如果以 gap = 2 来划分,可以分为 [1, 3, 5, 98 * 7] 和 [2, 4, 6, 8] 两个数组(对应的,如 gap = 3 ,则划分的数组为: [1, 4, 7] 、 [2, 5, 8] 、 99 * [3, 6] )然后分别对划分出来的数组进行插入排序,待各个子数组排序完毕之后再减小 gap 值重复进行之前的步骤,直至 gap = 1 100 * ,即对整个数组进行插入排序,此时的数组已经基本上快排好序了,所以需要移动的元素会很小很小,解决了插入排序在处理大规模数组时较多移动次数的问题。 101 * 102 * @param array 103 * @return 104 */ 105 public int[] Sort_xier(int[] array) { 106 int gap = 1; 107 while (gap < array.length / 3) { 108 gap = gap * 3 + 1; 109 } 110 while (gap >= 1) { 111 int num = array.length / gap; 112 for (int i = 0; i < gap; i++) { 113 int len = num; 114 if (i == gap - 1) { 115 len = array.length - num * i; 116 } 117 Sort_Insert(array, num * i, len); 118 } 119 gap = gap / 3; 120 } 121 return array; 122 } 123 124 /*** 125 * 归并排序采用的是递归来实现,属于“分而治之”,将目标数组从中间一分为二,之后分别对这两个数组进行排序,排序完毕之后再将排好序的两个数组“归并” 126 * 到一起, 127 * 128 * @param array 129 * @param start 130 * @param len 131 */ 132 public void Sort_digui(int[] array, int start, int len) { 133 if (len <= 1) { 134 return; 135 } 136 int mid = start + len / 2; 137 int len1 = len / 2; 138 int len2 = len - len / 2; 139 Sort_digui(array, start, len1);// 前面排序 140 Sort_digui(array, mid, len2);// 后面排序 141 // 合并 142 int[] array1 = new int[array.length]; 143 System.arraycopy(array, 0, array1, 0, array.length); 144 145 int i = 0; 146 int j = 0; 147 int l = 0; 148 while (i < len1 || j < len2) { 149 if (i < len1 && j < len2) { 150 if (array1[start + i] > array1[mid + j]) { 151 array[start + l] = array1[mid + j]; 152 j++; 153 } else { 154 array[start + l] = array1[start + i]; 155 i++; 156 } 157 } else if (i < len1) { 158 array[start + l] = array1[start + i]; 159 i++; 160 } else if (j < len2) { 161 array[start + l] = array1[mid + j]; 162 j++; 163 } 164 l++; 165 } 166 167 } 168 169 /*** 170 * 快速排序方法的基本思想是: 171 * <p> 172 * 1.先从数列中取出一个数作为基准数。 173 * <p> 174 * 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。 175 * <p> 176 * 3.再对左右区间重复第二步,直到各区间只有一个数。 177 * <p> 178 * 179 * @param array 180 */ 181 public void Sort_Quick(int[] array, int start, int len) { 182 if (len <= 1) { 183 return; 184 } 185 // 186 int[] array1 = new int[array.length]; 187 System.arraycopy(array, 0, array1, 0, array.length); 188 189 // 放入cur 190 int curValue = array[start]; 191 int cur = start; 192 int lenPaixu = 1; 193 //开始排序 194 for (int i = start + 1; i < start+len; i++) { 195 if (array1[i] <= curValue) {// 小于cur的 放入cur左边(start 位置) 196 for (int j = start + lenPaixu - 1; j >= start; j--) { 197 array[j + 1] = array[j]; 198 } 199 array[start] = array1[i]; 200 cur++; 201 } else { 202 array[start+lenPaixu] = array1[i]; 203 } 204 lenPaixu++; 205 } 206 207 Sort_Quick(array, start, cur-start); 208 Sort_Quick(array, cur+1, len-(cur-start)-1); 209 210 } 211 212 }