Java排序
1.基础排序
1.1冒泡排序
-
排序原理
/* * 1.比较相连的元素,如果前一个元素比后一个大的话,就交换两个元素; * 2.对每一对相连的元素做同样的操作,从一开始的第一对元素到结尾的最后 *一对元素,最终的位置就是最大元素。 */
-
实例
package com.atrx.algorithm.sort; public class Bubble { //对数组中元素进行排序 public static void sort(Comparable[] a){ for (int i=a.length-1;i>0;i--){ for(int j=0;j<i;j++){ //索引j j+1处元素大小 if(greater(a[j],a[j+1])){ exch(a,j,j+1); } } } } //比较v个元素是否大于w元素 private static boolean greater(Comparable v,Comparable w){ return v.compareTo(w)>0; } //交换数组元素i j的位置 private static void exch(Comparable[] a,int i,int j){ Comparable temp; temp=a[i]; a[i]=a[j]; a[j]=temp; } }
package com.atrx.algorithm.sort;
import java.util.Arrays;
public class BubbleTest {
public static void main(String[] args) {
Integer[] a={4,5,6,3,2,1};
Bubble.sort(a);
System.out.println(Arrays.toString(a));
//[1, 2, 3, 4, 5, 6]
//时间复杂度为n^2
}
}
1.2选择排序
-
排序原理
/* * 1.在每一次遍历过程中,都假定第一个索引处的元素是最小值,和其他元素索引处元素的值进行比较,如果当前索引处的值大于 * 其他某个索引处的值,则假定其他某个索引处的值为最小值,最后找到最小值所在元素的索引; * 2.交换第一个索引处和最小值所在索引处的值; * */
-
实例
package com.atrx.algorithm.sort; public class Selection { //对数组中元素进行排序 public static void sort(Comparable[] a){ for(int i=0;i<a.length-1;i++){ int minIndex=i;//假定最小元素的索引值为 for(int j=i+1;j<a.length;j++){ //满足,则赋值minIndex=j if(greater(a[minIndex],a[j])){ minIndex=j; } exch(a,i,minIndex); } } } //比较v个元素是否大于w元素 private static boolean greater(Comparable v,Comparable w){ return v.compareTo(w)>0; } //交换数组元素i j的位置 private static void exch(Comparable[] a,int i,int j){ Comparable temp; temp=a[i]; a[i]=a[j]; a[j]=temp; } }
package com.atrx.algorithm.sort; import java.util.Arrays; public class SelectionTest { public static void main(String[] args) { Integer[] a={4,6,8,7,9,2,10,1}; Selection.sort(a); System.out.println(Arrays.toString(a)); //[1, 2, 4, 6, 7, 8, 9, 10] //时间复杂度为n^2 } }
1.3 插入排序
-
排序原理
/* * 1.先把所有元素分为已排好序的和未排好序的; * 2.找到未排好序组的第一个元素,向已经排好序的组中插入; * 3.倒叙遍历已经排好序的元素,依次和待插入元素进行比较,直到有一个元素小于等于待插入元素, * 那么把待插入元素放到这个位置,其他元素向后移动一位。 */
-
实例
package com.atrx.algorithm.sort; public class Insertion { //对数组中元素进行排序 public static void sort(Comparable[] a){ for (int i=1;i<a.length;i++){ for(int j=i;j>0;j--){ if(greater(a[j-1],a[j])){ exch(a,j-1,j); }else { break; } } } } //比较v个元素是否大于w元素 private static boolean greater(Comparable v,Comparable w){ return v.compareTo(w)>0; } //交换数组元素i j的位置 private static void exch(Comparable[] a,int i,int j){ Comparable temp; temp=a[i]; a[i]=a[j]; a[j]=temp; } }
package com.atrx.algorithm.sort;
import java.util.Arrays;
public class InsertionTest {
public static void main(String[] args) {
Integer[] a={4,3,2,10,12,1,5,6};
Insertion.sort(a);
System.out.println(Arrays.toString(a));
//[1, 2, 3, 4, 5, 6, 10, 12]
//时间复杂度:n^2
}
}
2.高级排序
2.1希尔排序
-
排序原理
/* * 1.选定一个增长量h,按照h对数组数据进行分组; * 2.对分好组的每一组数据进行插入排序; * 3.减小增长量h,最小减为1,重复第二步操作。 * */
-
实例
package com.atrx.algorithm.sort; public class Shell { //对数组中元素进行排序 public static void sort(Comparable[] a) { //根据a的长度,确定增长量h int h=1; while(h<a.length/2){ h=h*2+1; } //希尔排序 while(h>=1){ //排序 for(int i=h;i<a.length;i++){ //找到待插入的元素 for (int j=i;j>=h;j-=h) { //将待插入元素插入到有序数组中 if(greater(a[j-h],a[j])){ //交换元素 exch(a,j-h,j); }else{ break; } } } //减小h的值 h=h/2; } } //比较v个元素是否大于w元素 private static boolean greater(Comparable v,Comparable w){ return v.compareTo(w)>0; } //交换数组元素i j的位置 private static void exch(Comparable[] a,int i,int j){ Comparable temp; temp=a[i]; a[i]=a[j]; a[j]=temp; } }
package com.atrx.algorithm.sort;
import java.util.Arrays;
public class ShellTest {
public static void main(String[] args){
Integer[] a={9,1,2,5,7,4,8,6,3,5};
Shell.sort(a);
System.out.println(Arrays.toString(a));
}
}
2.2归并排序
-
排序原理
/* * 归并排序原理(分治): * 1.尽可能将一组数据分成两个元数个数相等的子组,并对每个子组进行继续拆分,直到拆分后的元素个数唯一; * 2.将相连的两个子组进行合并成一个有序的大组; * 3.不断地重复步骤2,直到只有一个组为止。 * */
-
实例
package com.atrx.algorithm.sort; public class Merge { //对数组中元素进行排序 public static void sort(Comparable[] a) { //初始化数组assist assist = new Comparable[a.length]; //定义一个lo,hi变量,分别记录数组中最小的索引和最大的的索引 int lo = 0; int hi = a.length - 1; //调用sort重载方法完成数组中从lo到hi的元素的排序 sort(a, lo, hi); } //归并需要的辅助数组 private static Comparable[] assist; //比较v个元素是否大于w元素 private static boolean less(Comparable v, Comparable w) { return v.compareTo(w) < 0; } //交换数组元素i j的位置 private static void exch(Comparable[] a, int i, int j) { Comparable temp; temp = a[i]; a[i] = a[j]; a[j] = temp; } //对数组中从lo到hi的元素进行排序 private static void sort(Comparable[] a, int lo, int hi) { //安全校验 if (hi <= lo) { return; } //对lo到hi之间的数据分为两个组 int mid = lo + (hi - lo) / 2; //分别对每一组数据进行排序 sort(a, lo, mid); sort(a, mid + 1, hi); //把两个数组中数据进行归并 merge(a, lo, mid, hi); } //d对数组中,从lo到mid为一组,从mid+1到hi为一组,对这两组数据进行合并 private static void merge(Comparable[] a, int lo, int mid, int hi) { //定义三个指针 int i = lo; int p1 = lo; int p2 = mid+1; //遍历,移动p1和p2,比较对应索引处的值,找出最小的,放到辅助数组的对应索引处 while (p1 <= mid && p2 <= hi) { if (less(a[p1], a[p2])) { assist[i++] = a[p1++]; } else { assist[i++] = a[p2++]; } } //遍历,如果p1的指针没有走完,那么顺序移动p1指针,把对应的元素放到辅助数组的对应索引处 while (p1 <= mid) { assist[i++] = a[p1++]; } //遍历,如果p2的指针没有走完,那么顺序移动p2指针,把对应的元素放到辅助数组的对应索引处 while (p2 <= hi) { assist[i++] = a[p2++]; } //把辅助数组中的元素拷贝到原数组中 for (int index = lo; index <= hi; index++) { a[index] = assist[index]; } } }
package com.atrx.algorithm.sort;
import java.util.Arrays;
public class MergeTest {
public static void main(String[] args) {
Integer[] a={8,4,5,7,1,3,6,2};
Merge.sort(a);
System.out.println(Arrays.toString(a));
//[1, 2, 3, 4, 5, 6, 7, 8]
//时间复杂度:n*log(n)
}
}
2.3快速排序
-
排序原理
/* * 1.首先设立一个分界值,通过该分界值将数组分成左右两个部分; * 2.将大于等于分界值的数据放到数组右边,小于的放到左边。则此时左边部分各元素小于或等于分界值, * 右边部分各元素大于或等于分界值; * 3.然后,左右两边的数据可以独立排序。对于左边数据又可以设立一个分界值,将该部分分成左右两 * 部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似的操作; * 4.重复上述过程,很明显这是一个递归过程。通过递归将左侧的排好序后,再递归排好右边部分,当 * 左右两边排好后,整个数组也就排好序了。 * */
-
实例
package com.atrx.algorithm.sort; public class Quick { //对数组中元素进行排序 public static void sort(Comparable[] a){ int lo=0; int hi=a.length-1; sort(a,lo,hi); } //对数组中索引从lo到hi之间的元素进行排序 private static void sort(Comparable[] a,int lo,int hi){ if(hi<=lo){ return; } int partition=partition(a,lo,hi); sort(a,lo,partition-1); sort(a,partition+1,hi); } //对数组中从索引lo和hi之间的元素进行分组,并返回分组界限对应的索引 public static int partition(Comparable[] a,int lo,int hi){ //确定分界值 Comparable key=a[lo]; //定义两个指针,分别指向待切分元素的最小索引处和最大索引处的下一个位置 int left=lo; int right=hi+1; //切分 while(true){ //先从右往左,移动right指针,找到一个比分界值小的元素为止 while(less(key,a[--right])){ if(right==lo){ break; } } //先从左往右,移动left指针,找到一个比分界值大的元素为止 while(less(a[++left],key)){ if(left==hi){ break; } } //判断left>=right,如果成立,这证明元素完成移动,结束循环;如果不是,交换元素即可 if(left>=right){ break; }else { exch(a,left,right); } } //交换分界值 exch(a,lo,right); return right; } //比较v个元素是否大于w元素 private static boolean less(Comparable v,Comparable w){ return v.compareTo(w)<0; } //交换数组元素i j的位置 private static void exch(Comparable[] a,int i,int j){ Comparable temp; temp=a[i]; a[i]=a[j]; a[j]=temp; } }
package com.atrx.algorithm.sort; import java.util.Arrays; public class QuickTest { public static void main(String[] args) { Integer[] a={6,1,2,7,9,3,4,5,8}; Quick.sort(a); System.out.println(Arrays.toString(a)); //[1, 2, 3, 4, 5, 6, 7, 8, 9] //时间复杂度:n } }
2.4堆排序
-
实例
package com.atrx.algorithm.sort; public class HeapSort { //判断heap堆中索引i处的元素是否小于j处的元素 private static boolean less(Comparable[] heap, int i, int j) { return heap[i].compareTo(heap[j]) < 0; } //交换heap堆中i与j处索引的值 private static void exch(Comparable[] heap, int i, int j) { Comparable tmp = heap[i]; heap[i] = heap[j]; heap[j] = tmp; } //根据原数组source,构造堆heap private static void createHeap(Comparable[] source, Comparable[] heap) { //source数据拷贝到heap中 System.arraycopy(source, 0, heap, 1, source.length); //对堆中元素做下沉调整 for (int i = (heap.length) / 2; i > 0; i--) { sink(heap, i, heap.length - 1); } } //对source数组中的数据进行小到大的排序 public static void sort(Comparable[] source) { //构建堆 Comparable[] heap = new Comparable[source.length + 1]; createHeap(source, heap); //定义一个变量,记录未排序的元素中最大的索引 int N = heap.length - 1; //通过循环,交换1索引处的元素和排序的元素中的最大索引出的元素 while (N != 1) { //交换元素 exch(heap, 1, N); //排序交换后的最大元素所在的索引,让他不要参与堆的下沉调整 N--; //需要对索引1处的元素做堆的下沉调整 sink(heap, 1, N); } //数组的拷贝 System.arraycopy(heap, 1, source, 0, source.length); } //在heap堆中,对target处的元素做下沉,范围是0~range private static void sink(Comparable[] heap, int target, int range) { while (2 * target <= range) { int max; if (2 * target + 1 <= range) { //找出当前节点的较大子节点 if (less(heap, 2 * target, 2 * target + 1)) { max = 2 * target + 1; } else { max = 2 * target; } } else { max = 2 * target; } //比较当前节点的值和较大子节点的值 if (!less(heap, target, max)) { break; } exch(heap, target, max); target = max; } } }
package com.atrx.algorithm.sort; import java.util.Arrays; public class HeapTest { public static void main(String[] args) { String[] arr={"s","o","r","t","e","x","a","m","p","l","e"}; HeapSort.sort(arr); System.out.println(Arrays.toString(arr)); //[a, e, e, l, m, o, p, r, s, t, x] } }
heap, target, max)) {
break;
}
exch(heap, target, max);
target = max;
}
}
}
```java
package com.atrx.algorithm.sort;
import java.util.Arrays;
public class HeapTest {
public static void main(String[] args) {
String[] arr={"s","o","r","t","e","x","a","m","p","l","e"};
HeapSort.sort(arr);
System.out.println(Arrays.toString(arr));
//[a, e, e, l, m, o, p, r, s, t, x]
}
}