C语言中的七种常用排序

今天,为大家整理了C语言中几种常用的排序,以及他们在实际中的运用(有Bug请在下方评论):

一.桶排序

#include <stdio.h>
int main()
{
    int book[1001],i,j,t,n;
    for(i=0;i<=1000;i++)
        book[i]=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&t);
        book[t]++;
    }
    for(i=1000;i>=0;i--)
        for(j=1;j<=book[i];j++)
            printf("%d ",i);
    getchar();getchar();
    return 0;
}

桶排序是一种快速简单的排序,但实用性不强。工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。 

二.冒泡排序

void bubblesort(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz-1;i++)
    {
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}
void print_arr(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
}
int main()
{
    int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr, sz);
    print_arr(arr, sz);
}

*冒泡排序核心部分是双重for循环,故空间占用较大。

冒泡排序的原理是:从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。

三.快速排序

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void Quick_Sort(int a[], int l, int r) {
	if (l < r) {
		int i, j, x;
		i = l;
		j = r;
		x = a[i];
		while(i<j) {
			while (i<j && a[j]>x) {
				j--; 
			}
			if (i < j) {
				a[i++] = a[j];
			}
			while (i < j && a[i] < x) {
				i++; 
			}
			if (i < j) {
				a[j--] = a[i]; 
			}
		}
		a[i] = x;
		Quick_Sort(a, l, i - 1);
		Quick_Sort(a, i+1, r);
	}
}
 
