排序方法

  1 public class SortExample {
  2 
  3     public static void main(String[] args) {
  4         bubbleSort();
  5     }
  6 
  7     /**
  8      * 冒泡排序
  9      */
 10     private static void bubbleSort(){
 11         int[] arr  = {6,3,8,2,9,1};
 12         // 标识变量,表示是否进行过交换
 13         boolean flag = false;
 14         int temp = 0;
 15         for (int i = 0; i < arr.length-1; i++) {
 16             for (int j = 0; j < arr.length-1-i; j++) {
 17                 // 如果前面的数比后面的数大,则交换
 18                 if(arr[j]>arr[j+1]){
 19                     flag = true;
 20                     temp = arr[j];
 21                     arr[j] = arr[j+1];
 22                     arr[j+1] = temp;
 23                 }
 24             }
 25             // 在一趟排序中,一次交换都没有发生过
 26             if(!flag){
 27                 break;
 28             }
 29         }
 30 
 31         System.out.println("排序后的数组为:");
 32         for(int num:arr){
 33             System.out.print(num+" ");
 34         }
 35     }
 36 
 37     /** 选择排序
 38      * (1)在序列中找到最小元素,放在第一个位置;
 39      * (2)从剩余未排序元素中继续寻找最小元素,放在第二个位置;
 40      * @param arr
 41      */
 42     public static void selectSort(int[] arr) {
 43         for (int i = 0; i < arr.length - 1; i++) {
 44             int minIndex = i;
 45             int min = arr[minIndex];
 46             for(int j  = 1 + i;j<arr.length;j++){
 47                 if(min > arr[j]){
 48                     min = arr[j];
 49                     minIndex = j;
 50                 }
 51             }
 52             arr[minIndex] = arr[i];
 53             arr[i] = min;
 54         }
 55     }
 56 
 57     /**插入排序
 58      * 把n个待排序的元素第一位看成有序表,其它的看成无序表,排序过程中,每次从无序表中取出一个数,依次与有序表中的数进行比较,插入到合适的位置。
 59      * @param arr
 60      */
 61     public static void insertSort(int[] arr ){
 62         int insertVal = 0;
 63         int insertIndex = 0;
 64         for (int i = 1; i < arr.length; i++) {
 65             //定义待插入的数
 66             insertVal = arr[i];
 67             // 即arr[i]的前面这个数的下标
 68             insertIndex = i - 1;
 69             // 给insertVal 找到插入的位置
 70             // 说明
 71             // 1. insertIndex >= 0 保证在给insertVal 找插入位置,不越界
 72             // 2. insertVal < arr[insertIndex] 待插入的数,还没有找到插入位置
 73             // 3. 就需要将 arr[insertIndex] 后移
 74             while(insertIndex >= 0 && insertVal < arr[insertIndex]){
 75                 arr[insertIndex+1] = arr[insertIndex];
 76                 insertIndex--;
 77             }
 78             // 当退出while循环时,说明插入的位置找到, insertIndex + 1
 79             if(insertIndex + 1 != i){
 80                 arr[insertIndex+1] = insertVal;
 81             }
 82         }
 83     }
 84 
 85     //希尔排序(冒泡排序)
 86     // 使用逐步推导的方式来编写希尔排序
 87     // 希尔排序时, 对有序序列在插入时采用交换法,
 88     // 思路(算法) ===> 代码
 89     // 希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,
 90     // 同时该算法也是冲破O(n²)的第一批算法之一。它与插入排序的不同之处在于,它会优先比较较远的元素。
 91     public static void shellSort(int[] arr){
 92         // 根据前面的逐步分析,使用循环处理
 93         for(int step = arr.length/2;step>0;step /= 2 ){
 94             for (int i = step; i < arr.length; i++) {
 95                 // 遍历各组中所有的元素(共step组,每组有个元素), 步长step
 96                 for (int j = i - step; j >= 0; j -= step) {
 97                     // 如果当前元素大于加上步长后的那个元素,说明交换
 98                     if (arr[j] > arr[j + step]) {
 99                         int temp = arr[j];
100                         arr[j] = arr[j + step];
101                         arr[j + step] = temp;
102                     }
103                 }
104             }
105         }
106     }
107 
108     /**快速排序
109      * 通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录进行排序,以达到整个排序的过程。
110      * @param arr
111      * @param left
112      * @param right
113      */
114     public static void quickSort(int[] arr,int left, int right) {
115         int l = left; //左下标
116         int r = right; //右下标
117         //pivot 中轴值
118         int pivot = arr[(left + right) / 2];
119         int temp = 0; //临时变量,作为交换时使用
120         //while循环的目的是让比pivot 值小放到左边
121         //比pivot 值大放到右边
122         while( l < r) {
123             //在pivot的左边一直找,找到大于等于pivot值,才退出
124             while( arr[l] < pivot) {
125                 l += 1;
126             }
127             //在pivot的右边一直找,找到小于等于pivot值,才退出
128             while(arr[r] > pivot) {
129                 r -= 1;
130             }
131             //如果l >= r说明pivot 的左右两的值,已经按照左边全部是
132             //小于等于pivot值,右边全部是大于等于pivot值
133             if( l >= r) {
134                 break;
135             }
136 
137             //交换
138             temp = arr[l];
139             arr[l] = arr[r];
140             arr[r] = temp;
141 
142             //如果交换完后,发现这个arr[l] == pivot值 相等 r--, 前移
143             if(arr[l] == pivot) {
144                 r -= 1;
145             }
146             //如果交换完后,发现这个arr[r] == pivot值 相等 l++, 后移
147             if(arr[r] == pivot) {
148                 l += 1;
149             }
150         }
151 
152         // 如果 l == r, 必须l++, r--, 否则为出现栈溢出
153         if (l == r) {
154             l += 1;
155             r -= 1;
156         }
157         //向左递归
158         if(left < r) {
159             quickSort(arr, left, r);
160         }
161         //向右递归
162         if(right > l) {
163             quickSort(arr, l, right);
164         }
165     }
166 
167     /**基数排序
168      * 将所有带比较数值统一为同样的数位长度,数据较短的数前面补0,然后从最低位开始依次进行依次排序,这样从最低位排序一直到最高位排序完成之后,数列就变成了一个有序序列。
169      * @param arr
170      */
171     public static void radixSort(int arr[]){
172         System.out.println("基数排序,arr长度:"+arr.length);
173         //1. 得到数组中最大的数的位数
174         int max = arr[0]; //假设第一数就是最大数
175         for(int i = 1; i < arr.length; i++) {
176             if (arr[i] > max) {
177                 max = arr[i];
178             }
179         }
180         //得到最大数是几位数
181         int maxLength = (max + "").length();
182 
183         //定义一个二维数组,表示10个桶, 每个桶就是一个一维数组
184         //说明
185         //1. 二维数组包含10个一维数组
186         //2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
187         //3. 名明确,基数排序是使用空间换时间的经典算法
188         int[][] bucket = new int[10][arr.length];
189 
190         //为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
191         //可以这里理解
192         //比如:bucketElementCounts[0] , 记录的就是  bucket[0] 桶的放入数据个数
193         int[] bucketElementCounts = new int[10];
194 
195         //这里我们使用循环将代码处理
196         for(int i = 0 , n = 1; i < maxLength; i++, n *= 10) {
197             //(针对每个元素的对应位进行排序处理), 第一次是个位,第二次是十位,第三次是百位..
198             for(int j = 0; j < arr.length; j++) {
199                 //取出每个元素的对应位的值
200                 int digitOfElement = arr[j] / n % 10;
201                 //放入到对应的桶中
202                 bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
203                 bucketElementCounts[digitOfElement]++;
204             }
205             //按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
206             int index = 0;
207             //遍历每一桶,并将桶中是数据,放入到原数组
208             for(int k = 0; k < bucketElementCounts.length; k++) {
209                 //如果桶中,有数据,我们才放入到原数组
210                 if(bucketElementCounts[k] != 0) {
211                     //循环该桶即第k个桶(即第k个一维数组), 放入
212                     for(int l = 0; l < bucketElementCounts[k]; l++) {
213                         //取出元素放入到arr
214                         arr[index++] = bucket[k][l];
215                     }
216                 }
217                 //第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
218                 bucketElementCounts[k] = 0;
219 
220             }
221         }
222     }
223 }

 

posted @ 2022-11-04 16:58  忘语丷  阅读(42)  评论(0)    收藏  举报