桶排序、冒泡排序、快速排序


排序

一、桶排序

1、算法思想与原理

  • 设置两个数组,分别存放桶和输入的因素
  • 桶数组通过循环排序后,输入数字出现几次,在对应桶处标记几次并打印
  • 依次打印排序后的数据

2、算法思路

  • for循环:初始化数组、输入一串数字并读入数组、依次判断标记桶、打印排序好后的数组

3、代码实现

3.1最简单粗暴滴方法

#include
#include
using namespace std;

int main()
{
	int a[11],i,j,t;
	//int n[5];  
	for(i=0;i<=10;i++)  //将数组中的所有初始化为0 
	a[i]=0;
	
	for(i=1;i<=5;i++)   //循环输入5个数 
	{
		cin>> a[i];
	} 
	
	for(i=0;i<=10;i++)    //依次判断a[0]~a[10] 
	    for(j=1;j<=a[i];j++)     //依次打印排序好的数列 
	    cout<

说明:

(1)只能输入事先预定设置的数组个数
(2)数组中每个数的大小不能超过10
(3)没有人机交互

优化:

(1)从大到小排序
(2)先指定输入数组的大小再完成

3.2 进阶可指定数组大小

#include
#include
using namespace std;
int main()
{
	int a[201],i,j,t,n; 
	for(i=0;i<=200;i++)  //将数组中的所有初始化为0 
	{
		a[i]=0;
	}	
	cin>>n;             //输入一个数n,表示接下来的数组中有n个数 
	for(i=1;i<=n;i++)   //循环输入n个数 
	{
		cin>>a[i];     //把变量读入桶中
		a[i]++;        //在对应桶中计数 
	} 
	
	for(i=0;i<=n;i++)    //依次判断a[0]~a[n] 
	    for(j=1;j<=a[i];j++)     //依次打印排序好的数列 
	    cout<

效果如下:

image-20220205161601600

错误:2、9、1变成了指定1、2、3数字的个数

错误原因:存放输入数组数据时,没有用一个数组来存放,导致最终丢失输入数据

修改如下:

#include   //调用万能头文件 
using namespace std;
#define MAX 200       //定义数组长度
int n,a[MAX],t[MAX];   //分别定义两个数组、t[MAX]存放初始化桶、a[MAX]存放输入数组
 
int main(){
    memset(t,0,sizeof t);     //桶数组初始化为0 
    cin>>n;                  //输入数组元素数量,也可以用scanf("%d",&n); 
    for(int i=1;i<=n;i++){
        cin>>a[i];          //读入数组每一个元素
        t[a[i]]++;          // 在初始化桶中计数 
    }
    for(int i=0;i<=n;i++){    //!!!依次判断a[0]~a[n],所以i一定要从0开始,否则会漏掉数组里的数字 
        if(t[i]!=0){
            for(int j=1;j<=t[i];j++) cout<

运行正确。

4、总结

(1)时间复杂度:O(M+N) m:桶的个数,n:待排序的个数

(2)缺点:不可对负数进行排序,因为数组的编号只能从a[0]开始

? 优点:是一个非常快速的排序方法

二、冒泡排序

1、算法思想与原理

思想:每次比较相邻的元素、若顺序错误则交换过来

原理:n个数进行排序,进行n-1次排序操作。“每一趟”需从第一位开始进行相邻两个数的比较,直至最后一个数比较完成。

2、算法逻辑

  • 设置for循环进行整体n-1趟比较(n为输入数组个数)
  • 循环将第i个数依次后后面每一个数字作比较
  • if条件进行大小比较,并交换
  • 循环输出结果

3、代码实现

蓝桥杯:基础练习——BASIC-13 数列排序

#include
#include 
using namespace std;

int main()
{
	int a[100];
	int i,j,t,n;
	cin>>n;             //输入一个数,表示接下来有3个数 
	for(i=1;i<=n;i++)   //循环读入n个数到数组a中 
	{
		cin>>a[i];
	}
//冒泡排序核心部分
	for(i=1;i<=n-1;i++)   //n个数排序,只需要进行n-1趟 
	{
		for(j=1;j<=n-i;j++)     //从第1位开始比较直到最后一个尚未归为的数 。
						    //第i个数比较时只需要比较后面的n-i位 ,所以循环中时n-i即可 
	{
		if(a[j]>a[j+1])     //比较大小并交换 
		{
			t=a[j]; a[j]=a[j+1]; a[j+1]=t;
		}
	}
	} 
//输出结果
	for(i=1;i<=n;i++) 
	{   
	cout<

代码完善后可完成按照名字对应的分数排序,代码修改如下:

#include
#include 
using namespace std;

struct student   //此处创建一个结构体储存姓名和分数 
{
	char name [21];
	char score;
};

int main()
{
	struct student a[100],t;
	int i,j,n;
	cin>>n;             //输入一个数,表示接下来有3个数 
	for(i=1;i<=n;i++)   //循环读入n个名字到结构体中 
	{
		cin>>a[i].name;
	}
		for(i=1;i<=n;i++)   //循环读入n个分数到结构体中 
	{
		cin>>a[i].score;
	}
//冒泡排序核心部分
	for(i=1;i<=n-1;i++)   //n个数排序,只需要进行n-1趟 
	{
		for(j=1;j<=n-i;j++)     //从第1位开始比较直到最后一个尚未归为的数 。
						    //第i个数比较时只需要比较后面的n-i位 ,所以循环中时n-i即可 
	{
		if(a[j].score>a[j+1].score)     //比较大小并交换 
		{
			t=a[j]; a[j]=a[j+1]; a[j+1]=t;
		}
	}
	} 
//输出结果
	for(i=1;i<=n;i++) 
	{   
	cout<

4、小结

  • 时间复杂度:O(N ^ 2 )

三、快速排序

1、算法思想:

? 基于“二分”的算法思想,选取一个基准数将和两个指针分别指向数列的两端,并与基准数进行大小比较。通过比较完成对基准数的归位,即基准数左边比其大右边比其小。依次选取基准数归位后,便可完成整个数列的排序。

  • 1.先从数列中取出一个数作为基准数。
  • 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
  • 3.再对左右区间重复第二步,直到各区间只有一个数。

2、算法实现

① 从数列中挑出一个元素,称为 “基准”(pivot),
② 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
③ 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

3、代码实现

#include 
#include
using namespace std;
#include  
using namespace std;
void quickSort(int array[],int left,int right) //left,right分别是数组的起始下标
{
    int i,j,k,temp;
    if(left=k))    //顺序很重要,要先从右往左找
             j--;
            if(i>n;
  for (i = 0; i>a[i];
    }
  quickSort(a, 0, 10); 
  cout<<"输出数组元素:"<

image-20220210180813117