排序算法
一、冒泡排序
基本思想:通过对待排序序列从前向后(从下表较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就像水底下的气泡一样逐渐向上冒。
因为排序的过程中,各个元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在要在排序过程中设置一个标志flag判断元素是否进行过交换,从而减少不必要的比较。
时间复杂度:O(n^2)
代码
public class BubbleSort {
public static void main(String[] args) {
int[] arr = new int[]{12,34,24,15,6,8,65};
sort(arr);
for (int i=0;i<arr.length;i++){
System.out.print(arr[i] + " ");
}
}
public static void sort(int[] arr){
int flag = 1;
for (int i=0;i<arr.length && flag==1;i++){
flag = 0;
for (int j=0;j<arr.length-i-1;j++){
if (arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = 1;
}
}
}
}
}
结果:
二:选择排序
基本思想:第一次从a[0]~a[n-1]中选取最小值,与a[0]交换,第二次从a[1]-a[n-1]中选取最小值与a[1]交换…第i次从a[i-1]-a[n-1]中选取最小值与a[i-1]交换…第n-1次从a[n-2]-a[n-1]中选取最小值与a[n-2]交换,总共交换n-1 次,得到一个从小到大的排序序列。
图解如下:
代码如下:
public class SelectSort {
public static void main(String[] args) {
int[] arr = {14,25,3,9,89,5,4,78};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr){
for (int i=0;i<arr.length-1;i++){
int minIndex = i;
int min = arr[i];
for (int j=i+1;j<arr.length;j++){
if (arr[j] < min){
min = arr[j];
minIndex = j;
}
}
if (minIndex != i){
arr[minIndex] = arr[i];
arr[i] = min;
}
}
}
}
结果如下:
三、插入排序
基本思想:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。
图解如下:
代码如下:
public class InsertSort {
public static void main(String[] args) {
int[] arr = {14,25,3,9,89,5,4,78};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr){
for (int i=1;i<arr.length;i++){
int insertIndex = i - 1;
int insertValue = arr[i];
while(insertIndex>=0 && arr[insertIndex]>insertValue){
arr[insertIndex + 1] = arr[insertIndex];
insertIndex--;
}
if (insertIndex + 1 != i) {
arr[insertIndex + 1] = insertValue;
}
}
}
}
结果如下:
四、希尔排序
基本思想:希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减小,每组包含的关键词越来越多,当增量减至1时,整个文件被分成一组,算法终止;
图解如下:
方式一:对有序序列在插入时采用交换法(效率不是很高)
代码如下:
public class ShellSort {
public static void main(String[] args) {
int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr) {
int temp = 0;
for (int gap = arr.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < arr.length; i++) {
for (int j = i - gap; j >= 0; j -= gap) {
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
}
结果如下:
方式二:对有序序列在插入时采用移动法(推荐使用,效率很高)
public class ShellSort {
public static void main(String[] args) {
int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
sort2(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort2(int[] arr){
for (int gap = arr.length/2;gap > 0;gap /= 2){
for (int i = gap;i<arr.length;i++){
int j=i;
int temp = arr[j];
while (j - gap>=0 && temp < arr[j - gap]){
arr[j] = arr[j-gap];
j -= gap;
}
arr[j] = temp;
}
}
}
}
结果如下:
两种方式所用时间对比如下:
public static void main(String[] args) {
int[] arr = new int[80000];
for (int i=0;i<arr.length;i++){
arr[i] = (int) (Math.random()*800000);
}
long t1 = System.currentTimeMillis();
sort(arr);//或者sort2(arr);
long t2 = System.currentTimeMillis();
System.out.println("所用时间为:" + (t2 - t1) + "ms");
}
方式一:
方式二: