快速排序原理简介
快速排序是我们之前学习的冒泡排序的升级,他们都属于交换类排序,都是采用不断的比较和移动来实现排序的。快速排序是一种非常高效的排序算法,它的实现,增大了记录的比较和移动的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减少了总的比较次数和移动次数。同时采用“分而治之”的思想,把大的拆分为小的,小的拆分为更小的,其原理如下:对于给定的一组记录,选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分,直到序列中的所有记录均有序为止。
一,最小的k个数
输入n个数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8,个数字,则最小的数字是1,2,3,4
基于O(n)的算法,可以用基于Partion函数解决这个问题,如果基于数组的第k个数字来调整,使得比第k个数字小的所有数字都位于数组的左边,比第k个数组大的所有数字都位于数组的右边,这样调整之后数组左边的k个数字就是最小的k个数字,不一定有序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in= new Scanner(System.in); int n=in.nextint(); int k=in.nextint(); int [] num= new int [n]; int [] out= new int [k]; for ( int i= 0 ;i<n;i++){ num[i]=in.nextint(); } Boolean b=GetMinK(n,num,k,out); if (b){ for ( int i= 0 ;i<k;i++){ System.out.print(out[i]+ " " ); } } } public static Boolean GetMinK( int uiInputNum, int [] pInputArray, int uiK, int [] pOutputArray){ if (pInputArray== null ||pOutputArray== null ||uiK>uiInputNum||uiInputNum<= 0 ||uiK<= 0 ){ return false ; } int start= 0 ; int end=uiInputNum- 1 ; int index=partition(pInputArray,start,end); while (index!=uiK- 1 ){ if (index>uiK- 1 ){ //index在k-1的右边 end=index- 1 ; index=partition(pInputArray,start,end); } else { start=index+ 1 ; index=partition(pInputArray,start,end); } } for ( int i= 0 ;i<uiK;i++){ pOutputArray[i]=pInputArray[i]; } return true ; } //partion分区函数,返回数组a的首元素快排的索引值index public static int partition( int [] a, int start, int end){ int privot=a[start]; int i=start; int j=end; while (i<j){ while (i<j&&privot<=a[j]){ j--; } swap(a,i,j); while (i<j&&privot>=a[i]){ i++; } swap(a,i,j); } return i; } public static void swap( int [] a, int i, int j){ int t=a[i]; a[i]=a[j]; a[j]=t; } } |
二,数组中出现次数超过一半的数字
数组中有一个数字出现次数超过数组长度的一半,请找出这个数字。例如1,2,3,2,2,2,5,4,2,数字2在数组中出现了5次,超过数组长度的一半,输出2
受快速排序的启发,在快速排序中,现在数组中选择一个数字,然后调整数组中的数字的顺序,使得比选中数字小的数字都排在它的左边,比选中数字大的数字都排在它的右边。
如果选中的数字的下标刚好是n/2,那么这个数字就是数组中的中位数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in= new Scanner(System.in); int n=in.nextint(); int [] num= new int [n]; for ( int i= 0 ;i<n;i++){ num[i]=in.nextint(); } int b=GetHalfNum(n,num); if (b!=- 1 ){ System.out.println(b); } } public static int GetHalfNum( int uiInputNum, int [] pInputArray){ if (pInputArray== null ||uiInputNum<= 0 ){ return - 1 ; } int middle=uiInputNum>> 1 ; //长度的一半 int start= 0 ; int end=uiInputNum- 1 ; int index=partition(pInputArray,start,end); while (index!=middle){ //如果不等于长度的一半说明就没有找到这个中位数 if (index>middle){ end=index- 1 ; index=partition(pInputArray,start,end); } else { start=index+ 1 ; index=partition(pInputArray,start,end); } } return pInputArray[index]; //index=middle } public static int partition( int [] a, int start, int end){ int privot=a[start]; int i=start; int j=end; while (i<j){ while (i<j&&privot<=a[j]){ j--; } swap(a,i,j); while (i<j&&privot>=a[i]){ i++; } swap(a,i,j); } return i; } public static void swap( int [] a, int i, int j){ int t=a[i]; a[i]=a[j]; a[j]=t; } } |
三,找出数组中第k个最小的数
例如给定数组1,5,2,6,8,0,6中,第4小的数字是5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in= new Scanner(System.in); int n=in.nextint(); int k=in.nextint(); int [] num= new int [n]; //int[] out=new int[k]; for ( int i= 0 ;i<n;i++){ num[i]=in.nextint(); } int b=GetMinK(n,num,k); if (b!=- 1 ){ System.out.println(b); } } public static int GetMinK( int uiInputNum, int [] pInputArray, int uiK){ if (pInputArray== null ||uiK>uiInputNum||uiInputNum<= 0 ||uiK<= 0 ){ return - 1 ; } int start= 0 ; int end=uiInputNum- 1 ; int index=partition(pInputArray,start,end); while (index!=uiK- 1 ){ //如果index不是k-1的位置 if (index>uiK- 1 ){ end=index- 1 ; index=partition(pInputArray,start,end); } else { start=index+ 1 ; index=partition(pInputArray,start,end); } } return pInputArray[index]; //返回的这个位置的数值 } public static int partition( int [] a, int start, int end){ int privot=a[start]; int i=start; int j=end; while (i<j){ while (i<j&&privot<=a[j]){ j--; } swap(a,i,j); while (i<j&&privot>=a[i]){ i++; } swap(a,i,j); } return i; } public static void swap( int [] a, int i, int j){ int t=a[i]; a[i]=a[j]; a[j]=t; } } |
总结
以上就是本文关于Java编程基于快速排序的三个算法题实例代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/tuke_tuke/article/details/51476630