一般来说,判断一个数组或序列是正序,倒序还是乱序,需要我们将这个数组完整的遍历一遍后才能得出答案,它不像折半查找那样只处理少量的数据便能得出结论,因为一段包含成千上万个元素的有序序列,哪怕将其中两个元素的位置调换都能将这个序列变成乱序序列.如下面这段序列,只是数字8和9调换,就变成了乱序的.
[0, 1, 2, 3, 4, 5, 6, 7, 9, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
那么,怎样才能快速的判断序列是否有序呢?
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] // 序列arrayA
[19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] // 序列arrayB
[12, 7, 2, 5, 4, 14, 6, 13, 1, 16, 18, 19, 9, 8, 15, 11, 10, 0, 17, 3] // 序列arrayC
上面三段序列,分别为正序, 乱序和无序, 我们观察发现, 假如用冒泡法排序的单次冒泡循环对以上三个数组进行排序(排序顺序为从小到大), 第一个序列(正序序列)的冒泡次数为0; 第二个序列(倒序序列)的冒泡次数为 : 序列长度 - 1; 第三个序列(乱序序列)的冒泡次数介于上面两种序列之间, 且中途"气泡"(即需要进行交换的元素)发生了变化. 以此为规律, 我们可以利用计数冒泡次数和气泡是否发生了改变来判断一段有限序列是正序, 倒序还是无序.
// 根据数组需要冒泡的次数判断数组为顺序,逆序还是无序
public static int lookArray(int[] array) {
// 冒泡的次数
int count = 0;
// 上一次交换的"气泡"
int pop = array[0];
// 利用单次冒泡检验数组需要冒泡的次数
for (int j = 0; j < array.length - 1; j++) {
if (array[j] > array[j + 1]) {
// 判断此次需要向上冒的气泡是否和上次的相同,不同为乱序
if (pop != array[j]) {
// 若气泡发生了变化,证明是无序的,停止遍历,返回 0
return 0;
}
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
// 两相邻元素交换一次值,count计数一次
count++;
pop = array[j + 1];
//气泡向右移动,可能是逆序,对于逆序序列,还需保证气泡左侧所有的元素大于右侧
//所以当左侧最小的元素小于右侧元素时,为无序序列
if (j + 2 < array.length ){
if (array[j] < array[j+2]){
return 0;
}
}
}
}
// 正序返回 1, 倒序返回 -1
if (count == 0) {
return 1;
} else {
return - 1;
}
}
至此,我们实现了判断序列是否有序的算法. 我们可以在程序主入口main中调用这个方法,用一段乱序序列检验输出:
int[] array = {7,1,2,3,4,5,6,0};
int x = lookArray(array);
if (x == 1) {
System.out.println("正序");
} else if (x == - 1) {
System.out.println("逆序");
} else if(x == 0) {
System.out.println("无序");
}
输出为:
无序
至此,我们简单的实现了判断一段有限序列为正序,倒序,乱序的判别方法.