十种常见排序算法可以分为两大类:
-
比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
(1)交换排序:冒泡排序 和 快速排序
(2)插入排序:简单插入排序 和 希尔排序
(3)选择排序:简单选择排序 和 堆排序
(4)归并排序:二路归并排序 和 多路归并排序 -
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
(1)计数排序
(2)桶排序
(3)基数排序
稳定:若a=b,且在排序前a在b前面,排序后a仍在b前面。
不稳定:排序后a有可能到b后面。
1.冒泡排序
算法描述:
- 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
- 针对所有的元素重复以上的步骤,除了最后一个;
- 重复步骤1~3,直到排序完成。
代码:
for(i = 0; i < n-1; i++){
for(j = 0;j < n-i-1;j++){
if(arr[j]>arr[j+1]){
temp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
2.快速排序
快排是对冒泡排序的一种改进。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快排,整个排序过程可以递归进行,最后整个数据变成有序序列。
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int partition(int a[],int low,int high)
{
int privotKey = a[low];//基准元素
while(low<high){ //从表的两端交替地向中间扫描
while(low<high && a[high]>=privotKey)
--high;//从high所指位置向前搜索,将比基准元素小的交换到低端
swap(&a[low],&a[high]);
while(low<high && a[low]<=privotKey)
++low;
swap(&a[low],&a[high]);
}
return low;
}
void quickSort(int a[],int low,int high)
{
if(low<high){
int privotLoc=partition(a,low,high);//将表一分为二
quickSort(a,low,privotLoc-1);//递归对低子表排序
quickSort(a,privotLoc+1,high);//递归对高子表排序
}
}
3.插入排序
思想:
最基本的操作是将第i个元素插入到前面i-1个已经排好序的记录中。
for(int i=1;i<n;i++){
if(a[i]<a[i-1]){
int tmp=a[i];
for(j=i-1;j>=0&&a[j]>tmp;j--){
a[j+1]=a[j];
}
a[j+1]=tmp;
}
}