一、鸡尾酒排序
鸡尾酒排序是冒牌排序的一个改良版,与冒泡排序相不同的是鸡尾酒排序是运用双指针,一个指针(以下称为start指针)从左向右遍历另一个指针(以下称为end指针)从右向左遍历,在遍历的过程中,end指针如果遇到比自己大的数,就与他交换位置,把较大的数放在后面,start指针则相反,在遍历过程中,如果遇到比自己小的数就把他交换到前面。经过一次排序后我们可以确保这组数中最大的数在n-1的位置上,而最小的数在0位置上。然后在下一次循环的时候我们就可以不再去考虑这两个数,这样每次减少需要排序的两个数,就可以节省很多时间,同时这种节省后的排序方法很像一杯鸡尾酒的形状,所以也被称之为——鸡尾酒排序。
下面我们用{3,1,6,5,4,7}这组数据来模拟一下,此时我们的start→3,end→7
第一次——1,3,6,5,4,7
第二次——1,3,4,5,6,7
排序完成。下面是代码实现
public class jiweijiuSort {
public static void main(String args[]) {
int a[] = {3,1,6,5,4,7};
sort(a);
for(int i=0;i<a.length;i++)
{
System.out.println(a[i]);
}
}
private static void sort(int[] a) {
int start=0;
int end = a.length-1;
while(start<end) {
for(int j=end;j>start;j--)
{
if(a[j]<a[j-1])
{
swap(a,j,j-1);
}
}
for(int j=start;j<end;j++)
{
if(a[j]>a[j+1])
{
swap(a,j,j+1);
}
}
start++;
end--;
}
}
public static void swap(int []a,int b,int c) {
int temp;
temp = a[b];
a[b] = a[c];
a[c] = temp;
}
二、希尔排序
希尔排序是插入排序的一个改良版,希尔排序通过把一个长度较大大的数组,拆分成若干个长度较小数组,然后对小数组进行插入排序,然后使得小数组有序,进而使得大数组有序。当然我们在拆分的过程中,不可能真正的把它拆分成几个小的数组,我们只是用到这样的想法而已,我们通过设立一个分组数gap,通过跳跃取值,来实现数组元素的分组比较,在比较的过程中运用插入排序,然后经过多次小数组合并使得数据整体有序
下面为代码实现
public class ShellSort {
public static void main(String args[]) {
int[] a = {3,1,6,5,4,7};
sort(a);
for(int i=0;i<a.length;i++)
{
System.out.println(a[i]);
}
}
public static void sort(int[] a) {
int temp;
int gap = a.length;
while(gap>1) {
gap=gap/2;
for(int i=gap;i<a.length;i++)
{
for(int j=i;j>= gap && a[j]<a[j-gap];j-=gap) {
swap(a,j,j-gap);
}
}
}
}
private static void swap(int[] a, int b, int c) {
int temp;
temp = a[b];
a[b] = a[c];
a[c] = temp;
}
}
三、快速排序(填坑法)与快速排序(双指针法)
(1)双指针法
快速排序是一种十分实用的排序方法,首先,我们需要设立一个基准值pivot(通常情况下我们会把数组的第一个元素设立为基准值),以及两个分别从左右遍历数组的指针left和right,设立i从left开始从左往右遍历,j从right开始从右往左遍历,当i遇到比基准值大的数时就停下,当j遇到比基准值小的数的时候也停下,然后交换i和j的值,此时自i指向的数前面的数组元素,都小于基准值,自j以后包括j指向的数组元素都大于基准值,因为我们的a[0]已经被pivot暂存,所以我们可以吧a[i]的值赋给a[0],然后把pivot的值赋给a[i],这样既保证了基准值两侧得数全都大于或小于基准值,并且整个数组内数据完整,没有缺少,这就是一轮排序需要做的事情,然后我们再通过递归再次调用本身,分别对基准值左右两侧的数据分别再次进行排序。
下面是代码实现
public class kuaisuSort {
public static void main(String args[]) {
int[] a = {3,1,6,5,4,7};
sort(a,0,a.length-1);
for(int i=0;i<a.length;i++) {
System.out.println(a[i]);
}
}
private static void sort(int[] a,int left,int right) {
if(left>right) {
return;
}
int pivot = a[left];
int i = left;
int j = right;
while(i!=j) {
while(a[j]>= pivot && i<j) {
j--;
}
while(a[i]<= pivot && i<j) {
i++;
}
swap(a,i,j);
}
a[left] = a[i];
a[i] = pivot;
sort(a,left,i-1);
sort(a,j+1,right);
}
public static void swap(int []a,int b,int c) {
int temp;
temp = a[b];
a[b] = a[c];
a[c] = temp;
}
}
(2)填坑法
填坑法与双指针法的大概情况基本相同,主要不同的地方就在于双指针法采用的是数交换的方法,而填坑法则是采用数值覆盖。下面是代码实现
public class kuaisuSorttiankeng {
public static void main(String args[]) {
int[] a = {4,1,6,5,3,7};
sort(a,0,a.length-1);
for(int i=0;i<a.length;i++) {
System.out.println(a[i]);
}
}
private static void sort(int[] a,int left,int right) {
if(left>=right) {
return;
}
int pivot = a[left];
int i = left;
int j = right;
while(i!=j) {
while(a[j]>= pivot && i<j) {
j--;
}
a[i] = a[j];
while(a[i]<= pivot && i<j) {
i++;
}
a[j] = a[i];
}
a[j] = pivot;
sort(a,left,i-1);
sort(a,j+1,right);
}
}
这里划重点
填坑法的赋值运算一定要放在循环外面,切记切记切记!!!
while(a[j]>= pivot && i<j) {
j--;
}
a[i] = a[j];
while(a[i]<= pivot && i<j) {
i++;
}
a[j] = a[i];
就比如这里的赋值,如果在循环里面进行的话就会出现i和j数据位置的错误,导致数组元素丢失,所以一定要在循环外面赋值!