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 …

Verilog实战学习到RiscV - 2 : wire 和 reg 的区别

Verilog: wire 和 reg 的区别 1 引言 看Verilog例子过程中&#xff0c;总是分不清 wire 和 reg 的区别。这篇文章把两者放在一起总结一下&#xff0c;并且对比何时使用它们。 1.1 wire &#xff1a;组合逻辑 wire 是 Verilog 设计中的简单导线&#xff08;或任意宽度的总线…

mysql 权限apparmor=“DENIED“问题

简单记录下&#xff0c;最近安装一个mysql&#xff0c;但是修改了对应的数据文件的目录&#xff0c;也就是在/etc/mysql 修改了对应配置文件 [mysqld] datadir/data/mysql/data socket/var/lib/mysql/mysql.sock group_concat_max_len1024000 log-error/data/mysql/log/mysql-…

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…

算法在C++中的应用

算法是计算机程序设计的核心&#xff0c;是解决特定问题的一系列步骤或指令的集合。而C作为一种高级编程语言&#xff0c;提供了实现这些算法的工具和平台。C的丰富特性&#xff0c;如面向对象编程、泛型编程、模板元编程等&#xff0c;使得算法的实现更为高效、灵活和易于维护…

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

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

前端自定义滚动条样式

/* 滚动条轨道 */ ::-webkit-scrollbar-track {background-color: #f1f1f1; /* 轨道背景色 */ }/* 滚动条滑块 */ ::-webkit-scrollbar-thumb {background-color: #888; /* 滑块颜色 */border-radius: 5px; /* 滑块圆角 */ }/* 鼠标悬停在滑块上的效果 */ ::-webkit-scrollbar-…

关于ref和reactive

今天绑定一个表格时半天无法显示数据&#xff0c;发现是formData绑定错了&#xff0c;写成了reactive&#xff0c;console.log中拿到数据了就是不显示&#xff0c;找了大半天才知道原来要调用.ref才能显示&#xff0c;reactive更多的是传值。 .ref 是用于数据绑定的。在Vue3中…

Claude首位设计师的OpenAI之旅与AI时代成长法则

在这个飞速发展的AI时代,每一次技术革新都伴随着互联网人的成长与挑战。近期,Claude首位设计师的跳槽至OpenAI,不仅在业界激起千层浪,也为我们揭示了一套宝贵的职场成长法则。这位设计师以其丰富的经验和独到的见解,为我们绘制了一幅通往成功的路线图,让我们一同探索这些…

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…

pgsql

创建分区表&#xff1a; PostgreSQL分区表_pg分区表-CSDN博客 创建list分区的函数 create or replace function create_list_fq(tb_name char, row_name char) returns int AS $$ declares char; beginraise notice CREATE TABLE if not exists %_% PARTITION OF % FOR VALU…

005、API_数据结构

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

Docker疑难杂症解析与解决方案

Docker疑难杂症解析与解决方案 Docker 是一个开源的应用容器引擎&#xff0c;它允许开发者打包他们的应用以及应用的运行环境到一个可移植的容器中。Docker 容器可以在任何支持Docker的机器上运行&#xff0c;确保了环境的一致性。然而&#xff0c;在使用 Docker 的过程中&…

从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;就一定有一份资源是你的&…

CSP路径解析(简单易懂)

用栈模拟即可。 #include<bits/stdc.h> using namespace std;int n; string start; vector<string> v;//栈结构 void split_stack(string str,vector<string> &v)//将str拆分到栈中 {stringstream stemp(str);string ss;while(getline(stemp,ss,/)){if(…