鸡尾酒排序:每一轮首先从前往后遍历出一个最大值放在最后面,然后从后往前遍历一个最小值放在最前面,即每一轮遍历选出一个最大值和一个最小值。
适合用于大部分元素已经有序的情况
时间复杂度和空间复杂度?是否稳定性?
简单粗暴的鸡尾酒排序:
public static void jiweijiu1(int[] a) {
int tem;
//首先确定外层循环遍历次数
for (int i = 0; i < a.length/2; i++) {
//从前往后遍历,选出最大值,外循环每遍历一次,
前面和后面分别多增加一个有序值。故这里
int j = i; j < a.length-1-i;
for (int j = i; j < a.length-1-i; j++) {
if (a[j]>a[j+1]) {
tem = a[j+1];
a[j+1] = a[j];
a[j] = tem;
}
}
//从后往前遍历,选出最小值,外循环每遍历一次,
前面和后面分别多增加一个有序值。故这里
int k = a.length-1-i; k > i;
for (int k = a.length-1-i; k > i; k--) {
if (a[k-1]>a[k]) {
tem = a[k];
a[k] = a[k-1];
a[k-1] = tem;
}
}
}
}
第一次优化:进行内层循环的时候,只要存在一次遍历(从前往后遍历或者从后往前遍历)没有交换元素则认为数组有序
public static void jiweijiu2(int[] a) {
int tem;
//当从前往后选最大值或者从后往前遍历选最小值的时候不存再元素的交换,
即可认为次数数组是有序的,
boolean isSorted;
//首先确定外层循环遍历次数
for (int i = 0; i < a.length/2; i++) {
isSorted = true;
//从前往后遍历,选出最大值,外循环每遍历一次,
前面和后面分别多增加一个有序值。故这里
int j = i; j < a.length-1-i;
for (int j = i; j < a.length-1-i; j++) {
if (a[j]>a[j+1]) {
tem = a[j+1];
a[j+1] = a[j];
a[j] = tem;
isSorted = false;
}
}
if (isSorted) {
break;
}
isSorted = true;
//从后往前遍历,选出最小值,外循环每遍历一次,
前面和后面分别多增加一个有序值。故这里
int k = a.length-1-i; k > i;
for (int k = a.length-1-i; k > i; k--) {
if (a[k-1]>a[k]) {
tem = a[k];
a[k] = a[k-1];
a[k-1] = tem;
isSorted = false;
}
}
if (isSorted) {
break;
}
}
}
第二次优化:进行内层循环遍历的时候,可以找到有序无序的边界下标index,来减少内层循环次数
自己写的,没有考虑到 j 和 k 的初始值,这里还可以在优化一下。
public static void jiweijiu3(int[] a) {
int tem;
boolean isSorted;
//从前往后遍历的有序无序下标index
int qianToHouIndex = a.length-1;
//从后往前遍历的有序无序下标index
int houToQianIndex = 0;
//分别用来记录每次交换元素对应的下标index,
在遍历循环中最后一次交换元素的下标index即可认为是有序无序边界
int changeQthIndex = 0;
int changeHtqIndex = 0;
for (int i = 0; i < a.length/2; i++) {
//前往后
isSorted = true;
for (int j = i; j < qianToHouIndex; j++) {
if (a[j]>a[j+1]) {
tem = a[j+1];
a[j+1] = a[j];
a[j] = tem;
isSorted = false;
changeQthIndex = j;
}
}
if (isSorted) {
break;
}
//循环中最后一次交换元素时的下标就是有序无序边界
qianToHouIndex = changeQthIndex;
//后往前
isSorted = true;
for (int k = a.length-1-i; k > houToQianIndex; k--) {
if (a[k-1]>a[k]) {
tem = a[k];
a[k] = a[k-1];
a[k-1] = tem;
isSorted = false;
changeHtqIndex = k;
}
}
if (isSorted) {
break;
}
houToQianIndex = changeHtqIndex;
}
}
考虑 j 和 k 初始值后如下,只修改了内循环中的两个for语句对 j 和 k 初始值赋值
每次外循环既可以确定数组前面部分的有序边界index,也可以确定后面部分的有序边界index,所有可以再次优化。
public static void jiweijiu3(int[] a) {
int tem;
boolean isSorted;
//从前往后遍历的有序无序下标index
int qianToHouIndex = a.length-1;
//从后往前遍历的有序无序下标index
int houToQianIndex = 0;
//分别用来记录每次交换元素对应的下标index,
在遍历循环中最后一次交换元素的下标index即可认为是有序无序边界
int changeQthIndex = 0;
int changeHtqIndex = 0;
for (int i = 0; i < a.length/2; i++) {
//前往后
isSorted = true;
for (int j = houToQianIndex; j < qianToHouIndex; j++) {
if (a[j]>a[j+1]) {
tem = a[j+1];
a[j+1] = a[j];
a[j] = tem;
isSorted = false;
changeQthIndex = j;
}
}
if (isSorted) {
break;
}
//循环中最后一次交换元素时的下标就是有序无序边界
qianToHouIndex = changeQthIndex;
//后往前
isSorted = true;
for (int k = qianToHouIndex; k > houToQianIndex; k--) {
if (a[k-1]>a[k]) {
tem = a[k];
a[k] = a[k-1];
a[k-1] = tem;
isSorted = false;
changeHtqIndex = k;
}
}
if (isSorted) {
break;
}
houToQianIndex = changeHtqIndex;
}
}