算法思想
鸡尾酒排序:基于冒泡排序的一种升级排序法
简单来说,冒泡排序每次从头走到尾,然后再跳到头,重新开始比较交换,往尾部走;鸡尾酒排序呢,是走回头路,从头到尾然后再从尾到头,如此往复;
同时加入了对冒泡排序的另一种优化:将有序区域和无序区域分隔开,减少比较次数,每趟循环利用变量 flag 记录交换位置,最后一次交换位置即是有序区和无序区的边界 index2 和 index1(index2<=index1),[index2,index1]为无序区域。
程序运行过程中,有序区逐渐扩大,无序区逐渐减小,最终整个数组达到有序的状态;
代码
#include<cstdio>
#include<iostream>
#include<stdlib.h>
using namespace std;
void getdata(int *a,int n);//获取n个数据存放到数组a中
int *copy(int *b,int n);//复制含有n个数据的数组b,返回复制得到的数组
void showarray(int *a,int n);//显示含有n个数据的数组a
void swap(int *a,int *b);//交换a,b指向的两个数据
void cocktail(int *b, int n);//对含有n个数据的数组b进行鸡尾酒排序
int main(void)
{
int *a;
int n=10;
a=new int[n+1];
getdata(a,n);
cocktail(a,n);
delete []a;
return 0;
}
void getdata(int *a,int n)//获取n个数据存放到数组a中
{
for (int i= 1; i <= n; i++)
{
a[i] = rand() % 1000;
//a[i]=i;
//a[i]=n-i;
}
}
int *copy(int *b,int n)//复制含有n个数据的数组b,返回复制得到的数组
{
int i;
int *a=new int[n+1];
for (i = 1; i <= n; i++)
a[i]=b[i];
return a;
}
void showarray(int *a,int n)//显示数组a,a有n个数据
{
int j=0;
for (int i = 1; i <= n; i++)
{
cout<<a[i]<<" ";
j++;
if (j % 15 == 0)
cout<<endl;
}
cout<<endl;
if (j % 15 != 0)
cout<<endl;
}
void swap(int *a,int *b)//交换a,b指向的两个数据
{
int temp=(*a);
(*a)=(*b);
(*b)=temp;
}
void cocktail(int *b, int n)//对含有n个数据的数组b进行鸡尾酒排序
{
int *a=copy(b,n);
int index1,index2;
int flag;
int i,j; //计数器
//showarray(a,n);
index1=0;
for (i = 1; i < n; i++)
{
if (a[i] > a[i+1])
{
swap(&a[i], &a[i+1]);
index1=i; //记录第一趟排序最后交换的位置
}
}
//showarray(a,n);
index2=index1;
for (j = index2; j > 1; j--)
{
if (a[j-1] > a[j])
{
swap(&a[j-1], &a[j]);
index2=j; //记录第二趟排序最后交换的位置
}
}
//showarray(a,n);
flag=index2;
while (index1 != index2)
{
for (i = index2; i < index1; i++)
{
if (a[i] > a[i+1])
{
swap(&a[i], &a[i+1]);
flag=i;
}
}
//showarray(a,n);
index1=flag;
if(index1==index2)
break;
for (j = index1; j > index2; j--)
{
if (a[j-1] > a[j])
{
swap(&a[j-1], &a[j]);
flag=j;
}
}
//showarray(a,n);
index2=flag;
}
cout<<"\n鸡尾酒排序:\n";
showarray(a,n);
delete []a;
}
小结
- 优点:在大部分元素有序的情况下可以减少排序的回合数;
- 缺点:代码量增加,编程较难;