第一节 桶排序(简易)
原理:将所有出现的数与数组下标相对应,通过增加对应数组元素的值来标记该数值的存在。利用数组下标成自然排列的特性,从数组的第一个元素开始检索,根据元素的数值来打印对应次数的数组下标值。
问题引入:一场满分为10分的期末考试,5位同学参加,要求将他们的分数从高到低进行排序。
解决方案:
- 申请一个长度为11的整型数组,以数组的下标编号代表“0——10”这11个所有可能出现的分数。
- 将所有的数组元素初始化为0。
- 检视所有数字,每检测到一个数字,使数组中有对应下标的元素数值加一,表示有一个得到该分数的人。
- 检视并统计完所有数字后,从第一个数组元素开始检视,该元素的值是多少,就将该元素打印几次。
C代码实现
#include <stdio.h>
int main(void){
int score[11]={0},i,j,n;
for(i=1;i<=5;i++){
scanf("%d",&n);
score[n]++;
}
for(i=0;i<11;i++){
for(j=1;j<=score[i];j++){
printf("%d ",i);
}
}
printf("\n");
return 0;
}
分析
- 优点
- 缺点
- 使用的前提是待排序数的取值范围是明确的。
- 若待排序数的范围过大,将导致需要申请的数组元素多,占用大量空间。
- 由于数组的下标元素均为非负整数,该算法应用的范围仅限于非负整数。
- 适用:待排序数为明确的较小范围内的正整数。
第二节 冒泡排序(Bubble Sort)
原理:每次比较相邻两个元素的值,若顺序错误则交换位置。每趟归位一个元素。
问题引入:将n个数从大到小排序(n为已知常数)。
解决方案
- 申请一个长度为n的整数数组,分别存入n 个待排序的数。
- 进行n-1 趟排序,每一趟排序归位一个数,即将未排序数中的最小数排到末尾。每一趟排序都是从头开始对相邻两数进行比较,若顺序错误即交换。每一趟排序进行n-i (i 是当前趟的次序数)次比较。
- 从第一个元素开始,依次打印出数组中每个元素的值。
C代码实现
#include <stdio.h>
#define n 5
int main(void){
int num[n],number,i,j,t;
for(i=0;i<n;i++){
scanf("%d",&num[i]);
}
for(i=1;i<=n-1;i++){
for(j=0;j+1<=n-i;j++){
if(num[j]<num[j+1]){
t=num[j];
num[j]=num[j+1];
num[j+1]=t;
}
}
}
for(i=0;i<n;i++){
printf("%d ",num[i]);
}
printf("\n");
return 0;
}
分析
- 优点
- 缺点
- 运用双重嵌套循环,时间复杂度较高,为O(
N2
N
2
)。
第三节 快速排序(Quicksort)
原理:采用分治策略,找一个基准数,通过各个数与基准数的大小关系其确定相对基准数的位置,然后在基准数的左右两侧不断递归进行同样的操作。
问题引入:将n个数从大到小排序(n为已知常数)。
解决方案
- 申请一个长度为n 的整数数组,分别存入n 个待排序的数。
- 以第一个数作为基准数(pivot)。
- 从数列末尾开始逐个检视数组元素,直到找到小于该基准数的元素a。
- 从数列开头开始逐个检视数组元素,直到找到大于该基准数的元素b。
- 交换a、b。
- 以a、b的位置作为新的开头与末尾,重复执行3、4,直到a、b为同一个元素c。
- 将c与数列第一个元素交换。
- 在基准数的左右两边进行递归(重复执行2—7),直到只剩一个数字。
C代码实现
#include <stdio.h>
#define n 10
void quickSort(int b[], int l, int r);
int main(void){
int a[n],i;
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
quickSort(a,0,n-1);
for(i=0;i<10;i++){
printf("%d ",a[i]);
}
return 0;
}
void quickSort(int b[],int left,int right){
if(left<right){
int pivot=b[left],i=left,j=right;
while(i<j){
while(j>i&&b[j]>=pivot){
j--;
}
while(i<j&&b[i]<=pivot){
i++;
}
if(i<j){
int temp=b[i];
b[i]=b[j];
b[j]=temp;
}
}
b[left]=b[i];
b[i]=pivot;
quickSort(b,left,i-1);
quickSort(b,i+1,right);
}
}
分析
- 优点
- 平均时间复杂度为
O(nlogn)
O
(
n
l
o
g
n
)
,最坏状况的时间复杂度为
O(n2)
O
(
n
2
)
,一般较冒泡排序更快。