划 分
划分数据就是把数据分为两组,使所有关键字大于特定值的数据项在一组,是所有关键字小于特定值的数据项在另一组。
package com.gaojipaixu.partition;public class Arraypar{ private long[] theArray; private int nElems; public Arraypar(int max){ theArray = new long[max]; nElems = 0; } public void insert(long value){ theArray[nElems] = value; nElems++; } public int size(){ return nElems; } public void display(){ System.out.print("A="); for (int i = 0; i < nElems; i++) { System.out.print(theArray[i]+" "); } System.out.println(""); } public int partitionIt(int left,int right,long pivot){ int leftPtr = left-1; int rightPtr = right+1; while(true){ while(leftPtrleft && theArray[--rightPtr]>pivot) ; if(leftPtr >= rightPtr) break; else{ long temp ; temp = theArray[leftPtr]; theArray[leftPtr] = theArray[rightPtr]; theArray[rightPtr] = temp; } } return leftPtr; }}
public static void main(String[] args) { int maxSize = 16; Arraypar arr ; arr = new Arraypar(maxSize); for (int i = 0; i < maxSize; i++) { long n = (int)(java.lang.Math.random()*199); arr.insert(n); } arr.display(); long pivot = 99; System.out.println("Pivot is "+pivot); int size = arr.size(); int partDex = arr.partitionIt(0, size-1, pivot); System.out.println(",Partition is at index "+partDex); arr.display(); } //输出:A=170 142 81 128 131 39 16 186 84 35 46 195 174 114 144 103 Pivot is 99,Partition is at index 6A=46 35 81 84 16 39 131 186 128 142 170 195 174 114 144 103
可以看出划分是成功的:前6个数字都比枢纽99小;后8个数字则都大于枢纽。
注意划分的过程不一定要像这个例子一样把数组划分成大小相同的两半;这取决于枢纽及数据关键字的值。有可能一组中数据项个数多于另一组的数据项个数。
划分算法
划分算法由两个指针开始工作,两个指针分别指向数组的两头。(这里使用“指针”这个词是指示数组数据项的,而不是C++中所说的指针。)在左边的指针,leftPtr,向右移动,而在右边的指针,rightPtr,向左移动。
实际上,leftPtr初始化是时在第一个数据项的左边一位,rightPtr是在最后一个数据项的右边一位,这是因为在它们工作之前,它们都要分别的加一和减一。
停止和交换
当leftPtr遇到比枢纽小的数据项时,它继续右移,因为这个数据项的位置已经处在数组的正确一边了。但是,当遇到比枢纽大的数据项时,它就停下来,类似的,当rightPrt遇到大于枢纽的数据项时,它继续左移但是当发现比枢纽小的数据项时,它也停下来。当两个内层的while循环,第一个应用leftPtr,第二个应用于rightPrt,控制这个扫描过程。因为指针退出了while循环,所以它停止移动。下面是一段扫描不在适当位置上的数据项的简化代码:
while(theArray[++leftPtr] < pivot) //find bigger item ; //(nop)while(theArray[--right]>pivot) //find smaller item ; //(nop)swap(lefgPtr,rightPtr); //swap elements
第一个while循环在发现比枢纽大的数据项时退出;第二个循环在发现小的数据项时退出。当这两个循环都退出之后,leftPtr和rightPrt都指着在数组的错误一方位置上的数据项,所以交换着两个数据项。
256