算法笔记1排序

149 阅读2分钟

桶排序

简单来说就是开一个数据范围大小的数组a[数据范围+1]初始化为0 有数据输入就a[i]++
数据输入完之后 a[i]是几就代表这组数据中有几个i
然后用一个for循环判断并按顺序打印这组数字

  • 优点:耗时较短 循环次数少 时间复杂度 O(n)
  • 缺点:如果数据范围太大 开不了那么大的数组 就没法用了 空间复杂度高
//对数据范围在1-1000之间的n个整数从大到小进行排序

#include<stdio.h>
int main()
{
	int book[1001] = { 0 }, n, t;//book取标记的意思 n是数据个数 t是临时储存数据的变量
	scanf("%d", &n);//输入 一共有n个数
	for (int i = 1; i <= n; i++)//依次读入每个数并记录每个数出现的次数
	{
		scanf("%d", &t);
		book[t]++;
	}
	for (int i = n; i >= 1; i--)//从大到小打印这些数
	{
		for (int j = 1; j <= book[i]; j++)//出现几次打印几次
		{
			printf("%d ", i);
		}
	}
	return 0;
}

冒泡排序

基本思想是每次比较两个相邻的元素 如果顺序错误就把他们交换过来
如果有n个数 从小到大排序
每一趟需要从第一位开始进行两个相邻数字的比较 把较大的数字放在后面 这样就可以 把一个数归位
需要归位n-1趟

  • 优点:空间复杂度低 数组大小只用开到n+1
  • 缺点:双重嵌套循环 时间复杂度高 O(n^2) 容易RE
//对int类型的n个整数(n<=100)从小到大进行排序

#include<stdio.h>
int main()
{
	int a[101], t, n;
	scanf("%d", &n);//输入 共有n个数
	for (int i = 1; i <= n; i++)//读入n个数
		scanf("%d", &a[i]);
	for (int i = 1; i <= n - 1; i++)//只需要归位n-1趟
	{
		//从第一个数开始比较直到最后一个尚未归为的数 有n-i+1个尚未归位的数 因为后面有j+1所以只需要循环到n-i
                for (int j = 1; j <= n - i; j++)                
		{
			if (a[j] > a[j + 1])//比较大小 如果前面的数大就让他到后面去
			{
				t = a[j];
				a[j] = a[j + 1];
				a[j + 1] = t;
			}
		}
	}
	for (int i = 1; i <= n; i++)//输出结果
		printf("%d ", a[i]);
	return 0;
}

高阶一点 如果需要带人名的成绩比较 就整个结构 比较结构里的成绩 最后再打印结构就行了

快速排序

如果要从小到大排序 思路就是在一串数字里设置一个基准数(一般是最左边的)
比基准数大的放基准数左边 比基准数小的放基准数右边
然后在左右分别再次进行这种操作(递归) 直到所有数归位
为了实现这种想法需要在左右两边设置两个哨兵变量 碰到符合条件的数就把俩数交换位置
直到俩哨兵相遇 把哨兵数和基准数交换位置
这样就完成了一次操作
特别注意 如果基准数是最左边的数字 右边的哨兵要先行动

  • 优点:相比冒泡排序 每次交换是跳跃式的 时间复杂度o(nlgn)和空间复杂度都小
  • 最坏的情况是每次都交换相邻的两个数 因此最差时间复杂度同冒泡排序 O(n^2)
//对int类型的n个整数(n<=100)从小到大进行排序

#include<stdio.h>
int a[101], n;//定义全局变量 这两个变量需要在子函数中使用

void quicksort(int left,int right)//定义快速排序函数
{
	int i, j, t, temp;
	if (left > right)
		return;
	temp = a[left];//temp里存的就是基准数
	i = left;
	j = right;
	while (i != j)
	{
		//先从左往右找 
		while (a[j] >= temp && i < j)
			j--;
		//再从右往左找
		while (a[i] <= temp && i < j)
			i++;
		//交换两个数在数组中的位置
		if (i < j)//当哨兵i和j没有相遇时
		{
			t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
	}
	//i和j相遇 将基准数归位
	a[left] = a[i];
	a[i] = temp;

	quicksort(left, i - 1);//左边重复上述操作 递归
	quicksort(i - 1, right);//右边重复上述操作 递归
}
int main()
{
	int i, j, t;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	
	quicksort(1, n);//调用快速排序

	for (int i = 1; i <= n; i++)
		printf("%d ", a[i]);
	return 0;
}