算法是编程的灵魂,排序是算法的基础之一。计算机的飞速发展踊跃出了各样的算法排 序,一些常见的排序仍然是我们学习的基础。
1.冒泡排序(最流行的一种排序)
#include<stdio.h>
#define N 5
void sort(int a[],int n)
{
int i,j,flag=1;
for(i=1;i<n;i++)//最后一次不用排序
{
if(!flag)
{
break;//下面的循环没进行(即没有数据交换)则数据已经排好序
}
flag=0;
for(j=0;j<n-i;j++)//确定末位的数据
{
int t=a[j];
if(a[j]>a[j+1])
{
a[j]=a[j+1];
a[j+1]=t;
flag=1;//进行下一次循环
}
}
}
}
int main()
{
int a[N];
for(int i=0;i<N;i++)
{
scanf("%d",&a[i]);
}
sort(a,N);
for(int i=0;i<N;i++){
printf("%5d",a[i]);
}
return 0;
}
2.选择排序
#include<stdio.h>
#define N 5
void f(int a[],int n)
{
int i,j,t;
for(i=0;i<n-1;i++){//循环n-1次,最后一次不用排序
t=a[i];
int k=i;
for(j=i+1;j<=n-1;j++){//获取下标
if(a[k]>a[j]){
k=j;
}
}
if(k!=i){
a[i]=a[k];//交换数值
a[k]=t;
}
}
}
int main(){
int i,a[N];
for(i=0;i<N;i++){
scanf("%d",&a[i]);
}
f(a,N);
for(int i=0;i<N;i++){
printf("%5d",a[i]);
}
return 0;
}
3.插入排序
#include"stdio.h"
#define N 5
void insert(int a[],int n){
for(int j,i=1;i<n&&j>=0;i++)
{
int t=a[i];
for(j=i-1;j>=0 && t<a[j];j--)
{
a[j+1]=a[j];
}
a[j+1]=t;//插入数据
}
}
int main(){
int a[N];
for(int i=0;i<N;i++){
scanf("%d",&a[i]);
}
insert(a,N);
for(int i=0;i<N;i++){
printf("%d ",a[i]);
}
return 0;
}
4.希尔排序(插入排序升级版)
#include<stdio.h>
void f(int a[],int n){
int j,jump=n>>1;//jump为组距也为分的组数
while(jump>0)
{
for(int i=jump;i<n;i++)//每组依次一个数据循环进行
{
int t=a[i];
for(j=i-jump;t<a[j] && j>=0;j-=jump)//将该数据在该组内插入
{
a[j+jump]=a[j];
}
a[j+jump]=t;
}
jump=jump>>1;//将组距缩小
}
}
int main(){
int a[6]={4,4,5,5,8,1};
f(a,6);
for(int i=0;i<6;i++){
printf("%d ",a[i]);
}
return 0;
}
5.快速排序(排序大数组的最常用算法)
#include<stdio.h>
#include<string.h>
void Quicksort(int a[],int low,int high)
{
if(low>=high)//只有一个数据结束函数
{
return ;
}
int first=low;
int last=high;
int key=a[first];//确定一个中间数据
while(first<last)/*第一个a[first]保留,后面的a[first]全为重复数据,直到key为中间数据
此时first==last,且为重复数据,跳出循环,故赋值为key*/
{
while(first<last && a[last]>key)//从最右边开始找一个比key小的
{
--last;
}
a[first]=a[last];//比key小的放在左边
while(first<last && a[first]<key)
{
++first;
}
a[last]=a[first];
}
a[first]=key;//左边全比key小,右边全比key大
Quicksort(a,low,first-1);//区间左边再调用函数
Quicksort(a,last+1,high);
}
int main(){
int a[6]={5,5,6,6,8,1};
Quicksort(a,0,5);
for(int i=0;i<6;i++){
printf("%d ",a[i]);
}
return 0;
}
6.归并排序
#include<stdio.h>
#include<malloc.h>
#include<mem.h>
void recursion_(int a[],int left,int righ)
{
if(left>=righ)
return ;
int mid=((righ-left)>>1)+left;//中间值
recursion_(a,left,mid);//递归
recursion_(a,mid+1,righ);
void merger_(int a[],int left,int mid,int righ);
merger_(a,left,mid,righ);//合并
}
void merger_(int a[],int left,int mid,int righ)
{
int leght=righ-left+1;//数组长度
int *p=(int *)malloc(sizeof(int)*leght);/*申请一个整型的leght长度的地址
即申请辅助数组*/
int dex=0;
int low=left;
int high=mid+1;//mid为常数((中间值),取决于下一个函数f2
while(high<=righ)//判断右边是否排完
{
while(low<=mid && a[low]<=a[high])
{
p[dex]=a[low];
low++;
dex++;
}
if(low>mid)//左边排完,结束循环
break;
while(high<=righ && a[high]<=a[low])
{
p[dex]=a[high];
high++;
dex++;
}
}
if(low>mid)//左边排完
memmove(&p[dex],&a[high],sizeof(int)*(righ-high+1));/*将右边拷贝到辅助数组,
最大拷贝长度为righ-high+1*/
if(high>righ)
memmove(&p[dex],&a[low],sizeof(int)*(mid-low+1));
memmove(&a[left],p,sizeof(int)*(righ-left+1));/*将辅助数组拷贝到原数组*/
}
int main()
{
int a[6]={2,6,7,7,3,9};
recursion_(a,0,5);
for(int i=0;i<6;i++)
{
printf("%d ",a[i]);
}
return 0;
}
7.桶排序
#include<stdio.h>
#include<malloc.h>
void f1(int a[],int n)
{
int **t=(int **)malloc(sizeof(int)*10);/*申请二级指针,指向int 类型的指针,
且二级指针的长度为十行*/
for(int i=0;i<10;i++)//每一个int 类型的指针有n列
{
t[i]=(int *)malloc(sizeof(int )*n); //对int 类型的指针申请长度为n的int 类型值
}
for(int i=1;i<=100;i *=10)//最大排三位数
{
for(int x=0;x<10;x++)//将辅助数组初始值设为(-1)
{
for(int y=0;y<n;y++)
{
t[x][y]=-1;
}
}
for(int m=0;m<n;m++)
{
int dex=(a[m]/i)%10;//指定列数上依次按个十百...重排
t[dex][m]=a[m];//数据高的对应行数高,列数暂不变
}
int k=0;
for(int x=0;x<10;x++)
{
for(int y=0;y<n;y++)
{
if(t[x][y]!=-1)
{
a[k++]=t[x][y];//改变列数完成分位上的排序
}
}
}
}
for(int i=0;i<10;i++)//释放申请的int 类型值(长度为n)的空间
{
free(t[i]);
}
free(t);//释放申请的int 类型指针(长度为10)的空间
}
int main()
{
int a[10]={99,77,88,11,22,33,44,55,66,100};
f1(a,10);
for(int i=0;i<10;i++)
{
printf("%d ",a[i]);
}
return 0;
}
排序的方法有很多,在这里我只分享了七种,每一种排序都有它的优缺点,我们应该根据不同的情况选出最合适的一种。
祝大家学有所成!