java基础算法--排序大全

  1 package sorting;
  2
  3 import java.util.*;
  4 //import java.util.Comparator;
  5 //import java.util.PriorityQueue;
  6 //import java.util.Queue;
  7
  8 public class Sorting {
  9     /************************************序言**********************************************/
 10     /**
 11      * 排序方法:冒泡排序,插入排序,希尔排序,堆排序(2),归并排序(2),快排(2)...
 12      * */
 13
 14     /**
 15      * 最小值函数
 16      * */
 17     private static <AnyType extends Comparable<? super AnyType>> AnyType min(AnyType a, AnyType b){
 18         if(a.compareTo(b) <= 0)
 19             return a;
 20         else
 21             return b;
 22     }
 23
 24     /**
 25      * 交换函数
 26      * */
 27     private static <AnyType extends Comparable<? super AnyType>> void swap(AnyType [] a, int m, int n){
 28         AnyType tmp = a[n];
 29         a[n] = a[m];
 30         a[m] = tmp;
 31     }
 32     /**********************************BubleSort*****************************************/
 33     /**
 34      * 冒泡排序:BubleSort
 35      * 每次内层循环最大的都被滤到最后
 36      * */
 37     public static <AnyType extends Comparable<? super AnyType>> void bubleSort(AnyType [] a){
 38         for(int i=0;i<a.length;i++){
 39             for(int j=0;j<a.length-1-i;j++){
 40                 if(a[j].compareTo(a[j+1]) > 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      * 选择排序:SelectSort
 51      * 每次内层循环最小的被滤到最前
 52      */
 53      public static <AnyType extends Comparable<? super AnyType>> void selectSort(AnyType[] a) {
 54             int minIndex;
 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      * 插入排序:InsertionSort
 69      * @param a
 70      * 插入排序的实质是从a[1]~a[a.length-1]开始,逐个比较a[p](p=1,2,...,a.length-1)与a[j-1]的值,直至找到a[p]的位置。
 71      */
 72     public static <AnyType extends Comparable<? super AnyType>> void insertionSort(AnyType [] a){
 73         int j;
 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      * @param a
 87      * 希尔排序(即间隔排序)的作用:对于间隔k,希尔排序即对k个独立的子数组的一次插入排序
 88      */
 89     public static <AnyType extends Comparable<? super AnyType>> void shellSort(AnyType [] a){
 90         int j;
 91         for(int gap = a.length / 2; gap > 0; gap /= 2 ){
 92             //同时对k个子数组进行间隔排序,相当于和并单独子数组排序的两个for循环 for(int i=0;i<gap;i++){for(int p=i;i<a.length;p+=gap){}}
 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      * @param a
107      * 堆排序使用优先队列java.util.PriorityQueue实现
108      */
109     public static <AnyType extends Comparable<? super AnyType>> void heapSort1(AnyType [] a){
110         Comparator<AnyType> comparator = new Comparator<AnyType>(){
111             public int compare(AnyType left, AnyType right){
112                 return left.compareTo(right) ;
113              }
114         };
115         Queue<AnyType> heap = new PriorityQueue<AnyType>(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      * @param a
128      * 使用基础代码实现,建堆,排序
129      */
130     /**
131      * 求左子节点
132      * */
133     private static int leftChild(int i){
134         return 2 * i + 1;
135     }
136     /**
137      * 下滤函数:deleteMin(deleteMax)时候使用
138      * 对于大根堆下滤期间,大数被逐次滤上去(一步一步),小数被一直滤到它该到的位置(for结束后)
139      * @param a 堆数组
140      * @param i 开始下滤的起点
141      * @param n 堆的有效数组长度,随着不断deleteMax操作,堆中元素会不断减少,有效数组长度n也会逐渐减小
142      */
143      private static <AnyType extends Comparable<? super AnyType>> void percolateDown(AnyType[] a, int i, int n){
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 <AnyType extends Comparable<? super AnyType>> void heapSort2(AnyType [] a){
166         /*  在无序数组上直接下滤建立大根堆
167          *  从低向上开始下滤,即最后一个节点的父节点下滤即a[length/2]
168          *  堆从数组索引0开始,因此左子节点为2*i+1,右子节点为2*i+2
169          *  */
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      * @param a
191      * 实现方式:递归,本质就是一直讲待排序的数组二分下去,直至每一半均只有一个元素然后依次合并,完成排序。
192      * */
193
194     /**
195      * 实际完成归并排序的过程的程序
196      * */
197     private static <AnyType extends Comparable<? super AnyType>> void merge(AnyType [] a, AnyType [] tmpArray, int leftPos, int rightPos, int rightEnd){
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 <AnyType extends Comparable<? super AnyType>> void mergeSort(AnyType [] a, AnyType [] tmpArray, int left, int right){
224         if(left < right){
225             int center = (left + right)/2;
226             mergeSort(a, tmpArray, left, center);
227             mergeSort(a, tmpArray, center + 1, right);
228             merge(a, tmpArray, left, center + 1, right);//实际完成排序过程
229         }
230     }
231
232     /**
233      * 归并排序驱动程序
234      * */
235     public static <AnyType extends Comparable<? super AnyType>> void MergeSort1(AnyType [] a){
236         AnyType [] tmpArray = (AnyType[]) new Comparable[a.length];
237         mergeSort(a, tmpArray, 0, a.length - 1);
238     }
239
240     /********************************************************************************/
241     /**
242      * 归并排序:MergeSort2  最坏运行时间O(Nlog(N))
243      * @param a
244      * 实现方式:非递归,从单个元素开始归并合成小组,然后小组之间归并直至归并成一个完整的数组,依旧使用MergeSort1使用的merge函数
245      * */
246     public static <AnyType extends Comparable<? super AnyType>> void MergeSort2(AnyType [] a){
247         int n = a.length;
248         AnyType[] tmpArray = (AnyType[]) new Comparable[n];
249         for(int subList = 1; subList < n; subList *=2){
250             int leftPos = 0;
251             while(leftPos + subList < n){
252                 int rightPos = leftPos + subList;
253 //                int leftEnd = rightPos - 1;
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=10
265      * */
266     private static final int CUTOFF = 10;
267
268     /**
269      * 三数中值分割法:取左端,右端,中心位置的三个元素的中值作为枢纽元
270      * 排序后最小的将位于a[left],最大的位于a[right],枢纽元即中间值a[center]将被放置于a[right-1](亦即交换a[center]与a[right-1])
271      * 这样在分隔阶段,i,j将从left+1和right-2开始比较
272      * 三数中值分割法的好处:a[left]比枢纽元小,将作为j的警戒标记;而a[right-1]存放着枢纽元,则自然作为i的警戒标记。
273      * */
274     private static <AnyType extends Comparable<? super AnyType>> AnyType median3(AnyType [] a, int left, int right){
275         int center = (left +  right)/2;
276         if(a[center].compareTo(a[left]) < 0)
277             swap(a, center, left);
278         if(a[right].compareTo(a[left]) < 0)
279             swap(a, right, left);
280         if(a[right].compareTo(a[center]) < 0)
281             swap(a, right, center);
282         //将枢纽元至于a[right - 1]的位置上
283         swap(a, center, right - 1);
284         return a[right - 1];
285     }
286     /**
287      * 快速排序递归程序,主体程序,遇到跟pivot枢纽元值相等的值要停下
288      * */
289     private static <AnyType extends Comparable<? super AnyType>> void quickSort(AnyType [] a, int left, int right){
290         //利用截止范围判断数据量
291         if(left + CUTOFF <= right){
292             //获取枢纽元
293             AnyType pivot = median3(a, left, right);
294             //由于pivot放置在了a[right - 1]的位置(暂存pivot),因此i,j的取值应该为 left + 1,和right - 2
295             int i = left, j = right - 1;
296             for(;;){
297                 //在遇到i,j处值都等于pivot时候停下,但是还得继续道,j<i才算结束,因此while编写要格外注意
298                 while(a[++i].compareTo(pivot) < 0){}//遇到跟pivot枢纽元值相等的值要停下,否则N2效率低下
299                 while(a[--j].compareTo(pivot) > 0){}
300                 if(i < j)
301                     swap(a, i, j);
302                 else
303                     break;
304             }
305 //            for(;;){
306 //                while(a[i].compareTo(pivot) < 0){i++;}
307 //                while(a[j].compareTo(pivot) > 0){j--;}
308 //                if(i < j){
309 //                    swap(a, i, j);
310 //                    i++;j--;
311 //                }
312 //                else
313 //                    break;
314 //            }
315             //因为i左边都比pivot小,i及i右边除了right-1除存放着pivot外都比pivot大,因此将i处值与right-1处值交换
316             //即得到i左边都比其小,右边都比其大,i即pivot排序好的正确位置(换回pivot)
317             swap(a, i, right - 1);
318             //i已排好序
319             quickSort(a, left, i - 1);
320             quickSort(a, i + 1, right);
321         }else
322             insertionSort(a);
323     }
324     /**
325      * 快速排序驱动程序
326      * */
327     public static <AnyType extends Comparable<? super AnyType>> void QuickSort(AnyType [] a){
328         quickSort(a, 0, a.length - 1);
329     }
330
331     /*********************************QuickSort2***************************************/
332     /**
333      * 使用数组第一位作为枢纽元
334      * */
335     private static <AnyType extends Comparable<? super AnyType>> void quickSort2(AnyType [] a, int start, int end){
336         if(start < end){
337             int i = start, j = end;
338             AnyType base = a[start];
339             while(i < j ){
340                 while((a[j].compareTo(base) > 0) && (j > i))
341                     j--;
342                 if(i < j){
343                     a[i] = a[j];
344                     i++;//
345                 }
346                 while((a[i].compareTo(base) < 0) && (i < j))
347                     i++;
348                 if(i < j){
349                     a[j] = a[i];
350                     j--;//
351                 }
352
353             }//while
354             a[i] = base;
355
356             quickSort2(a, start, i-1);
357             quickSort2(a, i+1, end);
358         }
359
360     }
361     /**
362      * 驱动程序
363      * 使用数组第一位作为枢纽元
364      * */
365     public static <AnyType extends Comparable<? super AnyType>> void QuickSort2(AnyType [] a){
366         quickSort2(a, 0, a.length-1);
367     }
368     /*********************************QuickSort3***************************************/
369     /**
370      * 使用非递归的快速排序
371      * */
372     public static <AnyType extends Comparable<? super AnyType>> void QuickSort3(AnyType [] a){
373
374     }
375
376
377     /*-----------------------------------------main-------------------------------------------------*/
378     public static void main(String[] args) {
379         // TODO Auto-generated method stub
380         /**
381          * Test case: Sort the array.
382          * */
383 //        Integer[] a ={3,1,4,1,5,9,2,6,142,543,123,65,453,879,572,434,111,242,811,102};
384         Integer[] a ={3,1,4,1,5,9,2,6};
385         System.out.println("Before sorting:");
386         for(Integer i:a){
387             System.out.print(i+",");
388         }
389         System.out.println();
390
391         Sorting.selectSort(a);//排序方法调用
392         System.out.println("After sorting:");
393         for(Integer i:a){
394             System.out.print(i+",");
395         }
396         System.out.println();
397
398
399     }
400
401 }
时间: 2024-08-24 01:38:29

java基础算法--排序大全的相关文章

java基础算法之排序

总体基础算法总结 http://blog.csdn.net/lilong_dream/article/details/23356513 基础算法之排序 http://www.cnblogs.com/qqzy168/archive/2013/08/03/3219201.html 基础算法之数组.字符串 String l="helloworld";toCharArray 将字符串转化成数组char[] a1=l.toCharArray(); toCharArray()  //获得字符串对应

软帝学院:一万字的Java基础知识总结大全(实用)

Java基础总结大全(实用) 一.基础知识: 1.JVM.JRE和JDK的区别: JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性. java语言是跨平台,jvm不是跨平台的. JRE(Java Runtime Environment):java的运行环境,包括jvm+java的核心类库. JDK(Java Development Kit):java的开发工具,包括jre+开发工具 2.环境变量path和classpath的作用是什么? (1)p

java基础算法之选择排序

选择排序 选择排序(Selection sort)是一种简单直观的排序算法.它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完. 时间复杂度  选择排序的交换操作介于 0 和 (n - 1) 次之间.选择排序的比较操作为 n (n - 1) / 2 次之间.选择排序的赋值操作介于 0 和 3 (n - 1) 次之间.比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(

java基础算法之冒泡排序

接触冒泡算法还是大一了,学习C语言的冒泡算法.现在唯一记得就是冒泡与选择了.出来刚刚工作的时候觉的算法基本没撒用处,现在发现这些都是很好的基础.因此自己也准备重新拾起这些知识. 冒泡排序 泡排序是一种很简单的排序的算法,根据名字就可以知道这一个过程,一点点的把大的数移到顶部. 时间复杂度 若文件的初始状态是正序的,一趟扫描即可完成排序.所需的关键字比较次数 和记录移动次数 均达到最小值:  ,  .所以,冒泡排序最好的时间复杂度为 . 若初始文件是反序的,需要进行 趟排序.每趟排序要进行 次关键

java基础算法之快速排序

快速排序(Quicksort)是对冒泡排序的一种改进.在大学学过之后现在基本忘了,最近在好多地方都看到说快速排序在面试会问到,于是自己也准备重新拾起以前忘记的东西来,慢慢的积累自己的基础知识.fighting 算法概念 快速排序由C. A. R. Hoare在1962(50多年了呢)年提出,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有

java基础算法-快速排序

玩博客园很多年,第一次写点什么,就从基础开始吧.最近去面试,发现自己算法忘光了,赶紧复习下. /*** * 排序算法测试类**/public class TestForSort { /*** @param args*/public static void main(String[] args) {int[] array = new int[] {4,1,5,3,2,6};//快排quicksort(array,0,array.length-1);System.out.println("=====

【JAVA】算法排序(一)——选择排序法

一.前言 前文中我们总览了一下所有的排序的算法,下面小编就和给大家分享一下选择排序算法. 二 .核心知识点 选择排序的核心思想是我是最大的. 选择排序(Selection sort)是一种简单直观的排序算法.无论是那一种语言的教科书,都会运用到选择排序算法来比较大小.虽然代码就几行,但是如何理解其中的思想是很重要的.下面是小编自己的一些认识: 工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完. eg:比如从大到小,先随便取一个值

基础算法——排序【一】

排序可以说时最基础的算法之一,排序就是将数据按照某种逻辑重新排列的过程,比如从大到小排序.从小到大排序:排序非常常见比如有购物车物品的排序.历史订单的排序等等:算法我们比较关心的主要有两点:时间复杂度与空间复杂度,排序算法一样:这篇文章只介绍几种基本的排序算法:冒泡排序.插入排序.选择排序: 选择排序 算法逻辑上分为已排序未排序两个区间,从当前列表中选择最小的元素与当前列表第一个元素交换位置,从列表剩余元素中找到最小元素与列表第二个元素交换位置如此重复执行的算法为选择排序算法: 选择排序与数据的

java基础算法题

为了提高自己的代码能力和算法能力,我决定每天学习一道算法题,吸收前辈思想. [程序1] TestRabbit.java 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析:兔子数量的规律为数列:1,1,2,3,5,8,13.....其实就是斐波那契数列  使用递归就可以实现 1 /** 2 * 兔子问题 3 * 2016/5/9 4 * 斐波那契数列求值 5 *题目:古典问题:有一对兔子,