我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C语言中如何实现桶排序

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C语言中如何实现桶排序

C语言实现桶排序

1.原理

由映射函数分配初始元素的键值,然后将这些元素放入对应键值的桶中,并对桶中的数据进行排序。然后依次将每个桶中的元素分出得到排好序的序列。

在这里插入图片描述

2.桶排序不是基于比较的排序

将N个待排序的元素放入桶中只需要O(n)时间。后续则是对桶中元素的排序,所以当桶越多的时候,桶中的元素会越少,所采取的基于比较的排序算法的时间则会大大减少。

所以,这里我们就可确定了一个重点,即是桶的数量必须是有限个的,可以经过一系列运算得到具体数目的。

3.桶的实现形式

我们以结构体数组存储单链表实现。以结构体数组的数组单元来春初链表的头节点,头节点含有两个变量,为指针变量(指向下一个链表节点),和整形变量key(就是如下图里面头节点的值),key表示链表的节点个数。

在这里插入图片描述

4.桶中元素的排序

因为桶是采取单链表来实现的,所以桶中元素的插入就是链表中的元素插入。这里要注意分桶为空和非空两种情况来插入。

	if(p->key == 0){
			bucket_table[index]->next = node_branch;
			(bucket_table[index]->key)++;
		} 
		//链表的插入形式,按照大小从后到大。 
		else{
			while(p->next!=NULL && p->next->key <= node_branch->key){
			p=p->next;				
			}	
			node_branch->next = p->next;
			p->next = node_branch;
			(bucket_table[j]->key)++;
		}

4.最后就是将桶中的元素依次输出

或存放到数组原始序列的数组中。

5完整代码如下

#include<stdio.h>
#include<stdlib.h>
//整体思想大致为用数组单元内存放的为结构体式的链表,每个链表称为一个桶。通里面容纳的都是键值相同的元素。 
// 之后便是查看对应元素的键值,然后放进与之对应的桶,还需注意桶为空和不空的时的放入方式
//桶元素的插入就是看桶以什么方式的实现。这里桶以链表的形式表现,所以桶中元素的插入即为链表中数组的插入。
 
//桶排序的特点是要有界限分明的桶,而不能是无限个桶,也就是说桶排序的个数应该是可以确定的,有限个的。 
//这里链表实现桶排序的还有要注意的点,就是数组的首地址其实链表的头节点,有这里的值确定该桶的元素个数,并由这里出发寻找其他元素。 
typedef struct node *Snode;
typedef struct node{
	int key;
	Snode next;
}BBc;

void sort(int keys[],int keys_size,int bucket_size)
{
	Snode *bucket_table = (Snode *)malloc(bucket_size*sizeof(Snode));//为结构体数组分配空间。 
	for(int i=0;i<bucket_size;i++)//对每个数组单元赋予内存空间时,初始化每个结构体数组单元。 
	{
		bucket_table[i] = (Snode)malloc(sizeof(Snode));//这一步是必要的,因为之前只是给数组分配了一连串的存储空间,但是每个单元的存储地址都是 
	    //不确定,也不确定该方式是否会自动地分配内存空间给每个数组单元。 
	    //那么这样准确的给数组单眼分配的空间是占用之前的分配给数组的空间,还是重新分拨其他的空间给数组单元。
		//其实应该是分配之前给整个数组单元分配的一段存储空间。 
		bucket_table[i]->key = 0;
		bucket_table[i]->next = NULL;
	}//其实创建数组这部分应该放在主函数那里,否则某些功能只能在这个函数中使用。 
	for(int j=0;j<keys_size;j++)
	{
		Snode node_branch = (Snode)malloc(sizeof(Snode));//定义一个节点,满足条件时链入以链表为表现形式的桶。 
		node_branch->key = keys[j];
		node_branch->next = NULL;
		int index = keys[j]/10;
		Snode p = bucket_table[index];//p用来充当指向循环的变量。 
		//桶为空和非空时的两种插入形式 
		if(p->key == 0){
			bucket_table[index]->next = node_branch;
			(bucket_table[index]->key)++;
		} 
		//链表的插入形式,按照大小从后到大。 
		else{
			while(p->next!=NULL && p->next->key <= node_branch->key){
			p=p->next;				
			}	
			node_branch->next = p->next;
			p->next = node_branch;
			(bucket_table[j]->key)++;
		}
	}
	//以此输出每个桶中的所有元素。 
	for(int i=0;i<bucket_size;i++){
		for(Snode k = bucket_table[i]->next;k!=NULL;k = k->next){
			printf(" %d ",k->key);
		}
	}
	
}

int main()
{
	int keys[] = {49,26,53,47,89,31,72,11,33};
	int keys_size = sizeof(keys)/sizeof(int);
	int bucket_size = keys_size+2;
	sort(keys,keys_size,bucket_size);
}

7.桶排序的时间复杂度和空间复杂度

前面的将n个待排序元素分到对应键值的桶中只需要O(n)时间,后面则是基于比较的排序算法,基于比较的排序算法最快可以达到:O(nlogn)时间。

所以桶里面的排序算法的选择也会影响到桶排序的速度。至于空间复杂度,一般都是占用空间比较大,以便每个桶中尽可能的达到一个元素,这样桶里面的排序也是O(n)时间,可以说是非常快速的。所以桶排序也是一种空间换时间的排序。 

另外桶排序的元素键值应该相差不大,以免照成空间的浪费。另外,划分的桶也应该是有限个的。

【排序】图解桶排序

思想

一句话总结:划分多个范围相同的区间,每个子区间自排序,最后合并

桶排序是计数排序的扩展版本,计数排序可以看成每个桶只存储相同元素,而桶排序每个桶存储一定范围的元素,通过映射函数,将待排序数组中的元素映射到各个对应的桶中,对每个桶中的元素进行排序,最后将非空桶中的元素逐个放入原序列中。

