·
桶排序
#include <stdio.h>
#include <stdlib.h>
void main()
{
int book[1001], i, j, t, n;
for (i = 0; i < 1001; i++) //初始化数组,时间复杂度为m(m为桶的个数)
{
book[i] = 0;
}
scanf("%d", &n); //对n个数进行排序
for (i=1;i<=n;i++) //将这n个数放入桶中,数字5就放入桶5
{
scanf("%d", &t);
book[t]++; //统计每个桶有多少个数,时间复杂度为n
//如果需要去重,则将上面那一步改为book[t]=1;
}
for (i = 1000; i >=0; i--) //依次判断编号为1000~0的桶
{
for (j = 0; j < book[i]; j++) //时间复杂度为m+n
printf("%d ", i); //出现了几次就将桶的编号打印几次
}
system("pause"); //暂停键,配套上面的include<stdlib.h>使用
}
输入:
10
8 100 50 22 15 6 1 1000 999 0
输出
1000 999 100 50 22 15 8 6 1 0
·
该算法的时间复杂度为O(m+n+m+n)即O(2*(m+n))
忽略较小常数,最终桶排序的时间复杂度为O(m+n)
一般使用大写字母,所以为O(M+N)
但是桶排序太浪费空间了,而且没办法排小数,人名等
所以下面介绍另一种排序——冒泡排序
·
·
·
冒泡排序
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, a[100], b, n;
printf("Please enter the number of the numbers: "); //接下来将输入n个数
scanf_s("%d", &n);
printf("Please enter the number you want: ");
for (i = 0; i < n; i++) //循环读入n个数到数组
{
scanf_s("%d", &a[i]);
}
//冒泡排序的核心部分
for (i = 0; i < n; i++) //n个数排序,只进行n-1趟
{
for (j = 0; j < n-1-i; j++) //已经归位的数无需再比较,所以减去i+1
{
if (a[j] < a[j + 1]) //比较大小
{
b = a[j];
a[j] = a[j + 1];
a[j + 1] = b;
}
}
}
for (i = 0; i < n; i++) //输出结果
{
//如需去重,可加 if(a[i]!=a[i+1])
printf("%d ", a[i]);
}
system("pause");
return 0;
}
结果:
Please enter the number of the numbers: 10
Please enter the number you want: 8 100 50 22 15 6 1 1000 999 0
1000 999 100 50 22 15 8 6 1 0 请按任意键继续. . .
·
将上面代码稍加修改,就可以用来记录人名和分数。
#include <stdio.h>
#include <stdlib.h>
struct student
{
char name[21];
int score;
}; //构建结构体储存姓名和分数
int main()
{
struct student a[100], b;
int i, j, n;
printf("Please enter the number of the students: "); //接下来将输入n个数
scanf("%d", &n);
printf("Please enter their names and scores: "); //循环读入n个人名和分数
for (i = 0; i < n; i++)
{
scanf("%s", a[i].name,21);
//接收字符串存储到以name为首地址的数组中,不用&符号。
//因为name是数组,所以name相当于&name[0](首地址)
//所以scanf(%c,name)是对的。scanf(%s,name)和scanf(%s,&name[0])也是对的
//如果是scanf_s则为 scanf_s("%s", a[i].name,21);
//因为scanf_s函数在输入字符串的时候一定要限定输入字符串的长度
scanf("%d",&a[i].score);
}
for (i = 0; i < n; i++)//按分数从高到低进行排序
{
for (j = 0; j < n-1-i; j++)
{
if (a[j].score < a[j + 1].score)//比较分数
{
b = a[j];
a[j] = a[j + 1];
a[j + 1] = b;
}
}
}
for (i = 0; i < n; i++)//输出人名
{
printf("%s ", a[i].name);
}
system("pause");
return 0;
结果:
Please enter the number of the students: 5
Please enter their names and scores: huhu 5 haha 3 xixi 5 hengheng 2 gaoshou 8
gaoshou huhu xixi haha hengheng 请按任意键继续. . .
·
冒泡排序核心部分为双重嵌套循环,时间复杂度为O(N^2),非常高,所以不推荐这种算法。
·
·
·
快速排序
例:6 1 2 7 9 3 4 5 10 8
设基准数为最左边的数,则可以用两个变量i,j指向序列最左边和最右边。
每次必须是j先动。
8>6( j 动)
1<6( i 动)
10>6( j 动)
2<6( i 动)
5<6( j 不动)
7>6( i 不动)
交换 i , j 得:6 1 2 5 9 3 4 7 10 8
4<6( j 不动)
9>6( i 不动)
交换 i , j 得:6 1 2 5 4 3 9 7 10 8
3<6( j 不动)
3<6( i 与 j 撞上)
则交换基准数和3得:3 1 2 5 4 6 9 7 10 8
第一轮处理结束。
剩下的处理参考这个图:
6 1 2 7 9 3 4 5 10 8
3 1 2 5 4 6 9 7 10 8
3 1 2 5 4
2 1 3 5 4
2 1
1 2
……… 5 4
……… 4 5
……… 4
…………… 9 7 10 8
…………… 8 7 9 10
…………… 8 7
…………… 7 8
…………… 7
………………… 10
最后就是:1 2 3 4 5 6 7 8 9 10
·
void quick_sort(int s[], int l, int r)
{
if (l < r)
{
int i = l, j = r, x = s[l];
while (i < j)
{
while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
j--;
if(i < j)
s[i++] = s[j];
while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
i++;
if(i < j)
s[j--] = s[i];
}
s[i] = x;
quick_sort(s, l, i - 1); // 递归调用
quick_sort(s, i + 1, r);
}
}
具体看这个:https://blog.csdn.net/morewindows/article/details/6684558
三种排序算法中,桶排序最快。桶排序时间复杂度为O(N+M),冒泡排序时间复杂度为O(N^2),快速排序时间复杂度为O(NlogN)。