排序

  1 1.冒泡排序
  2 时间复杂度:O(n²)
  3 冒泡排序算法的运作如下:(从后往前)
  4 1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  5 2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  6 3)针对所有的元素重复以上的步骤,除了最后一个。
  7 4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
  8 代码实现:
  9 
 10 package cn.lpq.sort;
 11 
 12 public class BubbleSort {
 13     public static void main(String[] args) {
 14         System.out.println("排序前:");
 15         int[] arr={51, 46, 20, 18, 65, 97, 82, 30, 77, 50,2,33,12,100 };
 16         printSort(arr);
 17         System.out.println("排序后:");
 18         bubbleSort(arr);
 19         printSort(arr);
 20 
 21     }
 22     public static void bubbleSort(int[]arr){
 23         for(int x=0;x<arr.length-1;x++){
 24             for(int y=0;y<arr.length-1-x;y++){
 25                 if(arr[y]>arr[y+1]){
 26                     int temp=arr[y];
 27                     arr[y]=arr[y+1];
 28                     arr[y+1]=temp;
 29                 }
 30             }
 31 
 32         }
 33     }
 34     public static void printSort(int []arr){
 35         StringBuilder res=new StringBuilder();
 36         res.append("[");
 37         for(int i=0;i<arr.length;i++){
 38             if(i==arr.length-1)
 39                 res.append(arr[i]+"]");
 40             else
 41                 res.append(arr[i]+",");
 42         }
 43         System.out.println(res.toString());
 44     }
 45 }
 46 1
 47 2
 48 3
 49 4
 50 5
 51 6
 52 7
 53 8
 54 9
 55 10
 56 11
 57 12
 58 13
 59 14
 60 15
 61 16
 62 17
 63 18
 64 19
 65 20
 66 21
 67 22
 68 23
 69 24
 70 25
 71 26
 72 27
 73 28
 74 29
 75 30
 76 31
 77 32
 78 33
 79 34
 80 35
 81 36
 82 37
 83 结果:
 84 冒泡排序结果
 85 2.选择排序:
 86 时间复杂度:O(n²)
 87 选择排序(Selection sort)同样也是最经典最简单的排序算法之一,特点就是简单直观。
 88 排序的原理:首先在未排序的序列里找到最小(大)元素,放到序列的首端,再从剩余元素中找到最小(大)的元素,放到序列的尾端。依次循环,直到排序完成。
 89 代码实现:
 90 
 91 package cn.lpq.sort;
 92 
 93 public class SelectSort {
 94     public static void main(String[] args) {
 95         int[] arr={11,9,3,44,12,98,292,34,522,232};
 96         System.out.println("选择排序前:");
 97         printSort(arr);
 98         selectSort(arr);
 99         System.out.println("选择排序后:");
100         printSort(arr);
101     }
102     public static void selectSort(int[]arr){
103         for(int x=0;x<arr.length-1;x++){
104             for(int y=x+1;y<arr.length;y++){
105                 if(arr[x]>arr[y]){
106                     int temp=arr[y];
107                     arr[y]=arr[x];
108                     arr[x]=temp;
109 
110                 }
111             }
112 
113         }
114     }
115     public static void printSort(int []arr){
116         StringBuilder res=new StringBuilder();
117         res.append("[");
118         for(int i=0;i<arr.length;i++){
119             if(i==arr.length-1)
120                 res.append(arr[i]+"]");
121             else
122                 res.append(arr[i]+",");
123         }
124         System.out.println(res.toString());
125     }
126 }
127 1
128 2
129 3
130 4
131 5
132 6
133 7
134 8
135 9
136 10
137 11
138 12
139 13
140 14
141 15
142 16
143 17
144 18
145 19
146 20
147 21
148 22
149 23
150 24
151 25
152 26
153 27
154 28
155 29
156 30
157 31
158 32
159 33
160 34
161 35
162 36
163 37
164 结果:
165 选择排序结果
166 
167 3.快速排序:
168 快排思想:
169 快速排序的原理:选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。一般选择序列的第一个元素。
170 一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换。找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换。直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值来说,左右两边就是有序的了,接着分别比较左右两边的序列,重复上述的循环。
171 时间复杂度为:nlog(n)
172 
173 package cn.dataStructures.Sort;
174 //快速排序算法--利用递归
175 public class QuickSort {
176     public static void main(String[] args) {
177         int []arr={12,20,5,16,15,1,2,100,30,45,23,9};
178         int low=0;
179         int high=arr.length-1;
180         quickSort(arr,low,high);
181         printSortArr(arr);
182     }
183     public static void quickSort(int [] arr,int low,int high){
184         int start=low;//设置可以移动的最小值
185         int end=high;//设置可以移动的最大值
186         int key=arr[low];//设置标识
187         while(start<end){//整体大循环
188             while(start<end&&arr[end]>=key)//先从循环后面的,从后向前,找小于key的
189                 end--;
190             if(arr[end]<=key){
191                 int temp=arr[end];
192                 arr[end]=arr[start];
193                 arr[start]=temp;
194             }
195             while(start<end&&arr[start]<=key)//循环前面的,从前往后找大于key的值
196                 start++;
197             if(arr[start]>=key){
198                 int temp=arr[start];
199                 arr[start]=arr[end];
200                 arr[end]=temp;
201             }
202         }
203         //递归调用
204         if(low<start)
205             quickSort(arr,low,start-1);
206         if(end<high)
207             quickSort(arr,end+1,high);
208 
209     }//打印输出数组
210     public static void printSortArr(int []arr){
211         StringBuilder res=new StringBuilder();
212         res.append("[");
213         for(int i=0;i<arr.length;i++){
214             if(i==arr.length-1){
215                 res.append(arr[i]+"]");
216             }
217             else{
218                 res.append(arr[i]+",");
219             }
220         }
221         System.out.println(res.toString());
222     }
223 }
224 1
225 2
226 3
227 4
228 5
229 6
230 7
231 8
232 9
233 10
234 11
235 12
236 13
237 14
238 15
239 16
240 17
241 18
242 19
243 20
244 21
245 22
246 23
247 24
248 25
249 26
250 27
251 28
252 29
253 30
254 31
255 32
256 33
257 34
258 35
259 36
260 37
261 38
262 39
263 40
264 41
265 42
266 43
267 44
268 45
269 46
270 47
271 48
272 49
273 50
274 51
275 52
276 结果:
277 快速排序结果
278 4.归并排序:
279 时间复杂度为:nlog(n)
280 排序原理:
281 (1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
282 (2)设定两个指针,最初位置分别为两个已经排序序列的起始位置
283 (3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
284 (4)重复步骤3直到某一指针达到序列尾
285 (5)将另一序列剩下的所有元素直接复制到合并序列尾
286 
287 package cn.dataStructures.Sort;
288 
289 /**
290  * **归并排序(理解描述)**:
291  * 思想:
292  * 1.对原始序列arr进行一半分割,设置原始序列的第一个索引low和最后一个索引值high,并创建临时序列
293  * 2.求出原始序列的中间索引mid=(low+high)/2,根据mid对序列分割
294  * 3.判断low是否小于high,满足则递归调用步骤1和2,一直对分割的序列再分割,直到剩余一个元素为止
295  * 4.对分割的序列分别根据其索引指向的元素值进行比较,小的则放入临时序列中,各序列索引加1、、
296  * 5.对剩余没有加入到临时序列中的元素直接添加到临时序列的最后的位置
297  * 6.将临时序列赋值给原始序列,此时原始序列就是已经排好序的序列
298  * @author lpq
299  *
300  */
301 
302 public class MergeSort {
303     public static void main(String[] args) {
304         System.out.println("排序前:");
305         int[] arr={51, 46, 20, 18, 65, 97, 82, 30, 77, 50 };
306         printSort(arr);
307         mergeSort(arr,0,arr.length-1);
308         System.out.println("排序后:");
309         printSort(arr);
310     }
311     //切分原始数组
312     public static void mergeSort(int[]arr,int low,int high){
313         int mid=(low+high)/2;//将序列按中间分开
314 
315         if(low<high){
316             //分开左边
317             mergeSort(arr,low,mid);
318             //右半边
319             mergeSort(arr,mid+1,high);
320             //将左右已经排序好的合并
321             merge(arr,low,mid,high);
322         }
323 
324 
325     }
326     public static void merge(int[]arr,int low,int mid,int high){
327         /**
328          * 这里的start和end分别是左半边序列和右半边序列的其实指针,分别指向各半边序列的第一个位置,随着的元素的比较而发生改变
329          * 而low和high是不发生改变的,一般来说low指的是序列的第一个索引0即low=0,high=arr.lenth-1,
330          * low和length值不发生改变
331          */
332         //临时数组(序列)
333         int [] temp=new int[high-low+1];
334         //左半边序列的指针(一般指向第一个位置low)
335         int start=low;
336         //右半边序列的指针
337         int end=mid+1;
338         //临时数组序列的索引
339         int k=0;
340         //把小的元素加入到临时数组中
341         while(start<=mid&&end<=high){
342             if(arr[start]<arr[end])
343                 temp[k++]=arr[start++];
344             else
345                 temp[k++]=arr[end++];
346         }
347         //把左边剩余元素加入到临时数组的后面
348         while(start<=mid)//这里不能用if判断,因为if只能判断一次,while只要满足条件就会一直循环判断下去
349             temp[k++]=arr[start++];
350         //把右半边剩余元素加入到临时数组的后面
351         while(end<=high)
352             temp[k++]=arr[end++];
353         //将排序好的临时数组复制给原始数组arr
354         for(int i=0;i<temp.length;i++){
355             arr[i+low]=temp[i];
356         }
357     }
358     public static void printSort(int []arr){
359         StringBuilder res=new StringBuilder();
360         res.append("[");
361         for(int i=0;i<arr.length;i++){
362             if(i==arr.length-1)
363                 res.append(arr[i]+"]");
364             else
365                 res.append(arr[i]+",");
366         }
367         System.out.println(res.toString());
368     }
369 }
370 
371 1
372 2
373 3
374 4
375 5
376 6
377 7
378 8
379 9
380 10
381 11
382 12
383 13
384 14
385 15
386 16
387 17
388 18
389 19
390 20
391 21
392 22
393 23
394 24
395 25
396 26
397 27
398 28
399 29
400 30
401 31
402 32
403 33
404 34
405 35
406 36
407 37
408 38
409 39
410 40
411 41
412 42
413 43
414 44
415 45
416 46
417 47
418 48
419 49
420 50
421 51
422 52
423 53
424 54
425 55
426 56
427 57
428 58
429 59
430 60
431 61
432 62
433 63
434 64
435 65
436 66
437 67
438 68
439 69
440 70
441 71
442 72
443 73
444 74
445 75
446 76
447 77
448 78
449 79
450 80
451 81
452 82
453 83
454 84
455 85
456 结果:
457 归并排序结果
458 时间复杂度分析:
459 递归法分析:
460 因为归并排序实现要将原始序列分为2部分,然后将这2个序列排序好后再赋值给临时序列temp,假设原始序列的元素个数为N,则时间复杂度的主要表达式为:T(N)=2T(N/2)+N;
461 1.首先将N/2带入主要表达式。结果:2T(N/2)=2(2T(N/4))+N=4T(N/4)+N,根据主要表达式可知:2T(N/2)=T(N)-N,所以可简化为:T(N)=4T(N/4)+2N
462 2.将N/4带入主表达式,同理可得到:T(N)=8T(N/8)+3N,可类比为:T(N)=2^kT(N/2^k)+kN
463 3.利用k=log(N),可得T(N)=NT(1)+Nlog(N)=Nlog(N)+N
464 4.时间复杂度为:O(Nlog(N))
465 二分搜索法:
466 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
467 注意:二分查找前提条件是:该序列有序
468 
469 package cn.lpq.sort;
470 
471 import java.util.Arrays;
472 
473 //二分查找前提是该数组有序
474 public class BinarySerch {
475     public static void main(String[] args) {
476         int []arr={11,22,33,44,55,66,77};
477         Arrays.sort(arr);//对数组排序
478         System.out.println(binarySerch(arr,55));
479     }
480     public static int binarySerch(int[]arr,int value){
481         int min=0;
482         int max=arr.length-1;
483         int mid=(min+max)/2;
484         while(arr[mid]!=value){
485             if(arr[mid]>value){
486                 max=mid-1;
487             }
488             else if(arr[mid]<value){
489                 min=mid+1;
490             }
491             mid=(min+max)/2;
492         }
493         if(min>max){
494             return -1;//说明数组为空或所查找元素不存在
495         }
496         return mid;
497 
498     }
499 }

 

posted on 2020-09-22 09:41  nidegui  阅读(180)  评论(0编辑  收藏  举报