java中标准的排序语句_java基础算法--排序大全

1 packagesorting;2

3 import java.util.*;4 //import java.util.Comparator;5 //import java.util.PriorityQueue;6 //import java.util.Queue;

7

8 public classSorting {9 /************************************序言**********************************************/

10 /**

11 * 排序方法:冒泡排序,插入排序,希尔排序,堆排序(2),归并排序(2),快排(2)...12 **/

13

14 /**

15 * 最小值函数16 **/

17 private static >AnyType min(AnyType a, AnyType b){18 if(a.compareTo(b) <= 0)19 returna;20 else

21 returnb;22 }23

24 /**

25 * 交换函数26 **/

27 private static > void swap(AnyType [] a, int m, intn){28 AnyType tmp =a[n];29 a[n] =a[m];30 a[m] =tmp;31 }32 /**********************************BubleSort*****************************************/

33 /**

34 * 冒泡排序:BubleSort35 * 每次内层循环最大的都被滤到最后36 **/

37 public static > voidbubleSort(AnyType [] a){38 for(int i=0;i 0){ //如果后一个数小于前一个数交换

41 AnyType tmp=a[j];42 a[j]=a[j+1];43 a[j+1]=tmp;44 }45 }46 }47 }48 /*************************SelectSort*************************************************/

49 /***50 * 选择排序:SelectSort51 * 每次内层循环最小的被滤到最前52 */

53 public static > voidselectSort(AnyType[] a) {54 intminIndex;55 for (int i = 0; i < a.length; i++) {56 minIndex =i;57 for (int j = i + 1; j < a.length; j++) {58 if ((a[j].compareTo(a[minIndex])) < 0) {59 minIndex =j;60 }61 }62 swap(a, i, minIndex);63 }64 }65

66 /*************************InsertionSort**********************************************/

67 /***68 * 插入排序:InsertionSort69 *@parama70 * 插入排序的实质是从a[1]~a[a.length-1]开始,逐个比较a[p](p=1,2,...,a.length-1)与a[j-1]的值,直至找到a[p]的位置。71 */

72 public static > voidinsertionSort(AnyType [] a){73 intj;74 for(int p = 1; p < a.length; p++){75 AnyType tmp = a[p]; //务必使用tmp变量,否则可能第一轮比较过后啊a[p]也即a[j]的值被覆盖

76 for(j = p; j > 0 && tmp.compareTo(a[j - 1])<0;j--){//等于就不挪了,省一次操作

77 a[j] = a[j-1];78 }79 a[j] =tmp;80

81 }82 }83 /*************************ShellSort**********************************************/

84 /**

85 * 希尔排序:ShellSort 最坏情形:O(N2)86 *@parama87 * 希尔排序(即间隔排序)的作用:对于间隔k,希尔排序即对k个独立的子数组的一次插入排序88 */

89 public static > voidshellSort(AnyType [] a){90 intj;91 for(int gap = a.length / 2; gap > 0; gap /= 2){92 //同时对k个子数组进行间隔排序,相当于和并单独子数组排序的两个for循环 for(int i=0;i

93 for(int i = gap;i < a.length;i++){94 //每个子数组的插入排序

95 AnyType tmp =a[i];96 for(j = i;j >= gap && tmp.compareTo(a[j-gap])<0;j-=gap){//等于就不挪了,省一次操作

97 a[j] = a[j-gap];98 }99 a[j] =tmp;100 }101 }102 }103 /*************************HeapSort**********************************************/

104 /**

105 * 堆排序:HeapSort1 最坏情形:O(Nlog(N)) 堆排序要比希尔排序要慢106 *@parama107 * 堆排序使用优先队列java.util.PriorityQueue实现108 */

109 public static > voidheapSort1(AnyType [] a){110 Comparator comparator = new Comparator(){111 public intcompare(AnyType left, AnyType right){112 returnleft.compareTo(right) ;113 }114 };115 Queue heap = new PriorityQueue(a.length,comparator);116 for(AnyType e:a){117 heap.add(e);118 }119 int i = 0;120 while(!heap.isEmpty()){121 a[i++] =heap.poll();122 }123 }124 /****************************************************************************************/

125 /**

126 * 堆排序:HeapSort2 最坏情形:O(Nlog(N))127 *@parama128 * 使用基础代码实现,建堆,排序129 */

130 /**

131 * 求左子节点132 **/

