ABOUT SORT
#include<bits/stdc++.h>
using namespace std;
/*
关于排序:
1.冒泡排序 时间复杂度 O(n^2)
2.选择排序 时间复杂度 O(n^2)
3.直接插入排序 时间复杂度 O(n)~O(n^2) 空间复杂度O(1)
4.希尔排序(在插入排序的基础上改进,跳着插) 时间复杂度O(n^1.5)
5.堆排序 时间复杂度O(nlogn)
6.桶排序 时间复杂度O(n) 空间占用较大
7.基数排序 时间复杂度O(n*d) 空间复杂度O(n)
8.归并排序 时间复杂度O(nlog2n)(分治策略)
9.快速排序 时间复杂度O(nlogn){思想:二分}
算法稳定性:
稳定算法:1.2.3.4.
时稳定的算法:6.7
不稳定算法: 5.8.9
*/
//为堆排序准备的函数
/*
void heapfi(int *arr,int n,int i)
{
if(i>=n)
return ;
int lchild = i*2+1; //左孩子下标
int rchild = i*2+2; //右孩子下标
int max = i ;//默认数值最大第节点为该叶子节点的值
if(lchild <n && arr[lchild] > arr[max])//判断左孩子是否存在索引范围内及左孩子节点值是否大于根节点
max=lchild; //大于的话就将较大值的下标记录在max里
if(rchild <n && arr[rchild] > arr[max])//同上
max=rchild;
if(max!=i)
{
swap(arr[max],arr[i]); //如果最大值下标改变,则交换二者
heapfi(arr,n,max); //对剩下部分不是完全二叉树继续进行堆的建立,递归
}
}
void build_heap(int *arr)
{
int n=20;
int last_node = n-1;
int parent=(last_node-1) / 2;//从后往前建堆
for(int i = parent ;i>=0 ;i--)
{
heapfi(arr,n,i);
}
}*/
//基数排序的函数
/*
int MaxBit(int *arr,int n)//求数组中最大数的位数
{
int max=arr[0];
for(int i=0;i<n;i++)
{
if(arr[i]>max)
max=arr[i];
}
int sum=0;
while(max>0)
{
max/=10;
sum++;
}
return sum;
}
int GetNum(int num,int d)
{
int p=1;
while(d-1>0)
{
p*=10;
d--;
}
return num/p%10;
}*/
//为归并排序准备的函数
/*
void merge(int *arr,int left,int mid,int right)
{
int left_size=mid-left;
int right_size=right-mid+1;
int left_num[101];
int right_num[101];
int i,j,k;
//将数组前半部分复制到left_num,right_num中
for(i=left;i<mid;i++)
left_num[i-left]=arr[i];
for(i=mid;i<=right;i++)
right_num[i-mid]=arr[i];
i=j=0;
k=left;
//左右合并至一个数组中
while(i<left_size && j<right_size)
{
if(left_num[i]<right_num[j])//按照从小到大依次放入arr中
{
arr[k]=left_num[i];
i++;
k++;
}
else
{
arr[k]=right_num[j];
j++;
k++;
}
}
//放入剩余的
while(i<left_size)
{
arr[k]=left_num[i];
i++;
k++;
}
while(j<right_size)
{
arr[k]=right_num[j];
j++;
k++;
}
return ;
}
void merge_sort(int *arr,int left,int right)
{
if(left==right)
return ;
else
{
int mid=(left+right)/2;
merge_sort(arr,left,mid);
merge_sort(arr,mid+1,right);
merge(arr,left,mid+1,right);
}
return ;
}*/
//快速排序的函数
/*
int part(int *arr,int left,int right)
{
if(left>=right)
return -1;
int base=arr[left];//从最左边的元素为中心元素
while(left<right)
{
while(left<right && arr[right] > base) //判断右侧元素是否大于中心元素,大于就继续遍历
right--;
if(left<right) //否则就将右侧小于中心元素的元素挪到左边的位置
swap(arr[left++],arr[right]);
while(left<right && arr[left] <= base)//判断左侧元素是否小于中心元素,小于就继续遍历
left++;
if(left<right)
swap(arr[left],arr[right--]);//否则就将左侧小于中心元素的元素挪到右边的位置
}
arr[left]=base; //最后将中心放置左侧
return left;
}
void Quick_sort(int *arr,int left,int right)
{
if(left<right)
{
int base=part(arr,left,right);
Quick_sort(arr,left,base-1);//左边排序
Quick_sort(arr,base+1,right);//右边排序
}
return ;
}*/
int main()
{
default_random_engine e;//顺便学习一种生成大随机数的方法(为了装个×)
std::ios::sync_with_stdio(false);
cin.tie(0);
int n=20;
int arr[21];
for(int i=0;i<n;i++)
arr[i]=e()%100;
cout<<"数组:";
for(int i=0;i<n;i++)
cout<<' '<<arr[i];
cout<<endl;
//1.冒泡排序
//a.最原始的
/*
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
if(arr[i]>arr[j])//大小修改在这里
swap(arr[i],arr[j]);
}
}
*/
//b.常见的(优化后):
/*
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-i-1;j++)
{
if(arr[j]>arr[j+1])//大小修改在这里
{
swap(arr[j],arr[j+1]);
}
}
}
*/
//c.最佳的冒泡排序 但空间复杂度O(1)
/*
bool flag=true;
for(int i=0;i<n-1 && flag;i++)
{
flag=false;
for(int j=0;j<n-i-1;j++)
{
if(arr[j]>arr[j+1])//大小修改在这里
{
swap(arr[j],arr[j+1]);
flag=true;
}
}
}
//用flag成功优化了冒泡
*/
//2.选择排序(性能略优与冒泡排序)
/*
int minn;
for(int i=0;i<n;i++)
{
minn=i;
for(int j=i+1;j<n;j++)
{
if(arr[j]<arr[minn])
minn=j;
}
swap(arr[minn],arr[i]);
}
*/
//3.直接插入排序
/*
for(int i=1;i<n;i++)//从索引1开始 往前插入
{
int temp=arr[i];
int j=i-1;
for(j;j>=0 && arr[j]>temp;j--)//前面的数 > 后面的数,实现后移
arr[j+1]=arr[j];
arr[j+1]=temp;
}
*/
//4.希尔排序
/*
int gap=n; //增量
while(gap>1)
{
gap = gap/3+1;
for(int i=gap;i<n;i++)
{
int temp=arr[i];
int j=i-gap;
for(j;j>=0 && arr[j]>temp ;j= j-gap)//跳跃式前移
{
arr[j+gap]=arr[j];
}
arr[j+gap]=temp;
}
}
*/
//5. 堆排序
/*
build_heap(arr); //先建立一个大根堆
for(int i=n-1;i>=0;i--)
{
swap(arr[i],arr[0]);
heapfi(arr,i,0);
}
*/
//6.桶排序(有相当的局限性,会自动去重用,set或multiset(不去重)做更好,这里不演示)
//因为数据大小,桶排序没有固定写法。
//7.基数排序(非负数)
/*
int bucket[21];//创建临时存放排序过程数据的数组
int count[15];//创建按位计数的计数容器,即记录个位、十位、百位……各个数的位置的个数
for(int d=1;d<=MaxBit(arr,n);d++)
{
memset(count,0,sizeof(count));//初始化
//统计各个桶中的个数
for(int i=0;i<n;i++)
count[GetNum(arr[i],d)]++;
//得到某个数应该放入bucket的位置
for(int i=1;i<15;i++)
{
count[i]+=count[i-1];
}
for(int i=n-1;i>=0;i--)
{
int k=GetNum(arr[i],d);
bucket[count[k]-1]=arr[i];
count[k]--;
}
for(int j=0;j<n;j++)
{
arr[j]=bucket[j];
}
}
*/
//8.归并排序(自己看函数吧)
/*
//merge(arr,0,n/2,n);
merge_sort(arr,0,n);
*/
//9.快速排序
// Quick_sort(arr,0,n);
//最后让大家感受一下STL的强大
/*
经过优化的快速排序算法:
sort(begin,end)
sort(begin,end,op)
使用归并排序算法:
stable_sort(begin,end)
stable_sort(begin,end,op)
使用堆排序算法:(局部排序)
partial_sort(begin,sortEnd,end)
partial_sort(begin,sortEnd,end,op)
根据第n个位置排序(快速排序算法):
nth_element(beg,nth,end)
nth_element(beg,nth,end,op)
*/
//最后表演一个最常用的sort
sort(arr,arr+n);
cout<<"排序后:";
for(int i=0;i<n;i++)
cout<<' '<<arr[i];
cout<<endl; //完结撒花!
return 0;
}