排序算法比较Word文档格式.docx
《排序算法比较Word文档格式.docx》由会员分享,可在线阅读,更多相关《排序算法比较Word文档格式.docx(19页珍藏版)》请在冰豆网上搜索。
k++){
24//每轮循环中从最后一个元素开始向前起泡,直到i=k止,即i等于轮次止
25for(inti=end-from;
i>
=k;
i--){
26//按照一种规则(后面元素不能小于前面元素)排序
27if(pare(array[i],array[i-1])<
0){
28//如果后面元素小于了(当然是大于还是小于要看比较器实现了)前面的元素,则前后交换
29swap(array,i,i-1);
30}
31}
32}
33}
34
35/**
36*测试
37*@paramargs
38*/
39publicstaticvoidmain(String[]args){
40Integer[]intgArr={7,2,4,3,12,1,9,6,8,5,11,10};
41BubbleSort<
Integer>
sort=newBubbleSort<
();
42BubbleSort.testSort(sort,intgArr);
43BubbleSort.testSort(sort,null);
44}
45}
快速排序
快速排序采用了分治法的思想,把大的问题分解为同类型的小问题。
一般分如下步骤:
1)选择一个中枢元素(有很多选法,我的实现里使用第一个元素为中枢的简单方法)
2)以该中枢元素为基准点,将小于中枢的元素放在中枢后集合的前部分,比它大的在集合后部分,待集合基本排序完成后(此时前部分元素小于后部分元素),把中枢元素放在合适的位置。
3)根据中枢元素最后确定的位置,把数组分成三部分,左边的,右边的,枢纽元素自己,对左边的,右边的分别递归调用快速排序算法即可。
这里的重点与难点在于第二步,实现的方式有很多种,我这里实现了三种。
第一种实现(partition1方法):
以第一个元素为中枢元素,在中枢元素后面集合中从前往后寻找第一个比中枢元素小的元素,并与第一个元素交换,然后从剩余的元素中寻找第二个比中枢元素小的元素,并与第二位元素交换,这样直到所有小于中枢元素找完为止,并记下最后一次放置小于中枢的元素位置minIndex(即小于中枢与大于中枢的分界),并将中枢元素与minIndex位置元素互换,然后对中枢元素两边的序列进行同样的操作。
此种实现最为简洁,处理过程中不需要把中枢元素移来移去,只是在其它元素完成基本排序后(前部分小于后部分元素)再把中枢元素放置到适当的位置
第二种实现(partition2方法):
以第一个元素为中枢元素,刚开始时使用低指针指向中枢元素。
当中枢元素在低指针位置时,此时我们判断高指针指向的元素是否小于中枢元素,如果大于中枢元素则高指针继续向头移动,如果小于则与中枢元素交换,此时中枢元素被移到了高指针位置;
当中枢元素在高指针位置时,我们此时判断低指针指向的元素是否大于中枢元素,如果小于中枢元素则低指针继续向尾移动,如果大于则与中枢元素交换,此时中枢元素又回到了低指针位置;
这时是拿高还是低指针所指向的元素与中枢比较时根据前面逻辑来处理,直到高低指针指向同一位置则完成一轮排序,然后再对中枢元素两边的序列进行同样的操作直到排序完成
此种实现逻辑比较好理解,中枢元素的永远在低指针或指针所指向的位置,每次找到需处理的元素后,要与中枢交换,中枢就像皮球一样从这里踢到那里,又从那里踢到这里。
但此种实现会频繁地交换中枢元素,性能可能不如第一种
第三种实现(partition3方法):
此种方式与前两种方式不太一样,同时移动高低指针,低指针向尾找出大于等于中枢的元素,而高向头找出小于中枢的元素,待两者都找出后交换高低指针所指向的元素,直到高低指针指向同一位置止,然后比较中枢与高低指针所指向的元素大小,如果中枢元素大,则直接与高低指针元素交换,如果中枢元素小于等于高低指针元素,则中枢元素与高低指针前一元素交换,完成一轮比较,然后再对中枢元素两边的序列进行同样的操作直到排序完成
此种方式有点难度,在移动元素时要注意的是:
与中枢相等的元素也要向集合后部移动,不然的话如[3,3,0,3,3]第一轮排序结果不准确,虽然最后结果正确。
当中枢后面的元素集合移动完成后,还得要把中枢元素放置在集合中的合适位置,这就需要找准集合中前部分与后部分的边界,最后只能把中枢元素与最后一个小于中枢的元素进位置互换。
但此种实现方式与第一种有点像,也不需要把中枢元素调来调去的,而是待后面集合排序完成后将中枢放入适当位置
46packagesort;
47
48importjava.util.Arrays;
49importjava.util.Comparator;
50
51/**
52*快速排序算法
53*@authorjzj
54*@date2009-12-9
55*
56*@param<
57*/
58publicclassQuickSort<
59
60/**
61*排序算法的实现,对数组中指定的元素进行排序
62*@paramarray待排序的数组
63*@paramfrom从哪里开始排序
64*@paramend排到哪里
65*@paramc比较器
66*/
67publicvoidsort(E[]array,intfrom,intend,Comparator<
68quickSort(array,from,end,c);
69}
70
71/**
72*递归快速排序实现
73*@paramarray待排序数组
74*@paramlow低指针
75*@paramhigh高指针
76*@paramc比较器
77*/
78privatevoidquickSort(E[]array,intlow,inthigh,Comparator<
79/*
80*如果分区中的低指针小于高指针时循环;
如果low=higth说明数组只有一个元素,无需再处理;
81*如果low>
higth,则说明上次枢纽元素的位置pivot就是low或者是higth,此种情况
82*下分区不存,也不需处理
83*/
84if(low<
high){
85//对分区进行排序整理
86intpivot=partition1(array,low,high,c);
87/*
88*以pivot为边界,把数组分成三部分[low,pivot-1]、[pivot]、[pivot+1,high]
89*其中[pivot]为枢纽元素,不需处理,再对[low,pivot-1]与[pivot+1,high]
90*各自进行分区排序整理与进一步分区
91*/
92quickSort(array,low,pivot-1,c);
93quickSort(array,pivot+1,high,c);
94}
95
96}
97
98/**
99*实现一
100*
101*@paramarray待排序数组
102*@paramlow低指针
103*@paramhigh高指针
104*@paramc比较器
105*@returnint调整后中枢位置
106*/
107privateintpartition1(E[]array,intlow,inthigh,Comparator<
108EpivotElem=array[low];
//以第一个元素为中枢元素
109//从前向后依次指向比中枢元素小的元素,刚开始时指向中枢,也是小于与大小中枢的元素的分界点
110intborder=low;
111
112/*
113*在中枢元素后面的元素中查找小于中枢元素的所有元素,并依次从第二个位置从前往后存放
114*注,这里最好使用i来移动,如果直接移动low的话,最后不知道数组的边界了,但后面需要
115*知道数组的边界
116*/
117for(inti=low+1;
i<
=high;
i++){
118//如果找到一个比中枢元素小的元素
119if(pare(array[i],pivotElem)<
120swap(array,++border,i);
//border前移,表示有小于中枢元素的元素
121}
122}
123/*
124*如果border没有移动时说明说明后面的元素都比中枢元素要大,border与low相等,此时是
125*同一位置交换,是否交换都没关系;
当border移到了high时说明所有元素都小于中枢元素,此
126*时将中枢元素与最后一个元素交换即可,即low与high进行交换,大的中枢元素移到了序列最
127*后;
如果low<
minIndex<
high,表明中枢后面的元素前部分小于中枢元素,而后部分大于
128*中枢元素,此时中枢元素与前部分数组中最后一个小于它的元素交换位置,使得中枢元素放置在
129*正确的位置
130*/
131swap(array,border,low);
132returnborder;
133}
134
135/**
136*实现二
137*
138*@paramarray待排序数组
139*@paramlow待排序区低指针
140*@paramhigh待排序区高指针
141*@paramc比较器
142*@returnint调整后中枢位置
143*/
144privateintpartition2(E[]array,intlow,inthigh,Comparator<
145intpivot=low;
//中枢元素位置,我们以第一个元素为中枢元素
146//退出条件这里只可能是low=high
147while(true){
148if(pivot!
=high){//如果中枢元素在低指针位置时,我们移动高指针
149//如果高指针元素小于中枢元素时,则与中枢元素交换
150if(pare(array[high],array[pivot])<
151swap(array,high,pivot);
152//交换后中枢元素在高指针位置了
153pivot=high;
154}else{//如果未找到小于中枢元素,则高指针前移继续找
155high--;
156}
157}else{//否则中枢元素在高指针位置
158//如果低指针元素大于中枢元素时,则与中枢元素交换
159if(pare(array[low],array[pivot])>
160swap(array,low,pivot);
161//交换后中枢元素在低指针位置了
162pivot=low;
163}else{//如果未找到大于中枢元素,则低指针后移继续找
164low++;
165}
166}
167if(low==high){
168break;
169}
170}
171//返回中枢元素所在位置,以便下次分区
172returnpivot;
173}
174
175/**
176*实现三
177*
178*@paramarray待排序数组
179*@paramlow待排序区低指针
180*@paramhigh待排序区高指针
181*@paramc比较器
182*@returnint调整后中枢位置
183*/
184privateintpartition3(E[]array,intlow,inthigh,Comparator<
185intpivot=low;
186low++;
187//----调整高低指针所指向的元素顺序,把小于中枢元素的移到前部分,大于中枢元素的移到后面部分
188//退出条件这里只可能是low=high
189
190while(true){
191//如果高指针未超出低指针
192while(low<
193//如果低指针指向的元素大于或等于中枢元素时表示找到了,退出,注:
等于时也要后移
194if(pare(array[low],array[pivot])>
=0){
195break;
196}else{//如果低指针指向的元素小于中枢元素时继续找
197low++;
198}
199}
200
201while(high>
low){
202//如果高指针指向的元素小于中枢元素时表示找到,退出
203if(pare(array[high],array[pivot])<
204break;
205}else{//如果高指针指向的元素大于中枢元素时继续找
206high--;
207}
208}
209//退出上面循环时low=high
210if(low==high){
211break;
212}
213
214swap(array,low,high);
215}
216
217//----高低指针所指向的元素排序完成后,还得要把中枢元素放到适当的位置
218if(pare(array[pivot],array[low])>
219//如果退出循环时中枢元素大于了低指针或高指针元素时,中枢元素需与low元素交换
220swap(array,low,pivot);
221pivot=low;
222}elseif(pare(array[pivot],array[low])<
223swap(array,low-1,pivot);
224pivot=low-1;
225}
226
227//返回中枢元素所在位置,以便下次分区
228returnpivot;
229}
230
231/**
232*测试
233*@paramargs
234*/
235publicstaticvoidmain(String[]args){
236Integer[]intgArr={3,1,1,1,1,1,1};
237QuickSort<
sort=newQuickSort<
238QuickSort.testSort(sort,intgArr);
239QuickSort.testSort(sort,null);
240}
241}
归并排序
242packagesort;
243
244importjava.lang.reflect.Array;
245importjava.util.Comparator;
246
247/**
248*归并排序算法
249*@authorjzj
250*@date2009-12-11
251*
252*@param<
253*/
254publicclassMergeSort<
255
256/**
257*排序算法的实现,对数组中指定的元素进行排序
258*@paramarray待排序的数组
259*@paramfrom从哪里开始排序
260*@paramend排到哪里
261*@paramc比较器
262*/
263publicvoidsort(E[]arr,intfrom,intend,Comparator<
264partition(arr,from,end,c);
265}
266
267/**
268*递归划分数组
269*@paramarr
270*@paramfrom
271*@paramend
272*@paramcvoid
273*/
274privatevoidpartition(E[]arr,intfrom,intend,Comparator<
275//划分到数组只有一个元素时才不进行再划分
276if(from<
end){
277//从中间划分成两个数组
278intmid=(from+end)/2;
279partition(arr,from,mid,c);
280partition(arr,mid+1,end,c);
281//合并划分后的两个数组
282merge(arr,from,end,mid,c);
283}
284}
285
286/**
287*数组合并,合并过程中对两部分数组进行排序
288*前后两部分数组里是有序的
289*@paramarr
290*@paramfrom
291*@paramend
292*@parammid
293*@paramcvoid
294*/
295privatevoidmerge(E[]arr,intfrom,intend,intmid,Comparator<
296E[]tmpArr=(E[])Array.newInstance(arr[0].getClass(),end-from+1);
297inttmpArrIndex=0;
//指向临时数组
298intpart1ArrIndex=from;
//指向第一部分数组
299intpart2ArrIndex=mid+1;
//指向第二部分数组
300
301//由于两部分数组里是有序的,所以每部分可以从第一个元素依次取到最后一个元素,再对两部分
302//取出的元素进行比较。
只要某部分数组元素取完后,退出循环
303while((part1ArrIndex<
=mid)&
&
(part2ArrIndex<
=end)){
304//从两部分数组里各取一个进行比较,取最小一个并放入临时数组中
305if(pare(arr[part1ArrIndex],arr[part2ArrIndex])<
306//如果第一部分数组元素小,则将第一部分数组元素放入临时数组中,并且临时数组指针
307//tmpArrIndex下移一个以做好下次存储位置准备,前部分数组指针part1ArrIndex
308//也要下移一个以便下次取出下一个元素与后部分数组元素比较
309tmpArr[tmpArrIndex++]=arr[part1ArrIndex++];
310}else{
311//如果第二部分数组元素小,则将第二部分数组元素放入临时数组中
312tmpArr[tmpArrIndex++]=arr[part2ArrIndex++];
313}
314}
315//由于退出循环后,两部