133 private static int leftChild(inti){134 return 2 * i + 1;135 }136 /**

137 * 下滤函数:deleteMin(deleteMax)时候使用138 * 对于大根堆下滤期间,大数被逐次滤上去(一步一步),小数被一直滤到它该到的位置(for结束后)139 *@parama 堆数组140 *@parami 开始下滤的起点141 *@paramn 堆的有效数组长度,随着不断deleteMax操作,堆中元素会不断减少,有效数组长度n也会逐渐减小142 */

143 private static > void percolateDown(AnyType[] a, int i, intn){144 int child;//左右子中较小的那个节点

145 AnyType tmp =a[i];146

147 for(; leftChild(i)< n; i = child){//leftChild(i)< n 判断是否到达最后一个叶子节点

148 child =leftChild(i);149 //如果只有一个左子节点,那么不必判断那个更大了

150 if(child != n-1 && a[child].compareTo( a[child + 1] ) < 0)//child!=n-1为了确定是否有两个子节点

151 child++;//将两个儿子中大的那个滤上去

152 if(tmp.compareTo( a[child]) < 0 ){//等于就不挪了,省一次操作

153 a[i]=a[child];//大数被逐次滤上去(一步一步)

154 }else

155 break;156 }157 a[i]=tmp;//小数被for一直滤下来

158 }159

160 /**

161 * 排序结果:升序 ,使用大根堆162 * 建立大根堆,deleteMin操作,得到排序数组163 * 下虑操作:在建立二叉堆和deleteMin中都有使用164 **/

165 public static > voidheapSort2(AnyType [] a){166 /*在无序数组上直接下滤建立大根堆167 * 从低向上开始下滤,即最后一个节点的父节点下滤即a[length/2]168 * 堆从数组索引0开始,因此左子节点为2*i+1,右子节点为2*i+2169 **/

170 for(int i = a.length/2; i >= 0; i--){171 percolateDown(a, i, a.length);172 }173 /*堆排序:不断deleteMax将堆中最大的元素放置于数组a的末端174 **/

175 for(int j = a.length-1; j >= 0; j--){176 //deleteMax

177 AnyType tmp =a[j];178 a[j] = a[0];179 //将队尾元素放置堆根处,开始下滤

180 a[0] =tmp;181 percolateDown(a, 0, j);//初始时刻j为a.length-1

182 }183 }184 /*************************MergeSort**********************************************/

185 /**

186 * 归并排序:MergeSort1 最坏运行时间O(Nlog(N)) 对空间有要求,线性内存 比较次数最少187 * 注意: 归并排序严重依赖于比较元素和数组中移动元素的相对开销,是语言相关的。188 * 其中:java中,执行一次泛型排序(Comparator)时 ,比较(不容易内嵌,动态调度)的的开销要大于移动元素(引用赋值);由于比较次数最少,是标准java类库中泛型排序所使用的算法。189 * 而 C++则相反,其泛型排序中如果对象庞大,拷贝对象开销大,比较相对省时。C++库中使用快速排序方法。190 *@parama191 * 实现方式:递归,本质就是一直讲待排序的数组二分下去,直至每一半均只有一个元素然后依次合并,完成排序。192 **/

193

194 /**

195 * 实际完成归并排序的过程的程序196 **/

197 private static > void merge(AnyType [] a, AnyType [] tmpArray, int leftPos, int rightPos, intrightEnd){198 int leftEnd = rightPos - 1;199 int tmpPos =leftPos;200 int numElements = rightEnd - leftPos + 1;201

202 while(leftPos <= leftEnd && rightPos <=rightEnd){203 if(a[leftPos].compareTo(a[rightPos]) <= 0)//等不等于都得拷贝

204 tmpArray[tmpPos++] = a[leftPos++];205 else

206 tmpArray[tmpPos++] = a[rightPos++];207 }208 while(leftPos <=leftEnd){209 tmpArray[tmpPos++] = a[leftPos++];210 }211 while(rightPos <=rightEnd){212 tmpArray[tmpPos++] = a[rightPos++];213 }214 for(int i = numElements; i >0; i--){215 a[rightEnd] =tmpArray[rightEnd];216 rightEnd--;//注意rightEnd要单独拿出来自减,否则在上个语句中会自减两次

217 }218 }219

220 /**

221 * 主递归程序222 **/

223 private static > void mergeSort(AnyType [] a, AnyType [] tmpArray, int left, intright){224 if(left

229 }230 }231

232 /**

233 * 归并排序驱动程序234 **/

