C语言的常规排序算法
冒泡排序
算法原理:
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
代码展示:
#include<stdio.h>
int main()
{
void Selectsort(int arr[],int len); //函数声明
void Print(int arr[],int len); //函数声明
int arr[]={66,3,22,44,76,39,99,1,60,10,20,-1};
int len=sizeof(arr)/sizeof(arr[0]); //sizeof()求取数组长度
printf("打印排序前的10个数据数据:\n");
Print(arr,len);
printf("----------------------------------\n");
Selectsort(arr,len);
printf("----------------------------------\n");
printf("打印排序后的10个数据数据:\n");
Print(arr,len);
return 0;
}
void Selectsort(int arr[],int len) //冒泡法排序
{
int i,j,temp;
for(j=0;j<len-1;j++)
{
for(i=0;i<len-j-1;i++)
{
if(arr[i]>arr[i+1])
{
temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
printf("打印第%d趟的排序结果: ",j+1);
Print(arr,len);
}
}
void Print(int arr[],int len) //打印输出结果
{
int i;
for(i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
运行结果如下:
程序分析:
初始序列:66,3,22,44,76,39,99,1,60,10,20,-1
打印第1趟的排序结果: 3 22 44 66 39 76 1 60 10 20 -1 99
打印第2趟的排序结果: 3 22 44 39 66 1 60 10 20 -1 76 99
打印第3趟的排序结果: 3 22 39 44 1 60 10 20 -1 66 76 99
打印第4趟的排序结果: 3 22 39 1 44 10 20 -1 60 66 76 99
打印第5趟的排序结果: 3 22 1 39 10 20 -1 44 60 66 76 99
打印第6趟的排序结果: 3 1 22 10 20 -1 39 44 60 66 76 99
打印第7趟的排序结果: 1 3 10 20 -1 22 39 44 60 66 76 99
打印第8趟的排序结果: 1 3 10 -1 20 22 39 44 60 66 76 99
打印第9趟的排序结果: 1 3 -1 10 20 22 39 44 60 66 76 99
打印第10趟的排序结果: 1 -1 3 10 20 22 39 44 60 66 76 99
打印第11趟的排序结果: -1 1 3 10 20 22 39 44 60 66 76 99
最终排序结果:-1 1 3 10 20 22 39 44 60 66 76 99
时间复杂度和空间复杂度
1、时间复杂度
外循环和内循环以及判断和交换元素的时间开销:
最优的时间复杂度为: O(n);
最差的时间复杂度为:O( n^2 );
平均时间复杂度为:O(n^2);
2、空间复杂度
空间复杂度就是在交换元素时那个临时变量所占的内存空间;
最优的空间复杂度就是开始元素顺序已经排好了,则空间复杂度为:O(1);
最差的空间复杂度就是开始元素逆序排序了,则空间复杂度为:O(n);
选择排序
算法原理:
简单选择排序的基本思想:第1趟,在待排序记录r[1]r[n]中选出最小的记录,将它与r[1]交换;第2趟,在待排序记录r[2]r[n]中选出最小的记录,将它与r[2]交换;以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕。
代码展示:
#include<stdio.h>
int main()
{
void Selectsort(int arr[],int len); //函数声明
void Print(int arr[],int len); //函数声明
int arr[]={66,3,22,44,76,39,99,1,60,10,20,-1};
int len=sizeof(arr)/sizeof(arr[0]); //sizeof()求取数组长度
printf("打印排序前的10个数据数据:\n");
Print(arr,len);
printf("----------------------------------\n");
Selectsort(arr,len);
printf("----------------------------------\n");
printf("打印排序后的10个数据数据:\n");
Print(arr,len);
return 0;
}
void Selectsort(int arr[],int len) //选择法排序
{
int i,j,temp;
for(i=0;i<len-1;i++) //数组的长度为len,只需要比较(len-1)次即可
{
for(j=i+1;j<len;j++)
{
if(arr[i]>arr[j])
{
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
printf("打印第%d趟的排序结果: ",i+1); //数组从0开始,第一趟为(i+1)
Print(arr,len);
}
}
void Print(int arr[],int len) //打印输出结果
{
int i;
for(i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
Selectsort()优化:
void Selectsort(int arr[],int len)
{
int temp,i,j;
int minindex; //最小值的下标
for(i=0;i<len-2;i++)
{
minindex=i;
for(j=i+1;j<len;j++)
{
if(arr[j]<arr[minindex])
{
minindex=j;
}
}
temp=arr[i];
arr[i]=arr[minindex];
arr[minindex]=temp;
printf("打印第%d趟的排序结果:\n",i+1); 数组从0开始,第一趟为(i+1)
Print(arr,len);
printf("\n");
}
}
运行结果如下:
程序分析:
初始序列:66 3 22 44 76 39 99 1 60 10 20 -1
打印第1趟的排序结果: -1 66 22 44 76 39 99 3 60 10 20 1
打印第2趟的排序结果: -1 1 66 44 76 39 99 22 60 10 20 3
打印第3趟的排序结果: -1 1 3 66 76 44 99 39 60 22 20 10
打印第4趟的排序结果: -1 1 3 10 76 66 99 44 60 39 22 20
打印第5趟的排序结果: -1 1 3 10 20 76 99 66 60 44 39 22
打印第6趟的排序结果: -1 1 3 10 20 22 99 76 66 60 44 39
打印第7趟的排序结果: -1 1 3 10 20 22 39 99 76 66 60 44
打印第8趟的排序结果: -1 1 3 10 20 22 39 44 99 76 66 60
打印第9趟的排序结果: -1 1 3 10 20 22 39 44 60 99 76 66
打印第10趟的排序结果: -1 1 3 10 20 22 39 44 60 66 99 76
打印第11趟的排序结果: -1 1 3 10 20 22 39 44 60 66 76 99
最终排序的结果: -1 1 3 10 20 22 39 44 60 66 76 99
时间复杂度和空间复杂度
1、时间复杂度
外循环和内循环以及判断和交换元素的时间开销:
最优的时间复杂度为: O(n^2);
最差的时间复杂度为:O( n^2 );
平均时间复杂度为:O(n^2);
2、空间复杂度
空间复杂度就是在交换元素时那个临时变量所占的内存空间;
最优的空间复杂度就是开始元素顺序已经排好了,则空间复杂度为:O(1);
直接插入排序
算法原理:
每一趟将一个待排序的记录,按其关键字的大小插入到已经排好序的一组记录的适当位置上,直到所有待排序记录全部插入为止。
代码展示:
int main()
{
void insertsort(int a[],int n);
void Print(int arr[],int len);
int i=0,len=0;
int arr[]={66,3,22,44,76,39,99,1,60,10,20,-1};
len=sizeof(arr)/sizeof(arr[0]);
insertsort(arr,len);
return 0;
}
void insertsort(int arr[],int len) //排序
{
int i=0,temp=0,j=0;
for(i=1;i<len;i++)
{
if(arr[i]<arr[i-1])
{
temp=arr[i]; //存储arr[i]的值
for(j=i-1;j>=0 && arr[j]>temp;j--) //连续比较大小,确定arr[i]的合适位置
arr[j+1]=arr[j];
arr[j+1]=temp;
}
printf("打印第%d趟的排序结果: ",i);
Print(arr,len);
}
}
void Print(int arr[],int len) //打印输出结果
{
int i;
for(i=0;i<len;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
运行结果如下:
程序分析:
初始序列:66 3 22 44 76 39 99 1 60 10 20 -1
打印第1趟的排序结果: 3 66 22 44 76 39 99 1 60 10 20 -1
打印第2趟的排序结果: 3 22 66 44 76 39 99 1 60 10 20 -1
打印第3趟的排序结果: 3 22 44 66 76 39 99 1 60 10 20 -1
打印第4趟的排序结果: 3 22 44 66 76 39 99 1 60 10 20 -1
打印第5趟的排序结果: 3 22 39 44 66 76 99 1 60 10 20 -1
打印第6趟的排序结果: 3 22 39 44 66 76 99 1 60 10 20 -1
打印第7趟的排序结果: 1 3 22 39 44 66 76 99 60 10 20 -1
打印第8趟的排序结果: 1 3 22 39 44 60 66 76 99 10 20 -1
打印第9趟的排序结果: 1 3 10 22 39 44 60 66 76 99 20 -1
打印第10趟的排序结果: 1 3 10 20 22 39 44 60 66 76 99 -1
打印第11趟的排序结果: -1 1 3 10 20 22 39 44 60 66 76 99
最终排序的结果: -1 1 3 10 20 22 39 44 60 66 76 99
时间复杂度和空间复杂度
1、时间复杂度
插入排序的最好情况是数组已经有序,此时只需要进行n-1次比较,时间复杂度为O(n)
最坏情况是数组逆序排序,此时需要进行n(n-1)/2次比较以及n-1次赋值操作(插入)
平均来说插入排序算法的复杂度为O(n2)
2.空间复杂度
空间复杂度上,直接插入法是就地排序,空间复杂度为(O(1))