桶排序需要尽量保证元素分散均匀,否则当所有数据集中在同一个桶中时,桶排序失效。

图解过程

核心代码

public static void bucketSort(int[] arr){
    
    // 计算最大值与最小值
    int max = Integer.MIN_VALUE;
    int min = Integer.MAX_VALUE;
    for(int i = 0; i < arr.length; i++){
        max = Math.max(max, arr[i]);
        min = Math.min(min, arr[i]);
    }
    
    // 计算桶的数量
    int bucketNum = (max - min) / arr.length + 1;
    ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
    for(int i = 0; i < bucketNum; i++){
        bucketArr.add(new ArrayList<Integer>());
    }
    
    // 将每个元素放入桶
    for(int i = 0; i < arr.length; i++){
        int num = (arr[i] - min) / (arr.length);
        bucketArr.get(num).add(arr[i]);
    }
    
    // 对每个桶进行排序
    for(int i = 0; i < bucketArr.size(); i++){
        Collections.sort(bucketArr.get(i));
    }
    
    // 将桶中的元素赋值到原序列
	int index = 0;
	for(int i = 0; i < bucketArr.size(); i++){
		for(int j = 0; j < bucketArr.get(i).size(); j++){
			arr[index++] = bucketArr.get(i).get(j);
		}
	}  
}

复杂度分析

1. 时间复杂度:O(N + C)

对于待排序序列大小为 N,共分为 M 个桶,主要步骤有:

  • N 次循环,将每个元素装入对应的桶中
  • M 次循环,对每个桶中的数据进行排序(平均每个桶有 N/M 个元素)

一般使用较为快速的排序算法,时间复杂度为O(NlogN),实际的桶排序过程是以链表形式插入的。

整个桶排序的时间复杂度为:

O(N)+O(M*(N/M*log(N/M)))=O(N*(log(N/M)+1))

当 N = M 时,复杂度为 O(N)

2. 额外空间复杂度:O(N + M)

稳定性分析

桶排序的稳定性取决于桶内排序使用的算法。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C语言中如何实现桶排序

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C语言中如何实现桶排序

这篇文章主要介绍了C语言中如何实现桶排序问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-11-16

C语言中如何实现插入排序

这篇文章主要讲解了“C语言中如何实现插入排序”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言中如何实现插入排序”吧!程序代码:#include #include
2023-06-16

c语言如何实现排序算法

小编给大家分享一下c语言如何实现排序算法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.选择排序-简单选择排序选择排序是最简单的一种基于O(n2)时间复杂度的排
2023-06-15

C语言如何实现快速排序

今天小编给大家分享一下C语言如何实现快速排序的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。交换排序的思想基本思想:所谓交换,
2023-07-02

c语言如何排序

这篇文章给大家分享的是有关c语言如何排序的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。c语言排序方法有:1、简单选择排序,基于O(n2)时间复杂度的排序算法;2、冒泡排序;3、简单插入排序;4、希尔排序;5、归并
2023-06-20

如何使用C语言实现快速排序

本篇内容主要讲解“ 如何使用C语言实现快速排序”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“ 如何使用C语言实现快速排序”吧!快速排序的基本思想是:任取待排序数列中的一个数作为 key 值,通过
2023-07-05

C语言如何实现快速排序算法

这篇文章将为大家详细讲解有关C语言如何实现快速排序算法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。代码#define _CRT_SECURE_NO_WARNINGS 1//快速排序算法,递归求解#in
2023-06-22

C语言如何实现数组元素排序

这篇文章主要讲解了“C语言如何实现数组元素排序”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言如何实现数组元素排序”吧!前言在实际开发中,有很多场景需要我们将数组元素按照从大到小(或者从
2023-07-05

C语言如何实现交换排序算法

这篇文章主要介绍了C语言如何实现交换排序算法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言如何实现交换排序算法文章都会有所收获,下面我们一起来看看吧。一、冒泡排序1.基本思想对于很多同学来说冒泡排序是再熟
2023-07-02

c语言排序怎么实现

c 语言中实现排序可以使用多种算法,包括:冒泡排序:比较相邻元素,将较小的元素向前移动。选择排序:找到无序序列中的最小元素,并与第一个元素交换位置。插入排序:将元素逐个插入到已有序序列中。归并排序:分治排序,合并排序后的左右两半。快速排序:
c语言排序怎么实现
2024-05-15

C语言实现快速排序

快速排序不一定是稳定排序,这篇文章主要为大家详细介绍了C语言实现快速排序算法,具有一定的参考价值,感兴趣的同学可以借鉴阅读
2023-05-14

c语言冒泡排序怎么实现

C语言冒泡排序的实现步骤如下:1. 定义一个数组来存储待排序的元素。2. 使用两层循环来比较相邻两个元素的大小,并进行交换。3. 外层循环控制需要比较的轮数,共需比较n-1轮,其中n为数组元素的个数。4. 内层循环从第一个元素开始,比较相邻
2023-08-25

C语言如何给数字排序

C语言可以使用以下几种方法来给数字排序:冒泡排序:比较相邻的两个元素,如果顺序错误则交换位置,每次遍历都将最大(或最小)的元素移到最后,重复执行直到排序完成。void bubbleSort(int arr[], int n) {for (i
C语言如何给数字排序
2024-02-29

c语言中冒泡法排序法怎么实现

冒泡排序法是一种简单的排序算法,它重复地遍历要排序的数组,一次比较两个元素,如果它们的顺序错误就把它们交换位置。实现冒泡排序法的C语言代码如下:#include void bubbleSort(int arr[], in
c语言中冒泡法排序法怎么实现
2024-03-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录