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将数组都初始化为0int 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位的数字为tmpInsert_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较大的文件还是很有效的。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二进制中1的个数c++

题目描述 计算鸭给定一个十进制非负整数 NN&#xff0c;求其对应 22 进制数中 11 的个数。 输入 输入包含一行&#xff0c;包含一个非负整数 NN。(N < 10^9) 输出 输出一行&#xff0c;包含一个整数&#xff0c;表示 NN 的 22 进制表示中 11 的个数。 样例输入 100 …

001集—创建、写入、读取文件fileopen函数——vb.net

此实例为在指定路径下创建一个txt文本文件&#xff0c;在文本文件内输入文字&#xff0c;并弹窗显示输入文字&#xff0c;代码如下&#xff1a; Public Class Form1Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.ClickDim testcontent As Str…

英语学习笔记26——Where is it?

Where is it? 它在那里&#xff1f; 课文部分

springboot+vue+mybatis校园兼职平台+PPT+论文+讲解+售后

社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱&#xff0c;也逐渐进入了每个学生的使用。互联网具有便利性&#xff0c;速度快&#xff0c;效率高&#xff0c;成本低等优点。 因此&#xff0c;构建符合自己要…

opencv进阶 ——(五)图像处理之马赛克

一、遍历图像并对每个马赛克区域进行像素化处理 for (int y 0; y < image.rows; y blockSize) {for (int x 0; x < image.cols; x blockSize) {cv::Rect rect cv::Rect(x, y, std::min(blockSize, image.cols - x), std::min(blockSize, image.rows - y));cv::Scal…

新建一个STM32工程(精简版)

一、新建一个STM32工程 二、建立三个文件夹 1、Start文件夹里的东西 &#xff08;1&#xff09;启动文件&#xff1a;STM32入门教程资料\固件库\STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm &#xff08;2&#xff09;STM32…

005、API_数据结构

键的数据结构类型&#xff0c;它们分别是&#xff1a; string&#xff08;字符串&#xff09;、hash&#xff08;哈希&#xff09;、list&#xff08;列表&#xff09;、set&#xff08;集合&#xff09;、zset&#xff08;有序集 合&#xff09;&#xff0c;这些只是Redis对外…

从0开始学统计-蒙彼利埃尔悖论与条件概率

1.什么叫均衡可比&#xff1f; "均衡可比"指的是在进行比较时&#xff0c;确保所比较的对象或情况具有相似的特征和条件&#xff0c;以保持比较的公正性和准确性。这个概念通常应用于研究设计和数据分析中&#xff0c;以确保比较结果的可信度和有效性。 在研究中&a…

P6160 [Cnoi2020] 向量

[Cnoi2020] 向量 题目背景 向量(vector)&#xff0c;指具有大小(Magnitude)和方向(Direction) 的量。 与向量对应的量叫做数量(Scalar)&#xff0c;数量只有大小&#xff0c;没有方向。 对于 Cirno 来说&#xff0c;整天环绕氷屋的旋转 Sangetsusei 们是向量而不是数量。 Sun…

【JavaSE】/*类和对象(上)*/

目录 一、什么是类&#xff0c;什么是对象 二、类和对象的关系 三、学习类和对象的目的 四、怎样创建一个类 4.1 语法形式 4.2 创建示例 示例一&#xff1a;日期对象 示例二&#xff1a;小狗对象 示例三&#xff1a;学生对象 4.3 注意事项 4.4 修改public修饰的主类…

信号量——多线程

信号量的本质就是一个计数器 在多线程访问临界资源的时候&#xff0c;如果临界资源中又有很多份分好的资源&#xff0c;那么就可以通过信号量来表示里面还有多少份资源&#xff0c;且每份资源只有一个线程可以访问 线程申请信号量成功&#xff0c;就一定有一份资源是你的&…

python机器学习及深度学习在空间模拟与时间预测

原文链接https://mp.weixin.qq.com/s?__bizMzUyNzczMTI4Mg&mid2247628504&idx2&sn6fe3aeb9f63203cfe941a6bb63b49b85&chksmfa77a9e5cd0020f3aa4f01887e75b15096a182c2b5b42c1044787aa285c650f1469a0ef28aec&token2124656491&langzh_CN&scene21#we…

网络模型—BIO、NIO、IO多路复用、信号驱动IO、异步IO

一、用户空间和内核空间 以Linux系统为例&#xff0c;ubuntu和CentOS是Linux的两种比较常见的发行版&#xff0c;任何Linux发行版&#xff0c;其系统内核都是Linux。我们在发行版上操作应用&#xff0c;如Redis、Mysql等其实是无法直接执行访问计算机硬件(如cpu&#xff0c;内存…

勒索软件分析_Conti

0. Conti介绍 勒索软件即服务&#xff08;Ransomware as a Service&#xff0c;RaaS&#xff09;变体 Conti 推出还不到两年&#xff0c;已经进行了第七次迭代。Conti被证明是一种敏捷而熟练的恶意软件威胁&#xff0c;能够自主和引导操作&#xff0c;并具有无与伦比的加密速度…

详细分析Element中的Drawer(附Demo)

目录 前言1. 基本知识2. Demo2.1 基本用法2.2 不同方向2.3 自定义大小2.4 嵌入表单2.5 嵌套抽屉 3. 实战4. Element Plus&#xff08;Drawer&#xff09; 前言 对于该组件针对Vue2比较多&#xff0c;而Element Plus中的Drawer针对Vue3比较多 此处的Demo主要偏向Vue2 后续的El…

探索 Mistral 新发布的具有原生函数调用功能的 7B 模型【附notebook文件】

引言 Mistral 发布了新版的 7B 模型&#xff0c;这次更新引入了原生函数调用功能。对于开发者和 AI 爱好者来说&#xff0c;这一更新极具吸引力&#xff0c;因为它增强了模型的功能和实用性。在这篇博客中&#xff0c;我们将深入探讨这些新功能&#xff0c;展示如何使用该模型…

小程序-修改用户头像

1、调用拍照 / 选择图片 // 修改头像 const onAvatarChange () > { // 调用拍照 / 选择图片 uni.chooseMedia({ // 文件个数 count: 1, // 文件类型 mediaType: [image], success: (res) > { console.log(res) // 本地临时文件路径 (本地路径) const { tempFilePath } …

wordpress主题模板兔Modown 9.1开心版附送erphpdown v17.1插件

Modown 9.1开心版是一款模板兔开发的wordpress主题可&#xff0c;持续更新多年&#xff0c;优秀的资源下载类主题该模板基于Erphpdown&#xff0c;可以销售软件、视频教程、文章等等&#xff0c;通过主题和插件结合可以实现付费下载、付费阅读等功能&#xff0c;配合模板兔的一…

数组-下一个排列

一、题目描述 二、解题思路 1.反向遍历当前排列&#xff0c;比如 排列A[a,b,c,d,e,f...] &#xff0c;当遍历到e时&#xff0c;说明以 a,b,c,d,e为前缀的排列中不存在A排列的下一个排列。 2.把e&#xff08;位置设为idx&#xff09;和后面的元素作比较&#xff1a; 2.1 如果有…

【数据结构(邓俊辉)学习笔记】二叉树02——遍历

文章目录 0.概述1. 先序遍历1.1 递归版1.1.1 实现1.1.2 时间复杂度1.1.3 问题 1.2 迭代版11.3 迭代版21.3.1 思路1.3.2 实现1.3.3 实例 2. 中序遍历2.1 递归形式2.2 迭代形式2.2.1 观察2.2.2 思路&#xff08;抽象总结&#xff09;2.2.3 构思 实现2.2.4 分摊分析 3. 后序遍历3…