235 public static > voidMergeSort1(AnyType [] a){236 AnyType [] tmpArray = (AnyType[]) newComparable[a.length];237 mergeSort(a, tmpArray, 0, a.length - 1);238 }239

240 /********************************************************************************/

241 /**

242 * 归并排序:MergeSort2 最坏运行时间O(Nlog(N))243 *@parama244 * 实现方式:非递归,从单个元素开始归并合成小组,然后小组之间归并直至归并成一个完整的数组,依旧使用MergeSort1使用的merge函数245 **/

246 public static > voidMergeSort2(AnyType [] a){247 int n =a.length;248 AnyType[] tmpArray = (AnyType[]) newComparable[n];249 for(int subList = 1; subList < n; subList *=2){250 int leftPos = 0;251 while(leftPos + subList

254 int rightEnd = min(n-1, rightPos + subList - 1); //一定要注意不能越界 min

255 merge(a, tmpArray, leftPos, rightPos, rightEnd);256 leftPos = rightEnd + 1; //等同于leftPos += 2 * subList;

257 }258 }259 }260 /*************************QuickSort**********************************************/

261 /**

262 * 快速排序:QuickSort1 平均运行时间:O(NlogN) 最坏运行时间:O(N2)263 * 使用三数中值分割法选取枢纽元264 * 由于对于小数组(N<=20),快速排序的递归会不如插入排序,因此该程序调用插入排序函数。截止范围CUTOFF=10265 **/

266

267

268 /**

269 * 三数中值分割法:取左端,右端,中心位置的三个元素的中值作为枢纽元270 * 实在值得注意的一点是:三数中值分割法有效的条件是left+2<=right(即至少要有三个元素)的时候才成立,对于2个及2个一下元素将会出现错误。271 * 排序后最小的将位于a[left],最大的位于a[right],枢纽元即中间值a[center]将被放置于a[right-1](亦即交换a[center]与a[right-1])272 * 这样在分隔阶段,i,j将从left+1和right-2开始比较273 * 三数中值分割法的好处:a[left]比枢纽元小,将作为j的警戒标记;而a[right-1]存放着枢纽元,则自然作为i的警戒标记。274 **/

275 private static > AnyType median3(AnyType [] a, int left, intright){276 int center = (left + right)/2;277 if(a[center].compareTo(a[left]) < 0)278 swap(a, center, left);279 if(a[right].compareTo(a[left]) < 0)280 swap(a, right, left);281 if(a[right].compareTo(a[center]) < 0)282 swap(a, right, center);283 //将枢纽元至于a[right - 1]的位置上

284 swap(a, center, right - 1);285 return a[right - 1];286 }287 /**

288 * 分割策略289 **/

