//8638 直接插入排序
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n];
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=2;i<=n;i++)
{
if(a[i]<a[i-1])
{
int j;
a[0]=a[i];
a[i]=a[i-1];
for(j=i-2;a[0]<a[j];j--)
a[j+1]=a[j];
a[j+1]=a[0];
}
int k;//记住j,k要在外面定义
for(k=1;k<n;k++)
cout<<a[k]<<" ";
cout<<a[k]<<endl;
}
return 0;
}
//8639 折半插入排序
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
int n;cin>>n;
int a[n];
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=2;i<=n;i++)
{
if(a[i]<a[i-1])
{
a[0]=a[i];
int low=1,high=i-1,mid;
while(low<=high)
{
mid=low+((high-low)>>1);//右移一位相当于除于二,防止溢出
if(a[mid]>a[0])
high=mid-1;
else
low=mid+1;
}
//循环结束之后low=high+1
//high指向的数字可能小于或者等于a[0]
for(int j=i;j>low;j--)//low到i的数需要后移
{
a[j]=a[j-1];
}
a[low]=a[0];
}
//一次外层循环结束之后,再打印,不管是否a[i]<a[i-1]
for(int k=1;k<=n;k++)
cout<<a[k]<<" ";
cout<<endl;
}
return 0;
}
//8640 希尔(shell)排序
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n];
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int d=n/2;d>=1;d/=2)
{
for(int i=d+1;i<=n;i++)
{
if(a[i]<a[i-d])
{
int j;
a[0]=a[i];
for(j=i-d;a[j]>a[0]&&j>=1;j-=d)//这里是a[j]>a[0]而不是a[j-d]>a[0]
a[j+d]=a[j];
a[j+d]=a[0];
}
}
for(int k=1;k<=n;k++)//d变化一次输出一次
cout<<a[k]<<" ";
cout<<endl;
}
return 0;
}
//8641 冒泡排序
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;cin>>n;
int a[n];
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=n-1;i>=1;i--)
//因为有了flag判断是否还需要排列,所以i的初始值需要为j的最大值
//所以j刚开始循环的时候范围才能从最大开始,之后逐渐缩小范围
//保证了之后尾部都是有序的
{//冒泡循环外层循环为n-1次
int flag=0;
for(int j=1;j<=i;j++)
{
if(a[j]>a[j+1])
{
int temp;
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
flag=1;
}
}
for(int k=1;k<=n;k++)
cout<<a[k]<<" ";
cout<<endl;
if(!flag)//要先输出之后再判断flag
break;
}
return 0;
}
//8642 快速排序
#include <iostream>
#include <algorithm>
using namespace std;
int n,a[10000];
int paixu(int a[],int i,int j)
{
a[0]=a[i];//因为这里取出的是a[i]的值,
//所以下面循环里面要先比较a[j]>=a[0],让a[i]=a[j];
while(i<j)//记住这里要用while
{
//顺序不能调换,不然是错误的
while(i<j&&a[j]>=a[0])//不要漏掉i<j的条件
j--;
a[i]=a[j];
while(i<j&&a[i]<=a[0])
i++;
a[j]=a[i];
}
//循环后i等于j,这里a[i]或者a[j]都可以
a[i]=a[0];
return i;
}
void xunhuan(int a[],int i,int j)
{
if(i<j)
{
int k;
k=paixu(a,i,j);
for(int p=1;p<=n;p++)
cout<<a[p]<<" ";
cout<<endl;
xunhuan(a,i,k-1);//这里两行分别是i和j,不要搞错了
xunhuan(a,k+1,j);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
xunhuan(a,1,n);
return 0;
}
//8643 简单选择排序
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;cin>>n;
int a[n];
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n-1;i++)
{//注意i循环n-1次
//注意要记录k值,因为后面会改变
int k=i;
for(int j=i+1;j<=n;j++)
{
if(a[k]>a[j])//这一步是为了找到最小值,然后再交换
{
k=j;
}
}
if(k!=i)
{
int temp;
temp=a[k];
a[k]=a[i];
a[i]=temp;
}
for(int k=1;k<=n;k++)
cout<<a[k]<<" ";
cout<<endl;
}
return 0;
}
//8644 堆排序
#include <iostream>
#include <algorithm>
using namespace std;
int a[10000],n;
void heapbuilt(int start,int end)//初始构建堆
{
int dad=start;
int son=dad*2;
while(son<=end)
{
if(son+1<=end&&a[son]<a[son+1])
son++;//找到左右孩子中较大的孩子
if(a[dad]>a[son])//如果大于,说明子树全是大根堆,不需要再交换了,就退出
return ;
else
{
swap(a[son],a[dad]);//交换,使得父亲节点是最大值
//因为交换了,所以子树不一定是大根堆,需要再次循环比较
dad=son;
son=dad*2;
}
}
}
void heapsort()
{
for(int i=n/2;i>=1;i--)
heapbuilt(i,n);//这里初始值是最后一个结点,循环依次减小
for(int k=1;k<=n;k++)
cout<<a[k]<<" ";
cout<<endl;
for(int i=n;i>1;i--)//注意这里不能等于1
{
swap(a[1],a[i]);
heapbuilt(1,i-1);//这里初始值是1是因为只有头部和尾部动了,其他都是有序的
for(int k=1;k<=n;k++)
cout<<a[k]<<" ";
cout<<endl;
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
heapsort();
return 0;
}
//8645 归并排序(非递归算法)
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int *a=(int*)malloc(sizeof(int)*(n+1));
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int d=2;d<2*n-1;d=d*2)//d<=2*n-1是因为(n-1)*2小于d<=2*n-1,易错
{
for(int i=1;i<n;i=i+d)
{
sort(a+i,a+min(i+d,n+1));
//这里要取较小值是因为虽然规定了i<n,但是不一定能保证i+d<n,会超出比较的范围
//取了较小值之后就不会超出排序的范围
//sort 排序的范围是 [first, last),不包含 last 位置的元素。
//所以是n+1而不是n
}
for(int k=1;k<=n;k++)
cout<<a[k]<<" ";
cout<<endl;
}
return 0;
}