JAVA四种常用排序算法
冒泡排序法
-
算法原理
- 数组从后往前
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
- 数组从后往前
-
算法分析
- 第一趟:依次比较相邻的两个数,将小数放在前面,大数放在后面。首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。
- 在第二趟:仍从第一对数开始比较…
- 重复以上过程,直至最终完成排序。
-
图解演示
-
代码实例
- 运用遍历数组进行比较,通过不断的比较将最小值或者最大值一个一个的遍历出来。
import java.util.Scanner; public class paixu { public static void main(String[] args) { System.out.println("请输入一个正整数数组,以逗号隔开。"); Scanner scanner = new Scanner(System.in); String str = scanner.nextLine(); String[] numStr = str.split(","); int[] arr = new int[numStr.length]; for (int i = 0; i < arr.length; i++) { arr[i] = Integer.parseInt(numStr[i]); } maopao method = new maopao(); method.maopao(arr); System.out.print("冒泡排序后:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } } }
import java.util.Arrays; import java.util.Scanner; public class maopao { public void maopao(int arr[]) { for (int i = 0; i < arr.length - 1; i++) {// 外层循环控制排序趟数 for (int j = 0; j < arr.length - 1 - i; j++) {// 内层循环控制每一趟排序多少次 if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } }
-
时间复杂度
- 若记录序列的初始状态为"正序",则冒泡排序过程只需进行一趟排序,在排序过程中只需进行n-1次比较,且不移动记录;
- 若记录序列的初始状态为"逆序",则需进行n(n-1)/2次比较和记录移动。
- 冒泡排序总的时间复杂度为O(n*n)。
快速排序法
-
算法原理
- 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
-
算法分析
- 在数组中取出数组第一位为基准点,然后分别从数组的两端扫描数组,与该基准点进行比较。
- 设两个分区:小分区,大分区。先大分区从后向前扫描,再小分区从前向后扫描。
- 与基准点比较,如果在大分区发现有元素比该基准点的值小,等待,然后从前半部分开始扫秒,发现有元素大于基准点的值,将两元素交换位置,如此往复循环,直到最后一位的大分区值>=小分区值,然后把基准点的值放到大分区这个位置。
- 采用递归的方式分别对大分区和小分区排序,直至该数组有序。
-
图解演示
-
代码实例
import java.util.Scanner; public class paixu { public static void main(String[] args) { System.out.println("请输入一个正整数数组,以逗号隔开。"); Scanner scanner = new Scanner(System.in); String str = scanner.nextLine(); String[] numStr = str.split(","); int[] arr = new int[numStr.length]; for (int i = 0; i < arr.length; i++) { arr[i] = Integer.parseInt(numStr[i]); } kuaisu method2 = new kuaisu(); method2.kuaisu(arr, 0, arr.length-1); System.out.print("快速排序后:"); for(int i = 0;i<arr.length ;i++) { System.out.print(arr[i] + " "); } } }
public class kuaisu { public int getMiddle(int[] arrayInt,int low, int high) { int temp = arrayInt[low]; while(low<high) { while(low<high&&temp<arrayInt[high]) { high--; } arrayInt[low]=arrayInt[high]; while(low<high&&arrayInt[low]<temp) { low++; } arrayInt[high]=arrayInt[low]; } arrayInt[low]=temp; return low; } public void kuaisu(int [] arrayInt,int low,int high) { if (low<high) { int mid = getMiddle(arrayInt, low, high); kuaisu(arrayInt, low, mid); kuaisu(arrayInt, mid+1, high); } } }
-
时间复杂度
- 平均时间复杂度O(nlogn),最坏时间复杂度O(n*n),辅助空间O(logn)<每次都要分给一个额外空间,而总共有logn次> 。
- 每次分成两段,那么分的次数就是logn了,每一次处理需要n次计算,那么时间复杂度就是n(logn)。
- 根据平均情况来说是O(nlogn),因为在数据分布等概率的情况下对于单个数据来说在logn次移动后就会被放到正确的位置上了。
最坏是O(n^2).这种情况就是数组刚好的倒序,然后每次去中间元的时候都是取最大或者最小。
选择排序法
-
算法原理
- 每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。
-
算法分析
- 第1趟,在待排序记录r[1]…r[n]中选出最小的记录,将它与r[1]交换;
- 第2趟,在待排序记录r[2]…r[n]中选出最小的记录,将它与r[2]交换;
- 以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕。
-
图解演示
-
代码实例
public class Select { public static void select(int num[]) { for (int i = 0; i < num.length; i++) { int a = i; for (int j = i+1; j < num.length; j++) { if (num[j]<num[i]) { a = j; } if (a>i) { int temp = num[i]; num[i] = num[a]; num[a] = temp; } } } } public static void main(String[] args) { int[] testnum= {2,3,4,1}; select(testnum); System.out.print("选择排序后:"); for (int i : testnum) { System.out.print(i+" "); } } }
-
时间复杂度
- 简单选择排序的比较次数与序列的初始排序无关。
- 假设待排序的序列有 N 个元素,则比较次数总是N (N - 1) / 2。
- 当序列正序时,移动次数最少,为 0。
- 当序列反序时,移动次数最多,为3N (N - 1) / 2。
- 简单排序的时间复杂度为 O(N2)。
插入排序法
-
算法原理
- 输入一个元素,检查[数组列表中的每个元素,将其插入到一个已经排好序的数列中的适当位置,使数列依然有序,当最后一个元素放入合适位置时,该数组排序完毕。
-
算法分析
- 将一个待排序的元素按着其大小插入到已经有序的数组中的适当位置,直到全部插入完毕。
-
图解演示
-
代码实例
public class Insert { public static void insert(int num[]) { int insertNum; for (int i = 1; i < num.length; i++) { insertNum = num[i]; int j = i - 1; while (j >= 0 && insertNum < num[j]) { num[j + 1] = num[j]; j--; } num[j + 1] = insertNum; } } public static void main(String[] args) { int[] testnum = { 2, 1, 4, 3 }; insert(testnum); System.out.print("插入排序后:"); for (int i : testnum) { System.out.print(i + " "); } } }
-
时间复杂度
- 在最坏情况下,数组完全逆序,插入第2个元素时要考察前1个元素,插入第3个元素时,要考虑前2个元素,……,插入第N个元素,要考虑前 N-1个元素。因此,最坏情况下的比较次数是 N^2 / 2,所以最坏情况下的复杂度为 O(N^2)。
- 最好情况下,数组已经是有序的,每插入一个元素,只需要考查前一个元素,因此最好情况下,插入排序的时间复杂度为O(N)。