算法1:排序


·

桶排序

#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)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值