排序:
void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
1.冒泡排序(Bubble Sort)
1 //冒泡排序 2 public void bubbleSort(int[] arr) { 3 int count=0; 4 //i=0,第一轮比较 5 for (int i = 0; i < arr.length-1; i++) { 6 //第一轮,两两比较 7 for (int j = 0; j < arr.length-1-i; j++) { 8 if (arr[j]>arr[j+1]) { 9 swap(arr,j,j+1); 10 } 11 count++; 12 } 13 } 14 System.out.println("比较后:"+Arrays.toString(arr)); 15 System.out.println("一共比较了:"+count+"次");//一共比较了:105次 16 }
优化后:
1 public void bubbleSort1(int[] arr){ 2 3 int count=0; 4 for (int i = 0; i < arr.length-1; i++) { 5 boolean flag=true; 6 for (int j = 0; j < arr.length-1-i; j++) { 7 if (arr[j]>arr[j+1]) { 8 flag=false; 9 10 swap(arr,j,j+1); 11 } 12 count++; 13 } 14 if (flag) { 15 break; 16 } 17 } 18 System.out.println("比较后:"+Arrays.toString(arr)); 19 System.out.println("一共比较了:"+count+"次");//一共比较了:95次 20 }
2.选择排序(Select Sort)
1 //选择排序:先定义一个记录最小元素的下标,然后循环一次后面的,找到最小的元素,最后将他放到前面排序好的序列。 2 public void selectSort(int[] arr) { 3 for (int i = 0; i < arr.length-1; i++) { 4 int index=i;//标记第一个为待比较的数 5 for (int j = i+1; j < arr.length; j++) { //然后从后面遍历与第一个数比较 6 if (arr[j]<arr[index]) { //如果小,就交换最小值 7 index=j;//保存最小元素的下标 8 } 9 } 10 //找到最小值后,将最小的值放到第一的位置,进行下一遍循环 11 swap(arr,index,i); 12 } 13 System.out.println("比较后:"+Arrays.toString(arr)); 14 }
3.插入排序(Insert Sort)
1 //插入排序:定义一个待插入的数,再定义一个待插入数的前一个数的下标,然后拿待插入数与前面的数组一一比较,最后交换。 2 public void insertSort(int[] arr) { 3 for (int i = 0; i < arr.length; i++) { //长度不减1,是因为要留多一个位置方便插入数 4 //定义待插入的数 5 int insertValue=arr[i]; 6 //找到待插入数的前一个数的下标 7 int insertIndex=i-1; 8 while (insertIndex>=0 && insertValue <arr[insertIndex]) {//拿a[i]与a[i-1]的前面数组比较 9 arr[insertIndex+1]=arr[insertIndex]; 10 insertIndex--; 11 } 12 arr[insertIndex+1]=insertValue; 13 } 14 System.out.println("比较后:"+Arrays.toString(arr)); 15 }
4.希尔排序(Shell Sort)
1 //希尔排序:插入排序的升级 2 public void shellSort(int[] arr) { 3 int count=0;//比较次数 4 for (int gap=arr.length / 2; gap > 0; gap = gap / 2) { 5 //将整个数组分为若干个子数组 6 for (int i = gap; i < arr.length; i++) { 7 //遍历各组的元素 8 for (int j = i - gap; j>=0; j=j-gap) { 9 //交换元素 10 if (arr[j]>arr[j+gap]) { 11 swap(arr,j,j+gap); 12 count++; 13 } 14 } 15 } 16 } 17 18 System.out.println("比较后:"+Arrays.toString(arr)); 19 System.out.println("一共比较了:"+count+"次");//一共比较了:95次 20 }
5.快速排序(Quick Sort)
1 //快速排序:冒泡排序的升华版 2 void quickSort(int[] arr, int l, int r) { 3 // 子数组长度为 1 时终止递归 4 if (l >= r) return; 5 // 哨兵划分操作(以 arr[l] 作为基准数) 6 int i = l, j = r; 7 while (i < j) { 8 while (i < j && arr[j] >= arr[l]) j--; 9 while (i < j && arr[i] <= arr[l]) i++; 10 swap(arr, i, j); 11 } 12 swap(arr, i, l); 13 // 递归左(右)子数组执行哨兵划分 14 quickSort(arr, l, i - 1); 15 quickSort(arr, i + 1, r); 16 }
6.归并排序(Merge Sort)
1 public void mergeSort(int[] nums,int l, int r,int[] tmp) { 2 if (l >= r) return; 3 // 递归划分 4 int m = (l + r) / 2; 5 6 mergeSort(nums,l, m,tmp); 7 mergeSort(nums,m + 1, r,tmp); 8 9 // 合并阶段 10 int i = l, j = m + 1; 11 for (int k = l; k <= r; k++) 12 tmp[k] = nums[k]; 13 14 for (int k = l; k <= r; k++) { 15 if (i == m + 1) 16 nums[k] = tmp[j++]; 17 else if (j == r + 1 || tmp[i] <= tmp[j]) 18 nums[k] = tmp[i++]; 19 else { 20 nums[k] = tmp[j++]; 21 } 22 } 23 }
1 //归并排序 2 void mergeSort(int[] a, int left, int right, int[] temp) { 3 //分解 4 if (left<right) { 5 int mid=(left+right)/2; 6 //向左递归进行分解 7 mergeSort(a, left, mid, temp); 8 //向右递归进行分解 9 mergeSort(a, mid+1, right, temp); 10 //每分解一次便合并一次 11 merge(a,left,right,mid,temp); 12 } 13 } 14 private void merge(int[] a, int left, int right, int mid, int[] temp) { 15 int i=left; //初始i,左边有序序列的初始索引 16 int j=mid+1;//初始化j,右边有序序列的初始索引(右边有序序列的初始位置即中间位置的后一位置) 17 int t=0;//指向temp数组的当前索引,初始为0 18 19 //先把左右两边的数据(已经有序)按规则填充到temp数组 20 //直到左右两边的有序序列,有一边处理完成为止 21 while (i<=mid && j<=right) { 22 //如果左边有序序列的当前元素小于或等于右边的有序序列的当前元素,就将左边的元素填充到temp数组中 23 if (a[i]<=a[j]) { 24 temp[t]=a[i]; 25 t++;//索引向后移 26 i++;//i后移 27 }else { 28 //反之,将右边有序序列的当前元素填充到temp数组中 29 temp[t]=a[j]; 30 t++;//索引向后移 31 j++;//j后移 32 } 33 } 34 //把剩余数据的一边的元素填充到temp中 35 while (i<=mid) { 36 //此时说明左边序列还有剩余元素 37 //全部填充到temp数组 38 temp[t]=a[i]; 39 t++; 40 i++; 41 } 42 while (j<=right) { 43 //此时说明左边序列还有剩余元素 44 //全部填充到temp数组 45 temp[t]=a[j]; 46 t++; 47 j++; 48 } 49 //将temp数组的元素复制到原数组 50 t=0; 51 int tempLeft=left; 52 while (tempLeft<=right) { 53 a[tempLeft]=temp[t]; 54 t++; 55 tempLeft++; 56 } 57 }
7.堆排序(Heap Sort)
1 // 堆排序 2 public void heapSort(int[] arr) { 3 int length = arr.length; 4 //构建堆 5 buildHeap(arr,length); 6 for ( int i = length - 1; i > 0; i-- ) { 7 //将堆顶元素与末位元素调换 8 swap(arr,0,i); 9 10 //数组长度-1 隐藏堆尾元素 11 length--; 12 //将堆顶元素下沉 目的是将最大的元素浮到堆顶来 13 sink(arr, 0,length); 14 } 15 } 16 private void buildHeap(int[] arr, int length) { 17 for (int i = length / 2; i >= 0; i--) { 18 sink(arr,i, length); 19 } 20 } 21 22 private void sink(int[] arr, int index, int length) { 23 int leftChild = 2 * index + 1;//左子节点下标 24 int rightChild = 2 * index + 2;//右子节点下标 25 int present = index;//要调整的节点下标 26 27 //下沉左边 28 if (leftChild < length && arr[leftChild] > arr[present]) { 29 present = leftChild; 30 } 31 32 //下沉右边 33 if (rightChild < length && arr[rightChild] > arr[present]) { 34 present = rightChild; 35 } 36 37 //如果下标不相等 证明调换过了 38 if (present != index) { 39 //交换值 40 swap(arr,index,present); 41 42 //继续下沉 43 sink(arr, present, length); 44 } 45 }
8.计数排序 (Count Sort)(问题很多)
1 // 计数排序 2 public void countSort(int[] arr) { 3 //找出数组中的最大值 4 int max = arr[0]; 5 for (int i = 1; i < arr.length; i++) { 6 if (arr[i] > max) { 7 max = arr[i]; 8 } 9 } 10 //初始化计数数组 11 int[] countArr = new int[max + 1]; 12 13 //计数 14 for (int i = 0; i < arr.length; i++) { 15 countArr[arr[i]]++; 16 arr[i] = 0; 17 } 18 19 //排序 20 int index = 0; 21 for (int i = 0; i < countArr.length; i++) { 22 if (countArr[i] > 0) { 23 arr[index++] = i; 24 } 25 } 26 }
9.桶排序(Bucket Sort)
1 // 桶排序 2 public void bucketSort(int[] arr){ 3 //最大最小值 4 int max = arr[0]; 5 int min = arr[0]; 6 int length = arr.length; 7 8 for(int i=1; i<length; i++) { 9 if(arr[i] > max) { 10 max = arr[i]; 11 } else if(arr[i] < min) { 12 min = arr[i]; 13 } 14 } 15 16 //最大值和最小值的差 17 int diff = max - min; 18 19 //桶列表 20 ArrayList<ArrayList<Integer>> bucketList = new ArrayList<>(); 21 for(int i = 0; i < length; i++){ 22 bucketList.add(new ArrayList<>()); 23 } 24 25 //每个桶的存数区间 26 float section = (float) diff / (float) (length - 1); 27 28 //数据入桶 29 for(int i = 0; i < length; i++){ 30 //当前数除以区间得出存放桶的位置 减1后得出桶的下标 31 int num = (int) (arr[i] / section) - 1; 32 if(num < 0){ 33 num = 0; 34 } 35 bucketList.get(num).add(arr[i]); 36 } 37 38 //桶内排序 39 for(int i = 0; i < bucketList.size(); i++){ 40 //jdk的排序速度当然信得过 41 Collections.sort(bucketList.get(i)); 42 } 43 44 //写入原数组 45 int index = 0; 46 for(ArrayList<Integer> arrayList : bucketList){ 47 for(int value : arrayList){ 48 arr[index] = value; 49 index++; 50 } 51 } 52 }
10.基数排序(Raix Sort)
第一轮,以元素的个位数进行区分:[542,53,3,14,214,748]
第二轮,以元素的十位数进行区分:[3,14,214,542,748,53]
第三轮,以元素的百位数进行区分:[3,14,53,214,542,748]
1 // 基数排序 2 public void raixSort(int[] arr) { 3 // 得到数组中最大的数 4 int max = arr[0];// 假设第一个数就是数组中的最大数 5 for (int i = 1; i < arr.length; i++) { 6 if (arr[i] > max) { 7 max = arr[i]; 8 } 9 } 10 // 得到最大数是几位数 11 // 通过拼接一个空串将其变为字符串进而求得字符串的长度,即为位数 12 int maxLength = (max + "").length(); 13 14 // 定义一个二维数组,模拟桶,每个桶就是一个一维数组 15 // 为了防止放入数据的时候桶溢出,我们应该尽量将桶的容量设置得大一些 16 int[][] bucket = new int[10][arr.length]; 17 // 记录每个桶中实际存放的元素个数 18 // 定义一个一维数组来记录每个桶中每次放入的元素个数 19 int[] bucketElementCounts = new int[10]; 20 21 // 通过变量n帮助取出元素位数上的数 22 for (int i = 0, n = 1; i < maxLength; i++, n *= 10) { 23 for (int j = 0; j < arr.length; j++) { 24 // 针对每个元素的位数进行处理 25 int digitOfElement = arr[j] / n % 10; 26 // 将元素放入对应的桶中 27 // bucketElementCounts[digitOfElement]就是桶中的元素个数,初始为0,放在第一位 28 bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j]; 29 // 将桶中的元素个数++ 30 // 这样接下来的元素就可以排在前面的元素后面 31 bucketElementCounts[digitOfElement]++; 32 } 33 // 按照桶的顺序取出数据并放回原数组 34 int index = 0; 35 for (int k = 0; k < bucket.length; k++) { 36 // 如果桶中有数据,才取出放回原数组 37 if (bucketElementCounts[k] != 0) { 38 // 说明桶中有数据,对该桶进行遍历 39 for (int l = 0; l < bucketElementCounts[k]; l++) { 40 // 取出元素放回原数组 41 arr[index++] = bucket[k][l]; 42 } 43 } 44 // 每轮处理后,需要将每个bucketElementCounts[k]置0 45 bucketElementCounts[k] = 0; 46 } 47 } 48 System.out.println("比较后:"+Arrays.toString(arr)); 49 }