一年前写的JavaSwing排序动画JavaSwing排序动画,当时由于自己对归并排序理解不深,一直认为归并排序需要额外的数组空间,那时候一直想写出归并排序动画,可惜一直没成功,后来放弃了。
就在昨天翻看算法导论时,看到了归并排序的伪代码,突然迸发出灵感,这个算法也许可以让以前排序动画里的归并排序跑起来。
归并排序算法如下:
private static void mergeSort(int[] data, int start, int end){
if(start < end){
int mid = (start + end) / 2;
mergeSort(data, start, mid);
mergeSort(data, mid + 1, end);
merge(data, start, mid, end);
}
}
private static void merge(int[] data, int start, int mid, int end){
int capacity1 = mid - start + 1;
int capacity2 = end - mid;
int dataRight[] = new int[capacity1 + 1];
int dataLeft[] = new int[capacity2 + 1];
int i, j = 0;
for(i = 0; i < capacity1; i++){
dataRight[i] = data[start + i];
}
dataRight[i] = 10000; // 哨兵值,取一个比数据里面任何一个数都大的值
for(j = 0; j < capacity2; j++){
dataLeft[j] = data[mid + j + 1];
}
dataLeft[j] = 10000; // 哨兵值,取一个比数据里面任何一个数都大的值
int indexA = 0;
int indexB = 0;
// notice the ArrayIndexOutofBounds, first we must check the indexA and indexB
try{
for(int k = start; k < end + 1; k++){
if(dataRight[indexA] <= dataLeft[indexB] ){
data[k] = dataRight[indexA];
mergeHistogram.showHistogram(data, k);
Thread.sleep(20);
indexA++;
}
else if(dataRight[indexA] > dataLeft[indexB]){
data[k] = dataLeft[indexB];
mergeHistogram.showHistogram(data, k);
Thread.sleep(20);
indexB++;
}
}
mergeHistogram.showHistogram(data);
}catch(InterruptedException ex){
ex.printStackTrace();
}
}
为什么哨兵值要取一个比排序数据都大的数,为什么声明的dataRight,dataLeft数组长度要比capacity大1
一切都是为了下面的归并过程
for(int k = start; k < end + 1; k++){
if(dataRight[indexA] <= dataLeft[indexB] ){
data[k] = dataRight[indexA];
mergeHistogram.showHistogram(data, k);
Thread.sleep(20);
indexA++;
}
else if(dataRight[indexA] > dataLeft[indexB]){
data[k] = dataLeft[indexB];
mergeHistogram.showHistogram(data, k);
Thread.sleep(20);
indexB++;
}
}
如果dataRight和dataLeft的长度是capacity的话,if(dataRight[indexA] <= dataLeft[indexB] )这句话总会越界一次而且只会越界一次,每次运行都会抛出异常,所以我们声明数组长度是capacity+1,尽管最后一个数据没用到,但是我们可以通过最后一个哨兵最大值比较,归并过程是把两个有序数组的元素按照从小到大的顺序归并成一个有序的数组,所以当for循环从start迭代到end + 1后,就停止迭代,此时的哨兵值也不会被归并进来,从而不影响排序结果,又能很容易地回避数组越界问题
运行效果如图:
源代码下载地址归并排序动画源代码
可运行jar下载地址归并排序可运行jar
视频地址归并排序动画视频