版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zgcqflqinhao/article/details/83537017
一、鸡尾酒排序
鸡尾酒排序是冒泡排序的一种变形。它与冒泡排序的不同之处在于排序时是以双向在序列中进行排序。
二、原理
鸡尾酒排序的原理跟冒泡排序差不多,只不过冒泡排序每一轮的比较都是从左至右依次比较,而鸡尾酒排序则是一轮从左至右比较,下一轮从右至左比较。
假如有一个这样的数组:{2, 3, 4, 5, 6, 7, 8, 1},如果按照冒泡排序的比较方式,会是这样的流程:
可以看到其实每次移动的只是元素 1,如果按照冒泡排序的原理,一共需要进行 7 轮比较,显然这是可以进行优化的,在第 1 轮比较后,第 2 轮则从右至左比较,将最小的元素交换到最左侧,这样就可以减少比较的总次数:
三、代码实现
public static int[] cockTailSort1(int[] origin) {
if (origin == null || origin.length == 0) {
return new int[]{};
}
System.out.println("origin--->" + Arrays.toString(origin));
int index = 0;
for (int i = 0; i < origin.length - 1; i++) {
boolean isSorted = true;
if (i % 2 == 0) {
for (int j = 0; j < origin.length - i - 1; j++) {
if (origin[j] > origin[j + 1]) {
int temp = origin[j];
origin[j] = origin[j + 1];
origin[j + 1] = temp;
isSorted = false;
}
index++;
}
} else {
for (int j = origin.length - i - 1; j > 0; j--) {
if (origin[j - 1] > origin[j]) {
int temp = origin[j - 1];
origin[j - 1] = origin[j];
origin[j] = temp;
isSorted = false;
}
index++;
}
}
System.out.println("第" + (i + 1) + "次比较后" + "--->" + Arrays.toString(origin) + ",isSorted--->" + isSorted);
if (isSorted) {
break;
}
}
System.out.println("index--->" + index);
System.out.println("sortedArray--->" + Arrays.toString(origin));
return origin;
}
使用测试代码运行一遍:
@Test
public void testCockTailSort1() {
// int[] intArray = new int[10];
// for (int i = 0; i < intArray.length; i++) {
// intArray[i] = new Random().nextInt(100);
// }
int[] intArray = new int[]{2, 3, 4, 5, 6, 7, 8, 1};
cockTailSort1(intArray);
}
运行结果如下:
可以看到相较于冒泡排序,总的比较次数已经从 8 次减少到了 3 次。
四、优化
同样,鸡尾酒排序也可以像冒泡排序一样进行优化,记录左右比较位置,减少内循环次数:
public static int[] cockTailSort(int[] origin) {
if (origin == null || origin.length == 0) {
return new int[]{};
}
// 记录右侧最后一次交换的位置
int lastRightExchangeIndex = 0;
// 记录左侧最后一次交换的位置
int lastLeftExchangeIndex = 0;
// 无序数列的右边界,每次比较只需要比到这里为止
int rightSortBorder = origin.length - 1;
// 无序数列的左边界,每次比较只需要比到这里为止
int leftSortBorder = 0;
System.out.println("origin--->" + Arrays.toString(origin));
int index = 0;
for (int i = 0; i < origin.length - 1; i++) {
boolean isSorted = true;
if (i % 2 == 0) {
System.out.print("从 " + leftSortBorder + " 比较到 " + rightSortBorder + ",");
for (int j = leftSortBorder; j < rightSortBorder; j++) {
if (origin[j] > origin[j + 1]) {
int temp = origin[j];
origin[j] = origin[j + 1];
origin[j + 1] = temp;
isSorted = false;
lastRightExchangeIndex = j;
}
index++;
}
} else {
System.out.print("从 " + rightSortBorder + " 比较到 " + leftSortBorder + ",");
for (int j = rightSortBorder; j > leftSortBorder; j--) {
if (origin[j] < origin[j - 1]) {
int temp = origin[j];
origin[j] = origin[j - 1];
origin[j - 1] = temp;
isSorted = false;
lastLeftExchangeIndex = j;
}
index++;
}
}
leftSortBorder = lastLeftExchangeIndex;
rightSortBorder = lastRightExchangeIndex;
System.out.println("第" + (i + 1) + "次比较后" + "--->" + Arrays.toString(origin) + ",isSorted--->" + isSorted);
if (isSorted) {
break;
}
}
System.out.println("index--->" + index);
System.out.println("sortedArray--->" + Arrays.toString(origin));
return origin;
}
运行结果如下:
五、总结
时间复杂度
同冒泡排序,假设原始数组长度为 n,则外循环 n 次,每次遍历嵌套一个内循环,所以时间复杂度为 O(n²)。
空间复杂度
同冒泡排序,空间复杂度为 O(1)。
优点
1.在某些特定情况下,鸡尾酒排序相较于冒泡排序可以减少大量比较轮数,算是冒泡排序的一种优化。
缺点
1.代码量相较于冒泡排序增加了几乎一倍。