排序
内部排序
插入排序
- 直接插入排序
- 希尔排序
选择排序
- 简单选择排序
- 堆排序
交换排序
- 冒泡排序
- 快速排序
直接插入排序
给定一组序列,假定第一个记录自成一个有序序列,其余记录为无序序列。接着从第二个记录开始,按照记录的大小依此将当前处理的记录插入到其之前的有序序列中,直到最后一个记录插入到有序序列中为止
public static void insertSort(int arr[]){ // 1. 假设第一个序列的第一个元素是有序的 // 38,73,27,79,19,76 if(arr == null || arr.length ==0){ return ; } int j = 0; // 2. 设置一个下标,从1开始(从第二个元素开始) for(int i = 1;i<arr.length;i++){ // 当前元素和前一个比较 int temp = arr[i]; j = i; if(temp < arr[j=1]){ // 前一个比当前的大,则将当前元素放到合适的位置 // 此处要找出当前元素合适的位置,同时把前面的元素向后移动 do{ arr[j] = arr[j-1]; j--; }while(arr[j]>temp && j>=1); arr[j] = temp; } } }
排序前: 38 65 97 76 13 27 49 排序后: 13 27 38 49 65 76 97
希尔排序(最小增量排序)
算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行直接插入排序后,排序完成
public static void shellSort(int arr[]){ int length = arr.length; // 初始化增量h = length/2,每循环一次增量h/2 for(int h = length/2;h>0;h=h/2){ // 对相差当前增量的元素排序 for(int i = 0;i<length-h;i++){ int temp ; if(arr[i+h]<arr[i]){ temp = arr[i+h]; arr[i+h] = arr[i]; arr[i] = temp; } } } }
排序前: 38 65 97 76 13 27 49 shell排序后: 13 27 38 49 65 76 97
简单选择排序
在要排序的一组数中,选出最小的一个数与第一个位置的数交换;
然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止
public static void selectSort(int arr[]){ int minLocation = 0; // 在序列中挑选出最小的一个数和第一个交换 for(int i = 0;i<arr.length;i++){ int temp = arr[i]; // 最小的数 // 遍历查找出最下的数 for(int j = i+1;j<arr.length;j++){ if(temp > arr[j]){ temp = arr[j]; // temp 为最小的数 minLocation = j; } } // 到此,找出了本次循环最小的数和最小数的位置 // 交换 if(minLocation != i){ arr[minLocation] = arr[i]; arr[i] = temp; } } }
排序前: 38 65 97 76 13 27 49 选择排序后: 13 27 38 49 65 76 97
堆排序
堆排序是一种树形选择排序,是对直接选择排序的有效改进。
冒泡排序
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
public static void bubbleSort(int[] arr){ int i; int j; int temp = 0; for ( i = 0; i < arr.length; i++) { // 内部循环从序列末尾开始 for(j = arr.length-1;j>i;j--){ if(arr[j-1] > arr[j]){ // 交换 temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; } } } }
排序前: 38 65 97 76 13 27 49 21 5 8 6 4 8 3 9 冒泡排序后: 3 4 5 6 8 8 9 13 21 27 38 49 65 76 97
快速排序
快速排序是一种非常高效的排算法,它采用了分而治之
的思想,把大的拆成小的,小的再拆分为更小的
基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
public static void quickSort(int []arr){ sort(arr, 0, arr.length-1); } private static void sort(int arr[],int low,int high){ // 选择基准元素,扫描一遍 if(low>=high) return; int i = low; int j = high; int key = arr[low]; // 选择基准元素 while(j>i){ /*if(arr[i]>arr[j]){ // }*/ // 可能会出现连续的比关键字大的,就需要继续找,所以使用循环 // 从后向前比较 while(j>i && key <= arr[j]){ // 如果没有比关键字小的,则比较下一个,直到有比关键字小的交换位置 j--; } // 找出比关键字小的位置,交换两个位置的元素 if(arr[j]<=key){ int temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; } // 从前向后比较 while(j>i && key >= arr[i]){ // 如果没有比关键字小的,则比较下一个,直到有比关键字小的交换位置 i++; } if(arr[i]>=key){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } //此时第一次循环比较结束, //关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大, //但是两边的顺序还有可能是不一样的,进行下面的递归调用 // 递归 sort(arr, low, i-1); sort(arr,j+1,high); }
排序前: 38 65 97 76 13 27 49 21 5 8 6 4 8 3 9 58 66 75 22 93 91 10 冒泡排序后: 3 4 5 6 8 8 9 10 13 21 22 27 38 49 58 65 66 75 76 91 93 97
并归排序
并归排序的思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
使用技术: 递归
和 分治
先拆分再组合
并归时排序,采用双指针分别指向左半边和右半边,左半边的和有半边的比较大小,小的一边存入新的数组并自增
public static void mergeSort(int []arr,int low,int high){ if(low < high){ int mid = (low+high)/2; mergeSort(arr, low, mid); // 左边 mergeSort(arr, mid+1, high); // 右边 merge(arr, low, mid, high); } } private static void merge(int arr[],int low,int mid,int high){ int temp[] = new int [high-low+1]; int left = low; int right = mid + 1; int indexOfTemp = 0; // temp 数组中的索引 // 此时左边数组的数为有序的 while(left<=mid && right<=high){ // 比较左右两个,找出小的放到temp中 if(arr[left] < arr[right]){ temp[indexOfTemp++] = arr[left++]; }else{ temp[indexOfTemp++] = arr[right++]; } } while(left <= mid){ temp[indexOfTemp++] = arr[left++]; } while(right <= high){ temp[indexOfTemp++] = arr[right++]; } // temp -> arr for(int i = 0;i<temp.length;i++){ arr[low + i] = temp[i]; } }
排序前: 58 66 75 22 93 91 10 16 52 18 90 77 44 29 并归排序后: 10 16 18 22 29 44 52 58 66 75 77 90 91 93