各种排序算法的整合
相关代码:
#include<iostream>
using namespace std;
//内部排序 插、交、选、归、基
/**
一、插入排序
1)直接插入排序,找到插入位置,插入位置的元素往后移动
2)折半插入排序,是对寻找插入位置的时间复杂度进行的优化,用到分治的思想
相应的每一趟中比较的次数会减少,每趟比较的次数为O(log2n);
3)希尔排序(缩小增量排序),先追求表中的元素部分有序,在逐渐逼近全局有序
*/
/**
1、直接插入排序
*/
void InsertSort(int a[],int n)
{
int i,j,temp;
for(i=1;i<n;i++)
{
if(a[i]<a[i-1])
{
temp=a[i];
//插入元素之前都是已经排好序的从小到大的元素,
//只要是比插入元素大的都向后移
for(j=i-1;j>=0&&a[j]>temp;j--)
{
a[j+1]=a[j];
}
temp=a[j+1];
}
}
}
/**
折半插入排序
*/
void BinaryInsertSort(int a[],int n)
{
int i,j,left,right,mid,temp;
for(i=1;i<n;i++)
{
//待插入元素temp
temp=a[i];
left=0;
right=i-1;
//我们的任务就是找到比待插入元素小的元素
while(left<=right)
{
mid=(left+right)>>1;
//当划分元素比待插入元素大,查找左半子表
if(a[mid]>temp)
right=mid-1;
else
left=mid+1;
}
//跳出循环时left>right,我们要插入的位置就是left位置(或者说是right后边的一个元素位置)
//但要注意的是:往后移动元素时,要从后边开始往后移动,防止元素被覆盖掉
for(j=i-1;j>=left;j--)//注意i的位置是待插入元素的位置
{
a[j+1]=a[j];
}
//跳出循环时j=left-1;
a[j+1]=temp;
}
}
/**
希尔排序,对间隔为d的元素进行直接插入排序,d在不断的缩小,
init:d=n/2-->d=1,每次d/=2;
不稳定
*/
void ShellSort(int a[],int n)
{
int i,j,temp,d;
for(d=n/2;d>=1;d/=2)
{
for(i=d;i<n;i++)
{
if(a[i]<a[i-d])
{
temp=a[i];
for(j=i-d;j>=0&&a[j]>temp;j-=d)
{
a[j+d]=a[j];
}
a[j+d]=temp;
}
}
}
}
/**
二、交换排序
1)冒泡排序
2)快速排序
*/
//冒泡排序
void BubbleSort(int a[],int n)
{
int i,j;
//从前往后冒泡
for(i=0;i<n-1;i++)//需要进行n-1趟冒泡
{
bool flag=false;//判断是否发生交换
for(j=0;j<n-i;j++)
{
if(a[j]>a[j+1])
swap(a[j],a[j+1]);
flag=true;
}
if(flag==false)
return;
}
//从后往前冒泡
// for(i=0;i<n-1;i++)
// {
// bool flag=false;
// for(j=n-1;j>i;j--)//j>i而且不能等于i,否则下边a[j-1]会出现越界
// {
// if(a[j]<a[j-1])
// swap(a[j],a[j-1]);
// flag=true;
// }
// if(flag==false)
// return;
// }
}
/**
快速排序
*/
int Partition(int a[],int left,int right)
{
int temp=a[left];
while(left<right)
{
while(a[right]>=temp&&left<right)
right--;
a[left]=a[right];//将比枢轴小的元素移动到左边
while(a[left]<=temp&&left<right)
left++;
a[right]=a[left];//将比枢轴大的元素移动到右边
}
a[left]=temp;
return left;
}
void QuickSort(int a[],int left,int right)
{
int pivotpos=Partition(a,left,right);
if(left<right)
{
QuickSort(a,left,pivotpos-1);
QuickSort(a,pivotpos+1,right);
return;
}
}
//整合后的快速排序
//void QuickSort(int a[],int n,int left,int right)
//{
// int i,j,temp;//temp为枢轴(基准)
// i=left;
// j=right;
// temp=a[left];
// if(left>right)
// return;
// while(i!=j)
// {
// while(a[j]>=temp&&i<j)
// j--;
// while(a[i]<=temp&&i<j)
// i++;
// if(i<j)
// {
// swap(a[i],a[j]);
// }
// }
// a[left]=a[i];
// a[i]=temp;
// QuickSort(a,n,left,i-1);
// QuickSort(a,n,i+1,right);
// return ;
//}
/**
堆排序(heapsort):
*/
void HeadAdjust(int a[],int k,int n)
{
//将元素为k的子树进行调整,使得根>=左右孩子
a[0]=a[k];//用a[0]记录子树的根节点
for(int i=2*k;i<=n;i*=2)//k为子树的根节点不断向下筛选并调整,使这个子树是个大根堆
{
if(a[i]<a[i+1]&&i<n)
i++;//取关键值较大的子节点的下标
if(a[0]>=a[i])break;
else
{
a[k]=a[i];//a[i]调整到双亲节点上
k=i;//更新双亲节点的位置,继续向下筛选
}
}
a[k]=a[0];//被筛选节点的值放入最终位置
}
//建立大根堆
void BuildMaxHeap(int a[],int n)
{
//i=n/2代表非终端节点的个数
for(int i=n/2;i>0;i--)
HeadAdjust(a,i,n);
}
//堆排序
void HeapSort(int a[],int n)
{
//初始建堆,时间复杂度为O(n)
BuildMaxHeap(a,n);
//进行n-1趟的调整
for(int i=n;i>1;i--)
{
swap(a[i],a[1]);//固定堆顶元素
HeadAdjust(a,1,i-1);//将剩下的i-1个元素整理成堆
}
}
/**
归并排序
*/
//创建一个动态数组作为辅助数组
int n;
int *b=new int[n];//或者int *b=(int *)malloc(n*sizeof(int))
//归并两个有序表成一个新的有序表
void Merge(int a[],int left,int mid,int right)
{
//表a[]中的a[left,mid]和a[mid+1,right]两段各自有序,将他们合并成一个有序表
//将a[]中元素复制到辅助数组中去
for(int i=0;i<n;i++)
b[i]=a[i];
int i,j,k;
for(i=left,j=mid+1,k=left;i<=mid&&j<=right;k++)
{
if(b[i]<=b[j])
a[k]=b[i++];
else
a[k]=b[j++];
}
while(i<=mid)
a[k++]=b[i++];
while(j<=right)
a[k++]=b[j++];
}
//归并排序
void MergeSort(int a[],int left,int right)
{
if(left<right)
{
int mid=(left+right)>>1;
MergeSort(a,left,mid);
MergeSort(a,mid+1,right);
Merge(a,left,mid,right);
}
}
int main()
{
int a[100];
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
MergeSort(a,0,n-1);
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}