#include<iostream>
using namespace std;
/*直接输出*/
void output(int a[],int length)
{
for(int i=0;i<length;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
}
/*直接插入排序*/
void InsertSort(int a[],int length)
{
for(int i=1;i<length;i++)
{
int temp=a[i];//待排序
int j;
for(j=i-1;j>=0&&temp<a[j];j--)
{
a[j+1]=a[j]; //如果待排序比数组元素小,则后移
}
a[j+1]=temp; //此时j是第一个比插入数小的位置,则插入j+1位置
}
}
/*
二分排序
*/
void BinInsertSort(int a[],int length) //先找到插入位置,再整体后移
{
for(int i=1;i<length;i++)
{
int temp=a[i];
int left=0;
int right=i-1;
while(left<=right)
{
int mid=(left+right)/2;
if(temp>a[mid])
{
left=mid+1;
}
else right=mid-1;
}
for(int j=i-1;j>=left;j--) //只是减少了比较次数,没有减少移动次数
a[j+1]=a[j];
a[left]=temp;
}
}
/*
希尔排序
选取分量间隔进行插入排序,因为相同
的值可能在不同的分组,排序过程中相对位置可能发生变化,不稳定
*/
void ShellSort(int a[],int length)
{
for(int gap=length/2;gap>=1;gap=gap/2) //直到增量为1
{
for(int i=gap;i<length;i++) //第一组为已经排好的,相当于直接插入中的a[0],所以从gap开始
{
int temp=a[i];
int j;
for(j=i-gap;j>=0&&temp<a[j];j=j-gap)
{
a[j+gap]=a[j];
}
a[j+gap]=temp;
}
}
}
/*冒泡排序*/
void BubbleSort(int a[],int length)
{
for(int i=0;i<length;i++)
for(int j=0;j<length-1-i;j++) //后面i个都是排好的,不需要再比较
{
if(a[j]>a[j+1]) //交换位置
{
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
/*
选择排序
每次从无序数组中选择一个最小的出来
*/
void SelectSort(int a[],int length)
{
int min;
for(int i=0;i<length-1;i++) //不用进行length次因为最后剩下一个必然是最大
{
min=i; //假设还没排序的第一个就是最小的
for(int j=i;j<length;j++)
{
if(a[j]<a[min]) min=j; //如果有更小的换位置
}
int temp=a[i];
a[i]=a[min];
a[min]=temp;
}
}
/*快速排序
先进行一次快排,再递归对基准数两边的分组进行快排
*/
void OnceQuickSort(int a[],int left,int right)
{
if(left>=right) return; //要排序的组只要一个元素,说明已经排好,则停止
int temp=a[left];
int i=left;
int j=right;
while(i!=j)
{
if(a[j]>=temp&&i<j)
{
j--;
}
if(i<j) a[i]=a[j];
if(a[i]<=temp&&i<j)
{
i++;
}
if(i<j) a[j]=a[i];
}
a[i]=temp;
OnceQuickSort(a,i+1,right); //递归排序右边
OnceQuickSort(a,left,i-1); //递归排序左边
}
/*
归并排序
一次归并两个以begin和end中间值为界的两个数组
先对原始数组分为两个进行排序,再递归对分好的两个数组继续分裂归并
递归停止条件为分组中只有一个元素
*/
void OnceMergeSort(int a[],int begin,int end)
{
if(begin>=end) return; //递归停止条件
int mid=(begin+end)/2;
int length=end-begin+1;
OnceMergeSort(a,begin,mid); //递归调用,分裂排序
OnceMergeSort(a,mid+1,end);
int *p=new int[length]; //临时数组
int k=0; //临时数组下标
int i,j;
for(i=begin,j=mid+1;i<=mid,j<=end;) //将以mid为界分成的两个数组进行一次归并
{
if(a[i]<a[j]) p[k++]=a[i++];
else p[k++]=a[j++];
}
while(i<mid+1)
{
p[k++]=a[i++];
}
while(j<end+1)
{
p[k++]=a[j++];
}
for(k=0;k<length;k++)
{
a[begin++]=p[k]; //将临时数组复制回原始数组
}
delete[] p;
}
/*
堆排序
小顶堆,每个父节点的值都比两个子节点的值小
堆调整:从堆的最后一个节点的父节点开始一次向上调整
调整一次则堆顶为最小值,删除堆顶元素,将最后一个元素换给堆顶继续调整
*/
void OnceHeapsSort(int a[],int begin,int end)
{
if(end==1) return;
for(int i=end/2;i>=begin;i--) //从堆的最后一个节点的父节点开始一次向上调整
{
int temp=a[i];
int m=i; // 表示a[i]该放的位置
for(int j=2*i;j<=end;j=j*2)
{
if(j<end&&a[j]>a[j+1]) j++; //说明该节点有两个子节点,记录小的那个
if(temp<a[j]) break; //不必继续往下调整
a[m]=a[j]; //将更小的放在a[i]所在位置
m=j; //a[i]此时应该放在m位置
}
a[m]=temp; //最后将a[i]放在所在位置
}
int temp=a[end]; //将第一个和最后一个交换
a[end]=a[1];
a[1]=temp;
OnceHeapsSort(a,1,end-1); //再对新的堆进行调整
}
/*基数排序
*/
void LSDSort(int a[],int length)
{
int n=1;
int max=a[0]; //获取最大值得到最大数是几位数,则进行几次排序
int base=1;
for(int i=0;i<length;i++)
{
if(a[i]>max) max=a[i];
}
while(max/10)
{
n++;
max=max/10;
}
cout<<"基数排序进行"<<n<<"趟排序:"<<endl;
while(n--)
{
int b[10][10]={0}; //用数组存个位数对应的值
int k=0;
for(int i=0;i<length;i++)
{
int index=a[i]/base%10; //个位数
b[index][k++]=a[i]; //放在相应位置下
}
k=0;
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
if(b[i][j]) a[k++]=b[i][j]; //收集
}
base=base*10; //求下一位
}
}
int main(void)
{
int a[10]={31,9,15,20,1,49,84,71,10,6};
int b[11]={10,3,9,5,2,1,4,8,7,0,6}; //堆排序第一个不用
output(a,10);
// InsertSort(a,10);
// BinInsertSort(a,10);
// ShellSort(a,10);
// BubbleSort(a,10);
// SelectSort(a,10);
// OnceQuickSort(a,0,9);
// OnceMergeSort(a,0,9);
//output(a,10);
// OnceHeapsSort(b,1,10);
// output(b,11); //排序过程中数组后面的为先输出来的
LSDSort(a,10);
output(a,10);
}
复杂度: