随笔 - 6  文章 - 0  评论 - 0  阅读 - 7897

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

排序

一、桶排序

1、算法思想与原理

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

2、算法思路

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

3、代码实现

3.1最简单粗暴滴方法

#include<iostream>
#include<stdio.h>
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<<i;
		
		return 0; 
} 

说明:

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

优化:

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

3.2 进阶可指定数组大小

#include<iostream>
#include<stdio.h>
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<<i;
		
		return 0; 
} 

效果如下:

image-20220205161601600

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

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

修改如下:

#include<bits/stdc++.h>   //调用万能头文件 
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<<i<<' ';
        }
    }
    return 0;
}

运行正确。

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<iostream>
#include <string>
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<<a[i]<<' '; 
    }
	 
		return 0; 
} 

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

#include<iostream>
#include <string>
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<<a[i].name<<' '; 
    }
	
	  
		return 0; 
} 

4、小结

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

三、快速排序

1、算法思想:

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

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

2、算法实现

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

3、代码实现

#include <string>
#include<stdio.h>
using namespace std;
#include<iostream>  
using namespace std;
void quickSort(int array[],int left,int right) //left,right分别是数组的起始下标
{
    int i,j,k,temp;
    if(left<right)
    {
        i=left;        
        j=right;
        k=array[i];  //关键值(基准值) 
        do{
            while((i<j)&&(array[j]>=k))    //顺序很重要,要先从右往左找
             j--;
            if(i<j)               //右边的元素小于k,移到k的左边。
            {
                array[i]=array[j];  
                i++;             
            }
            while((i<j)&&array[i]<=j)  //再从左往右找
                i++;
            if(i<j)  //左边的值小于k,移到看k的右边
            {
                array[j]=array[i];
            }

        }while(i!=j);
          array[i]=k;//复制key值到array[i] 
        quickSort(array,left,i-1);//对i的左侧进行排序
            quickSort(array,i+1,right);//对z的右侧进行排序
    }
}
int main()
{
    int a[110], i,n;
    // char tmp[20];
    cin>>n;
  for (i = 0; i<n; i++) {
 
   cin>>a[i];
    }
  quickSort(a, 0, 10); 
  cout<<"输出数组元素:"<<endl; 
  for (i = 0; i<n; i++)
   cout<<a[i]<<' ';
     return 0;
 }

image-20220210180813117

posted on   澹月  阅读(103)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示