290 private static > int partition(AnyType [] a, int left, intright){291 AnyType pivot =median3(a, left, right);292 //由于pivot放置在了a[right - 1]的位置(暂存pivot),因此i,j的取值应该为 left + 1,和right - 2

293 int i = left, j = right - 1;294 for(;;){295 //在遇到i,j处值都等于pivot时候停下,但是还得继续道,j

296 while(a[++i].compareTo(pivot) < 0){}//遇到跟pivot枢纽元值相等的值要停下,否则N2效率低下

297 while(a[--j].compareTo(pivot) > 0){}298 if(i

301 break;302 }303 //for(;;){304 //while(a[i].compareTo(pivot) < 0){i++;}305 //while(a[j].compareTo(pivot) > 0){j--;}306 //if(i < j){307 //swap(a, i, j);308 //i++;j--;309 //}310 //else311 //break;312 //}

313 swap(a, i, right - 1);314 returni;315 }316 /**

317 * 快速排序递归程序,主体程序,遇到跟pivot枢纽元值相等的值要停下318 * 前提条件:left+1

322 private static final int CUTOFF = 10;//CUTOFF>=2

323 private static > void qSort(AnyType [] a, int left, intright){324 //利用截止范围判断数据量

325 if(left + CUTOFF <=right){326 //获取枢纽元327 //AnyType pivot = median3(a, left, right);328 // //由于pivot放置在了a[right - 1]的位置(暂存pivot),因此i,j的取值应该为 left + 1,和right - 2329 //int i = left, j = right - 1;330 //for(;;){331 // //在遇到i,j处值都等于pivot时候停下,但是还得继续道,j 0){}334 //if(i < j)335 //swap(a, i, j);336 //else337 //break;338 //}339 //for(;;){340 //while(a[i].compareTo(pivot) < 0){i++;}341 //while(a[j].compareTo(pivot) > 0){j--;}342 //if(i < j){343 //swap(a, i, j);344 //i++;j--;345 //}346 //else347 //break;348 //}349 //因为i左边都比pivot小,i及i右边除了right-1除存放着pivot外都比pivot大,因此将i处值与right-1处值交换350 //即得到i左边都比其小,右边都比其大,i即pivot排序好的正确位置(换回pivot)351 //swap(a, i, right - 1);

352 int i =partition(a, left, right);353 //i已排好序

354 qSort(a, left, i - 1);355 qSort(a, i + 1, right);356 }else{357 insertionSort(a);//在这里处理了当CUTOFF等于1时的情景不会出错。当CUTOFF等于0时首先是不允许的(那样left就等于right了),其次这会导致median3()函数数组索引越界异常

358 }359 }360 /**

361 * 快速排序驱动程序362 **/

363 public static > voidquickSort(AnyType [] a){364 qSort(a, 0, a.length - 1);365 }366

367 /*********************************QuickSort2***************************************/

368 /**

369 * 分割策略370 **/

371 private static > int partition2(AnyType [] a, int start, intend){372 int i = start, j =end;373 AnyType base =a[start];374 while(i 0) && (j >i))376 j--;377 if(i

388 }//while

389 a[i] =base;390 returni;391 }392 /**

393 * 使用数组第一位作为枢纽元394 * 前提条件:start

396 private static > void qSort2(AnyType [] a, int start, intend){397 if(start 0) && (j > i))402 //j--;403 //if(i < j){404 //a[i] = a[j];405 //i++;//

406 //}407 //while((a[i].compareTo(base) < 0) && (i < j))408 //i++;409 //if(i < j){410 //a[j] = a[i];411 //j--;//

412 //}413 //

414 //}//while415 //a[i] = base;

416 int i =partition2(a, start, end);417

418 qSort2(a, start, i-1);419 qSort2(a, i+1, end);420 }421

422 }423 /**

424 * 驱动程序425 * 使用数组第一位作为枢纽元426 **/

427 public static > voidquickSort2(AnyType [] a){428 qSort2(a, 0, a.length-1);429 }430 /*********************************QuickSort3***************************************/

431 /**

432 * 三数中值分割的使用非递归的快速排序433 **/

434 public static > voidquickSort3(AnyType [] a){435 if(a==null||a.length<=0)return;436 Stack index=new Stack();437 int start=0;438 int end=a.length-1;439

440 intpivotPos;441

442 index.push(start);443 index.push(end);444

445 while(!index.isEmpty()){446 end=index.pop();447 start=index.pop();448 if(start+1

449 pivotPos=partition(a,start,end);450

451 if(startpivotPos+1){456 index.push(pivotPos+1);457 index.push(end);458

459 }460 }else{//三数中值必备

461 if(a[start].compareTo(a[end])>0)462 swap(a, start, end);463 }464 }465 }466 /*********************************QuickSort4***************************************/

467 /**

468 * 使用第一值为枢纽元的使用非递归的快速排序469 **/

470 public static > voidquickSort4(AnyType [] a){471 if(a==null||a.length<=0)return;472 Stack index=new Stack();473 int start=0;474 int end=a.length-1;475

476 intpivotPos;477

478 index.push(start);479 index.push(end);480

481 while(!index.isEmpty()){482 end=index.pop();483 start=index.pop();484 //if(start

485 pivotPos=partition2(a,start,end);486

487 if(startpivotPos+1){492 index.push(pivotPos+1);493 index.push(end);494

495 }496 //}

497 }498 }499

500 /*-----------------------------------------main-------------------------------------------------*/

501 public static voidmain(String[] args) {502 //TODO Auto-generated method stub

503 /**

504 * Test case: Sort the array.505 **/

506 //Integer[] a ={3,1,4,1,5,9,111,2,6,142,543,123,65,453,123,879,572,434,111,242,811,102};

507 Integer[] a ={3,1,4,1,5,9,2,6};508 System.out.println("Before sorting:");509 for(Integer i:a){510 System.out.print(i+",");511 }512 System.out.println();513

514 Sorting.quickSort4(a);//排序方法调用

515 System.out.println("After sorting:");516 for(Integer i:a){517 System.out.print(i+",");518 }519 System.out.println();520

521

522 }523

524 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值