int main() {
	int arr[] = { 9,5,1,6,2,3,0,4,8,7 };
	Quick_Sort(arr, 0, 9);
	for (int i = 0; i < 10; i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
 
	return 0;
}

快速排序是最常用的一种排序,其思路为:

假设一个数组,我们可以用一种办法分成小数块和大数块,然后递归继续分成小数块和大数块,最后每一块都只有1个(或者0个)的时候,排序就完成了 

四.计数排序

//注:引用自DYson~的博客
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//计数排序
void CountSort(int *a, int len)
{
	assert(a);
	//通过max和min计算出临时数组所需要开辟的空间大小
	int max = a[0], min = a[0];
	for (int i = 0; i < len; i++){
		if (a[i] > max)
			max = a[i];
		if (a[i] < min)
			min = a[i];
	}
	//使用calloc将数组都初始化为0
	int range = max - min + 1;
	int *b = (int *)calloc(range, sizeof(int));
	//使用临时数组记录原始数组中每个数的个数
	for (int i = 0; i < len; i++){
		//注意:这里在存储上要在原始数组数值上减去min才不会出现越界问题
		b[a[i] - min] += 1;
	}
	int j = 0;
	//根据统计结果,重新对元素进行回收
	for (int i = 0; i < range; i++){
		while (b[i]--){
			//注意:要将i的值加上min才能还原到原始数据
			a[j++] = i + min;
		}
	}
	//释放临时数组
	free(b);
	b = NULL;
}
//打印数组
void PrintArray(int *a, int len)
{
	for (int i = 0; i < len; i++){
		printf("%d ", a[i]);
	}
	printf("\n");
}
int main()
{
	int a[] = { 3, 4, 3, 2, 1, 2, 6, 5, 4, 7 };
	printf("排序前:");
	PrintArray(a, sizeof(a) / sizeof(int));
	CountSort(a, sizeof(a) / sizeof(int));
	printf("排序后:");
	PrintArray(a, sizeof(a) / sizeof(int));
	system("pause");
	return 0;
}

计数排序的基本思想是对于给定的输入序列中的每一个元素 x,确定该序列中值小于 x 的元素的个数(此处并非比较各元素的大小,而是通过对元素值的计数和计数值的累加来确定)。一旦有了这个信息,就可以将 x 直接存放到最终的输出序列的正确位置上。例如,如果输入序列中只有 17 个元素的值小于 x 的值,则 x 可以直接存放在输出序列的第 18 个位置上。当然,如果有多个元素具有相同的值时,我们不能将这些元素放在输出序列的同一个位置上,因此,上述方案还要作适当的修改。

五.基数排序

#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <stdlib.h>
 
typedef struct Node
{
    int data;
    struct Node *next;
}Node,*List;
 
void InitList(Node *plist)
{
    assert(plist != NULL);
    plist->next = NULL;
}
 
Node *GetNode(int val)
{
    Node *pGet = (Node *)malloc(sizeof(Node));
    assert(pGet !=NULL);
 
    pGet->data = val;
    pGet->next = NULL;
    return pGet;
}
 
void Insert_tail(Node *plist,int val)
{
    assert(plist != NULL);
 
    Node *p = plist;
    while (p->next != NULL)
    {
        p = p->next;
    }
    Node *pGet = GetNode(val);
    p->next = pGet;
}
 
bool DelHeadNode(Node *plist,int *res)
{
    assert(plist != NULL);
 
    Node *pDel = plist->next;
    if (pDel == NULL)
    {
        return false;
    }
 
    *res = pDel->data;
    plist->next = pDel->next;
    free(pDel);
    pDel = NULL;
    return true;
}
 
int GetMaxBit(int *arr, int length)
{
    assert(arr != NULL);
    int max = INT_MIN;
    for (int i = 0; i < length; i++)
    {
        if (arr[i] > max)
        {
            max = arr[i];
        }
    }
    int digit = 0;
    while (max != 0)
    {
        digit++;
        max /= 10;
    }
    return digit;
}
 
int GetNum(int num, int figures)   // 123   123 / 1 % 10 == 3      123 / 10 % 10 == 2   123 / 100 % 10 == 1   
{
    int base = pow((double)10,(figures));
    return num / base % 10;
}
 
 
//figures --> 从右往左数第figures位的数字
void Radix(int *arr,int length,int figures)
{
    Node head[10];
    for (int i = 0; i < 10; i++)
    {
        InitList(&head[i]);  // 初始化10个桶
    }
 
    int tmp = 0;
    // 1、入桶 == 》 拿到数字,判断第figures位的数字为多少,并入相应的桶
    int i = 0;
    for (; i < length; i++)
    {
        tmp = GetNum(arr[i],figures);  // 第figures位的数字为tmp
        Insert_tail(&head[tmp],arr[i]); // 将 arr[i] 出到 tmp桶中
    }
 
    // 2、出桶
    i = 0; // i 代表数组下标
    int j = 0;
    while (j < 10)    // j 代表桶的个数
    {
        while (DelHeadNode(&head[j],&arr[i])) 
        {
            i++;
        }
        j++;
    }
}
 
 
void RadixSort(int *arr, int length)
{
    int count = GetMaxBit(arr ,length);
    for (int i = 0; i < count; i++)
    {
        Radix(arr,length,i);
    }
}
 
void Show(int *arr, int length)
{
    for (int i = 0; i < length; i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
}
 
 
void test(int *arr, int length)
{
    RadixSort(arr,length);
    Show(arr,length);
}
 
void test1()
{
    int arr[] ={1,2,3,4,12,4444,2222,1112,11};
    int length = sizeof(arr)/sizeof(arr[0]);
    test(arr,length);
}
 
void test2()
{
    int arr[] ={336,719,329,170,66,511,36,519,200,504};
    int length = sizeof(arr)/sizeof(arr[0]);
    test(arr,length);
}
 
int main()
{
    test1();
    test2();
    return 0;
}

基数排序与桶排序思路相仿,但优化了许多(也麻烦了许多,不太建议日常使用)

六.插入排序

示意图: 

//插入排序(从小到大) 
#include<stdio.h>
#include<stdlib.h>
int number[100000000];     //定义数组 
void insertion_sort(int *number,int n)    //定义一个插入函数"insertion_sort" 
{
    int i,t,temp;  
    for(i=1;i<n;i++)  //外层循环遍历 (需要插入n个数)
    {
        temp=number[i];  //取未排序列的元素,有n个,从第一个开始取
        for(t=i;t>0&&number[t-1]>temp;t--);
		{
			number[t]=number[t-1];//依次比较并右移
			number[t]=temp;//放进合适位置
		}
	}
}
int main() 
{
    int i=0,n,j=0;
    printf("输入数字个数:\n");    
    scanf("%d",&n);       //输入要排序的数字的个数 
    printf("输入%d个数:\n",n);
    for(j=0;j<n;j++)       //将所有数全放入number数组中 
        scanf("%d",&number[j]) ;
    insertion_sort(number,n);   //引用插入函数 
    for(i=0;i<n-1;i++)    //循环输出 
        printf("%d ",number[i]);    //格式需要  
    printf("%d\n",number[i]);
	system("pause");
    return 0;
}
 

 插入排序其实就是拿未排序数组中的第一个值,插入到已排序完中的数组的合适位置,来完成排序

七.堆排序

#include <stdio.h>
#include <malloc.h>
void HeapAdjust(int a[],int s,int m)//一次筛选的过程
{
    int rc,j;
    rc=a[s];
    for(j=2*s;j<=m;j=j*2)//通过循环沿较大的孩子结点向下筛选
    {
        if(j<m&&a[j]<a[j+1]) j++;//j为较大的记录的下标
        if(rc>a[j]) break;
        a[s]=a[j];s=j;
    }
    a[s]=rc;//插入
}
void HeapSort(int a[],int n)
{
    int temp,i,j;
    for(i=n/2;i>0;i--)//通过循环初始化顶堆
    {
        HeapAdjust(a,i,n);
    }
    for(i=n;i>0;i--)
    {
        temp=a[1];
        a[1]=a[i];
        a[i]=temp;//将堆顶记录与未排序的最后一个记录交换
        HeapAdjust(a,1,i-1);//重新调整为顶堆
    }
}
int main()
{
    int n,i;
    scanf("%d",&n);
    int a[n+1];
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    HeapSort(a,n);
}

堆排序的思想基于二叉树,比较麻烦

堆排序方法对记录较少的文件并不值得提倡,但对n较大的文件还是很有效的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/641014.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第八节 条件装配案例讲解

一、条件装配的作用是什么 条件装配是 Spring 框架中一个强大的特性&#xff0c;使得开发者能够创建更加灵活和可维护的应用程序。在 Spring Boot 中&#xff0c;这个特性被大量用于自动配置&#xff0c;极大地简化了基于 Spring 的应用开发。 二、条件装配注解 <dependen…

为什么要用虚拟时钟Virtual clock?

通常RTL设计要求对芯片/module的输入信号进行reg_in打拍处理&#xff0c;对芯片/module的输出也要求做reg_out打拍处理&#xff0c;这是良好的代码习惯&#xff0c;为时序收敛留下足够裕量&#xff0c;也避免顶层例化综合后的子模块时出现模块间IO时序不满足的情况。综合阶段可…

DNF手游攻略:角色培养与技能搭配!游戏辅助!

角色培养和技能搭配是《地下城与勇士》中提升战斗力的关键环节。每个职业都有独特的技能和发展路线&#xff0c;合理的属性加点和技能搭配可以最大化角色的潜力&#xff0c;帮助玩家在各种战斗中立于不败之地。接下来&#xff0c;我们将探讨如何有效地培养角色并搭配技能。 角色…

亿图图示——文本换行

一、点击文本框&#xff0c;选择更多 二、勾选文本换行

数据结构和算法基础(二)

树和二叉树——树的基本概念 树和二叉树——树转二叉树 树和二叉树——查找二叉树&#xff08;二叉排序树&#xff09; 树和二叉树——构造霍夫曼树&#xff08;最优&#xff09; 树和二叉树——线索二叉树 树和二叉树——平衡二叉树 图——基本概念 1、有向图 2、无向图 3、完…

Platformer Project

Platformer项目适合那些寻找坚实基础来构建你梦想中的3D平台游戏的人,提供受该类型最具影响力游戏启发的核心机制。 一般功能 移动支持; 自定义运动学角色控制器; Humanoid Rig支持(共享动画); 保存/加载(二进制、JSON或Playerprefs); 支持多个存储槽; 三星、硬币和最…

Dockerfile使用

1.Dockerfile是什么 官网地址 https://docs.docker.com/reference/dockerfile/概念 是什么 Dockerfile 是用于构建 Docker 镜像的文本文件&#xff0c;它包含一系列的指令&#xff08;instructions&#xff09;和参数&#xff0c;用于描述如何构建和配置镜像。 Dockerfile 是…

微信小程序中van-tab的title(动态)根据文本内容,自适应宽度

小程序van-tab的title&#xff08;动态&#xff09;根据文本内容&#xff0c;自适应宽度 效果图代码主要调整点 效果图 代码 <van-tabs color"#00aaff" active"{{ active }}" bind:click"onTabChange"><van-tab title"7天内&quo…

游戏后台开发技术全面解析

在这个数字时代&#xff0c;游戏产业已经成为全球最受欢迎的娱乐方式之一。从简单的手机游戏到复杂的大型多人在线角色扮演游戏&#xff08;MMORPG&#xff09;&#xff0c;游戏的世界正变得越来越丰富和多样化。而这一切的背后&#xff0c;都离不开强大的游戏后台技术支持。在…

【网络技术】【Kali Linux】Wireshark嗅探(十四)QUIC(快速UDP互联网连接)协议报文捕获及分析

往期 Kali Linux 上的 Wireshark 嗅探实验见博客&#xff1a; 【网络技术】【Kali Linux】Wireshark嗅探&#xff08;一&#xff09;ping 和 ICMP 【网络技术】【Kali Linux】Wireshark嗅探&#xff08;二&#xff09;TCP 协议 【网络技术】【Kali Linux】Wireshark嗅探&…

Mac电脑太卡了怎么办 Mac电脑常见问题 cleanmymacX有必要买吗

当我们遇到mac电脑出现卡顿的情况&#xff0c;首先应排除是否是电脑硬件的问题&#xff0c;可以通过重启电脑来检测是否硬盘或程序是否发生错误。其次对电脑进行全面的健康检测&#xff0c;找到具体卡顿问题。 磁盘空间不足是导致电脑运行缓慢的常见原因之一。定期清理不需要的…

PMBOK® 第六版 项目经理的角色

项目经理普遍是一个责任大但权力有限的角色&#xff0c;是一个综合的中层领导者&#xff0c;负责项目从启动到收尾的全过程。他需要整合项目管理的各个方面&#xff0c;以确保项目目标的实现&#xff0c;并满足相关方的期望和需求。在工作中&#xff0c;项目经理大部分时间都用…

【面试干货】杨辉三角形

【面试干货】杨辉三角形 1、实现思想2、代码实现 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 杨辉三角形&#xff08;也称帕斯卡三角形&#xff09;是一个规则的数字三角形&#xff0c;它的构造方法是&#xff0c;第一行只有一个数字1&a…

SQL Server基础学习笔记

SQL Server基础学习笔记 SQL Server简介 SQL Server是微软开发的一种关系数据库管理系统&#xff08;RDBMS&#xff09;。它是一个功能强大且广泛使用的数据库平台&#xff0c;支持存储、管理和检索数据&#xff0c;并提供各种工具和功能来提高开发和管理效率。 安装与配置 …

麻省理工出品!这个自动化神器让你的电脑自己工作

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

建议收藏 | 2023年生物学类SCI期刊影响因子最新预测,Molecular Plant遥遥领先

公众号&#xff1a;生信漫谈&#xff0c;获取最新科研信息&#xff01; 建议收藏 | 2023年生物学类SCI期刊影响因子最新预测&#xff0c;Molecular Plant遥遥领先https://mp.weixin.qq.com/s/tFINUzZ1l4H9x1HWTq1kFg 2023年生物学类SCI期刊影响因子最新预测&#xff0c;Molecu…

大佬大讲堂(1)电机及其驱动内核-自适应观察器

点击上方 “机械电气电机杂谈 ” → 点击右上角“...” → 点选“设为星标 ★”&#xff0c;为加上机械电气电机杂谈星标&#xff0c;以后找夏老师就方便啦&#xff01;你的星标就是我更新动力&#xff0c;星标越多&#xff0c;更新越快&#xff0c;干货越多&#xff01; 关注…

React 中的jsx 的语法使用

react 中是使用 JSX 编写标签的 它是可选的&#xff0c;但大多数 React 项目会使用 JSX&#xff0c;主要是它很方便。所有 我们推荐的本地开发工具 都开箱即用地支持 JSX。 JSX 比 HTML 更加严格。你必须闭合标签&#xff0c;如 <br />。你的组件也不能返回多个 JSX 标…

冷干机使用中的注意事项

冷干机使用中的注意事项 使用冷干机时&#xff0c;以下是几个注意事项&#xff1a; 安装位置&#xff1a;选择一个通风良好、温度适宜的位置安装冷干机。确保周围环境没有过多的灰尘、腐蚀性气体或其他污染物&#xff0c;以免对冷干机的正常运行和寿命产生不利影响。 电源要求…

高效使用 LaTeX 技巧

但对于一般人而言&#xff0c;你不需要通过学习 Vim 来达到高效编辑 LaTeX 的方式。而是通过一些比较容易实现的方式&#xff0c;使得你能够在原来的基础上更加高效得使用 LaTeX&#xff0c;并达到以思考的速度输入 LaTeX 的方式。 在第一部分&#xff0c;我会首先介绍高效编辑…