八大排序源码(含优化)

文章目录

  • 1、直接插入排序
  • 2、希尔排序
  • 3、选择排序
  • 4、冒泡排序
  • 5、堆排序
  • 6、快速排序
    • 快速排序递归实现
      • 霍尔法
      • 挖坑法
      • 前后指针法
      • 快速排序小区间优化
    • 快速排序非递归实现
  • 7、归并排序
    • 归并排序递归实现
    • 归并排序非递归
  • 8、计数排序

大家好,我是纪宁,这篇文章是关于八大排序的源代码,具体实现过程会在后续文章中介绍。

1、直接插入排序

时间复杂度O(N^2),原数据越有序,效率越高。
当原数据有序时,则时间复杂度为O(N)。原数据倒序时,时间复杂度为O(N^2)
在这里插入图片描述

void InsertSort(int* a, int n)//直接插入排序
{for (int i = 0; i < n - 1; i++){int end = i;int tmp = a[end+1];while (end >= 0){if (a[end] >tmp){a[end + 1] = a[end];}else{break;}end--;}a[end + 1] = tmp;}
}

2、希尔排序

时间复杂度:O(N^1.3) 空间复杂度:O(1)
希尔排序是插入排序的优化,整体思路是先预排序,使原数据更接近有序,等到gap==1时,就变成了直接插入排序。

void ShellSort(int* arr, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;//gap也可以 /=2;奇特数字必须保证gap最后的值为1for (int i = 0; i < n - gap; i++){int end = i;int tmp = arr[end + gap];while (end >= 0){if (tmp < arr[end]){arr[end + gap] = arr[end];}else{break;}end -= gap;}arr[end + gap] = tmp;}}
}

3、选择排序

时间复杂度:O(N^2) 空间复杂度:O(1)
每次选择一个最大或者最小的数,使其出现在正确的位置。
在这里插入图片描述

void SelectSort(int* a, int n)
{for (int j = 0; j < n; j++){int mini = j;int maxi= n - j-1;for (int i = j; i < n-j; i++){if (a[i] < a[mini]){mini = i;}if (a[i] > a[maxi]){maxi = i;}}Swap(&a[mini], &a[j]);if (maxi == j){maxi = mini;//最大值如果在 j 这个位置的话,结果这个位置被换成了min 的值}Swap(&a[maxi], &a[n-1-j]);}
}

4、冒泡排序

时间复杂度:O(N^2) 空间复杂度:O(1)
思路最简单的排序,所有程序员的白月光!
在这里插入图片描述

void BubbleSort(int* a, int n)//冒泡排序
{for (int i = 0; i < n; i++){int ret = 0;//如果一趟后ret还等于0,说明数据已经有序for (int j = 0; j < n - i - 1; j++){if (a[j] > a[j + 1]){Swap(&a[j], &a[j + 1]);ret = 1;}}if (ret == 0)break;}
}

5、堆排序

时间复杂度:O(N*logN) 空间复杂度:O(1)
建堆的时候可以采用向上调整和向下调整建堆,而排序的时候只能使用向下调整算法。
排升序建大堆,降序建小堆。

void Adjustup(int* a, int child)//向上调整
{int parent = (child - 1) / 2;while (parent >= 0){if (a[child] > a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void Adjustdown(int* a, int parent, int n)//向下调整
{int child = 2 * parent + 1;while (child < n){if (child + 1 < n && a[child + 1] > a[child]){child++;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void HeapSort(int* arr, int sz)
{//第一步,建堆向上调整建堆//for (int i = 1; i < sz; i++)//{//	Adjustup(arr, i); //}//向下调整建堆for (int i = (sz - 1) / 2; i >= 0; i--){Adjustdown(arr, i, sz - 1);}int end = sz - 1;while (end > 0){Swap(&arr[0], &arr[end]);Adjustdown(arr, 0, end);end--;}
}

6、快速排序

时间复杂度:O(N*logN) 空间复杂度:O(1)

快速排序递归实现

霍尔法

在这里插入图片描述

int QuickSortPart1(int*a,int left,int right)//霍尔版本
{int* Maxi = (&a[left], &a[right], &(a[(left + right) / 2]));//三数取中Swap(&a[left], Maxi);//换到最左边int key = a[left];int keyi = left;while (left<right){while (left<right && a[right]>=key){right--;}while (left < right && a[left] <= key){left++;}Swap(&a[left], &a[right]);}Swap(&a[keyi], &a[left]);return left;
}
void QuickSort(int*arr, int begin, int end)
{if (begin >= end)//等于是只有一个数需要排,大于是没有数需要排{return;}int keyi = QuickSortPart1(arr, begin, end);/*int keyi = QuickSortPart2(arr, begin, end);int keyi = QuickSortPart3(arr, begin, end);*/QuickSort(arr, begin, keyi - 1);QuickSort(arr, keyi + 1, end);
}

挖坑法

在这里插入图片描述

int QuickSortPart2(int* arr, int left, int right)//挖坑法
{int* Maxi = (&arr[left], &arr[right], &(arr[(left + right) / 2]));Swap(&arr[left], Maxi);int holei = left;int hole = arr[left];while (left < right){while (left < right && arr[right] >= hole){right--;}arr[holei] = arr[right];holei = right;while (left < right && arr[left] <= hole){left++;}arr[holei] = arr[left];holei = left;}arr[holei] = hole;return left;
}
void QuickSort(int*arr, int begin, int end)
{if (begin >= end)//等于是只有一个数需要排,大于是没有数需要排{return;}/*int keyi = QuickSortPart1(arr, begin, end);*/int keyi = QuickSortPart2(arr, begin, end);/*int keyi = QuickSortPart3(arr, begin, end);*/QuickSort(arr, begin, keyi - 1);QuickSort(arr, keyi + 1, end);
}

前后指针法

在这里插入图片描述

int QuickSortPart3(int* a, int left, int right)//快排快慢指针
{int* Maxi = (&a[left], &a[right], &(a[(left + right) / 2]));Swap(&a[left], Maxi);int keyi = left;int prev = left;int cur = left+1;while (cur <= right){if (a[cur] < a[keyi]&& ++prev!= cur){Swap(&a[prev], &a[cur]);}cur++;}Swap(&a[prev],&a[keyi]);return prev;
}void QuickSort(int*arr, int begin, int end)
{if (begin >= end)//等于是只有一个数需要排,大于是没有数需要排{return;}//*int keyi = QuickSortPart1(arr, begin, end);*///int keyi = QuickSortPart2(arr, begin, end);int keyi = QuickSortPart3(arr, begin, end);QuickSort(arr, begin, keyi - 1);QuickSort(arr, keyi + 1, end);
}

快速排序小区间优化

void QuickSort1(int* a, int begin, int end)
{if (begin >= end)return;// 小区间优化,小区间不再递归分割排序,降低递归次数if ((end - begin + 1) > 10){int keyi = PartSort3(a, begin, end);// [begin, keyi-1] keyi [keyi+1, end]QuickSort1(a, begin, keyi - 1);QuickSort1(a, keyi + 1, end);}else{InsertSort(a + begin, end - begin + 1);//直接插入排序}
}

快速排序非递归实现

快排非递归要用栈来实现

void QuickSortNorn(int* a, int begin, int end)
{ST st;//创建数组栈STInit(&st);//初始化栈STPush(&st, end);//入栈STPush(&st, begin);//入栈while (!STEmpty(&st))//判空{int left = STTop(&st);//取栈顶数据STPop(&st);//出栈int right = STTop(&st);STPop(&st);int keyi = QuickSortPart1(a, left,right);if (keyi + 1 < right){STPush(&st, right);STPush(&st, keyi + 1);}if (keyi - 1 > left){STPush(&st, keyi - 1);STPush(&st, left);}}STDestroy(&st);//销毁栈
}

7、归并排序

时间复杂度:O(N*logN) 空间复杂度:O(N)

归并排序递归实现

在这里插入图片描述

void _MergeSortPart(int* a, int* tmp, int begin, int end)
{if (begin >= end)return;int midi = (begin + end) / 2;_MergeSortPart(a, tmp, begin, midi);_MergeSortPart(a, tmp, midi + 1, end);int begin1 = begin, end1 = midi;int begin2 = midi + 1, end2 = end;int index = begin;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}memcpy(a+begin, tmp+begin, sizeof(int) * (end - begin + 1));
}
void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);_MergeSortPart(a, tmp, 0, n - 1);free(tmp);tmp = NULL;
}

归并排序非递归

void _MergeSortNonr(int* a, int* tmp, int begin, int end)
{int gap = 1;while (gap <= end){for (int i = 0; i <= end; i += 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;int index = i;if (begin2 > end){break;}if (end2 > end){end2 = end;//对范围进行修正}while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2]){tmp[index++] = a[begin1++];}else{tmp[index++] = a[begin2++];}}while (begin1 <= end1){tmp[index++] = a[begin1++];}while (begin2 <= end2){tmp[index++] = a[begin2++];}memcpy(a + i, tmp + i, sizeof(int) * (end2-i+1));//拷贝回原数组}gap *= 2;}}
void MergeSortNonr(int* a, int n)//归并排序非递归
{int* tmp = (int*)malloc(sizeof(int) * n);_MergeSortNonr(a, tmp, 0, n - 1);free(tmp);tmp = NULL;
}

8、计数排序

时间复杂度:O(MAX(N,range)) 空间复杂度:O(range)

void CountSort(int* a, int n)//计数排序
{//先找最大值和最小值int maxi = 0, mini = 0;for (int i = 1; i < n; i++){if (a[i] > a[maxi]){maxi = i;}if (a[i] < a[mini]){mini = i;}}int max = a[maxi], min = a[mini];int range = a[maxi] - a[mini]+1;int* count = (int*)malloc(sizeof(int) * range);memset(count, 0, sizeof(int) * range);for (int j = 0; j < n; j++){count[a[j] - min]++;}int i = 0;for (int j = 0; j < n; j++){while (count[j]--){ a[i++] = j + min;}}
}

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

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

相关文章

GPT系列论文解读:GPT-2

GPT系列 GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一系列基于Transformer架构的预训练语言模型&#xff0c;由OpenAI开发。以下是GPT系列的主要模型&#xff1a; GPT&#xff1a;GPT-1是于2018年发布的第一个版本&#xff0c;它使用了12个Transformer…

VUE3照本宣科——认识VUE3

VUE3照本宣科——认识VUE3 前言一、命令创建项目1.中文官网2.菜鸟教程 二、VUE3项目目录结构1.public2.src&#xff08;1&#xff09;assets&#xff08;2&#xff09;components 3. .eslintrc.cjs4. .gitignore5. .prettierrc.json6.index.html7.package.json8.README.md9.vit…

进程调度算法之时间片轮转调度(RR),优先级调度以及多级反馈队列调度

1.时间片轮转调度算法(RR) round Robin 1.算法思想 公平地、轮流地为各个进程服务&#xff0c;让每个进程在一定时间间隔内都可以得到响应。 2.算法规则 按照各进程到达就绪队列的顺序&#xff0c;轮流让各个进程执行一个时间片&#xff08;如100ms&#xff09;。 若进程未…

Linux 文件上传、下载

1、通过FinalShell工具虚拟机进行数据交换 在FinalShell软件的下方窗体中&#xff0c;提供了Linux的文件系统视图&#xff0c;可以方便的&#xff1a; 浏览文件系统&#xff0c;找到合适的文件&#xff0c;右键点击下载&#xff0c;即可传输到本地电脑 浏览文件系统&#xff0…

数值分析学习笔记——绪论【华科B站教程版本】

绪论 数值分析概念 用计算机求解数学问题的数值方法和理论 三大科学研究方法 实验理论分析科学计算&#xff08;用计算机去辅助研究&#xff09;&#xff1a;数值方法计算机 解析解和近似解 解析解&#xff1a;使用数学方法求出或推导出的结果&#xff0c;往往可以求解出…

【STL】list常见用法及模拟实现(附完整源码)

目录 前言1. list介绍及使用1.1 list介绍1.2 list使用 2. list模拟实现2.1 迭代器功能分类2.2 list迭代器模拟实现2.2.1 普通迭代器2.2.2 const迭代器 3. list和vector区别4. 源码 前言 这篇文章我们继续STL中容器的学习&#xff0c;这篇文章要讲解的是list。 1. list介绍及使用…

软件工程与计算总结(三)示例项目描述

本节介绍一个标准的项目描述&#xff0c;大家可以作为蓝本学习~ 目录 一.背景 二.目标 三.系统用户 四.用户访谈要点 1.收银员 2.客户经理 3.总经理 4.系统管理员 五.项目实践过程 一.背景 A是一家刚刚发展起来的小型连锁商店&#xff0c;其前身是一家独立的小百货门面…

SDL2绘制ffmpeg解析的mp4文件

文章目录 1.FFMPEG利用命令行将mp4转yuv4202.ffmpeg将mp4解析为yuv数据2.1 核心api: 3.SDL2进行yuv绘制到屏幕3.1 核心api 4.完整代码5.效果展示6.SDL2事件响应补充6.1 处理方式-016.2 处理方式-02 本项目采用生产者消费者模型&#xff0c;生产者线程&#xff1a;使用ffmpeg将m…

Python 无废话-基础知识流程控制语句

If 流程控制语句 最常见的控制流语句是if 语句。在自然语言中&#xff0c;if 语句念起来可能是&#xff1a;“如果条件为真&#xff0c;执行子句中的代码。”在Python中的条件语句用于根据特定条件执行不同的代码块条件。 用代码描述如下&#xff1a; cost 60000 if cost &…

代码随想录Day12 二叉树 LeetCode T102二叉树的层序遍历 T226 翻转二叉树 T101 对称二叉树

本文思路和详细讲解来自于:代码随想录 (programmercarl.com) LeetCode T102 二叉树的层序遍历 题目链接:102. 二叉树的层序遍历 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 本题使用队列辅助完成,讲解主要函数CheckOrder:首先判断root是否为空,是就直接返回,然后创建…

Linux下的基本指令

目录 一、基本指令 1.1 ls指令 1.2 pwd指令 1.3 cd指令 1.4 touch指令 1.5 mkdir指令&#xff08;重要&#xff09; 1.6 rmdir指令 && rm 指令&#xff08;重要&#xff09; 1.7 man指令&#xff08;重要&#xff09; 1.8 cp指令&#xff08;重要&#xff09;…

安卓教材学习

文章目录 教材学习第一行代码 Android 第3版环境配置gradle配置下载包出现问题 教材学习 摘要&#xff1a;选了几本教材《第一行代码 Android 第3版》&#xff0c;记录一下跑案例遇到的问题&#xff0c;和总结一些内容。 第一行代码 Android 第3版 环境配置 gradle配置 gradl…

了解基于Elasticsearch 的站内搜索,及其替代方案

对于一家公司而言&#xff0c;数据量越来越多&#xff0c;如果快速去查找这些信息是一个很难的问题&#xff0c;在计算机领域有一个专门的领域IR&#xff08;Information Retrival&#xff09;研究如何获取信息&#xff0c;做信息检索。在国内的如百度这样的搜索引擎也属于这个…

gitgitHub

在git中复制CtrlInsert、粘贴CtrlShif 一、用户名和邮箱的配置 查看用户名 &#xff1a;git config user.name 查看密码&#xff1a; git config user.password 查看邮箱&#xff1a;git config user.email 查看配置信息&#xff1a; $ git config --list 修改用户名 git co…

Android 开发错误集合

&#x1f525; 开发错误集合一 &#x1f525; Caused by: java.lang.ClassNotFoundException: Didnt find class "com.mask.app.ui.LoginRegisterActivity" on path: DexPathList[[zip file "/data/app/~~NMvHVhj8V6-HwGbh2amXDA/com.mask.app-PWbg4xIlETQ3eVY…

全志ARM926 Melis2.0系统的开发指引⑦

全志ARM926 Melis2.0系统的开发指引⑦ 编写目的11. 调屏11.1. 调屏步骤简介11.1.1. 判断屏接口。11.1.2. 确定硬件连接。11.1.3. 配置显示部分 sys_config.fex11.1.3.1. 配置屏相关 IO 11.1.4. Lcd_panel_cfg.c 初始化文件中配置屏参数11.1.4.1. LCD_cfg_panel_info11.1.4.2. L…

存在负权边的单源最短路径的原理和C++实现

负权图 此图用朴素迪氏或堆优化迪氏都会出错&#xff0c;floyd可以处理。 负环图 但floyd无法处理负权环&#xff0c;最短距离是无穷小。在环上不断循环。 经过k条边的最短距离&#xff08;可能有负权变&#xff09; 贝尔曼福特算法(bellman_ford)就是解决此问题的。 原理 …

(详解)Linux常见基本指令(1)

目录 目录&#xff1a; 1:有关路径文件下的操作(查看&#xff0c;进入) 1.1 ls 1.2 pwd 1.3 cd 2:创建文件或目录 2.1 touch 2.2 mkdir 3:删除文件或目录 3.1 rm与rmdir 4:复制剪切文件 4.1 cp 4.2 mv 1:有关路径的操作 1 ls 指令 语法&#xff1a;ls [选项] [目录或文…

DevicData-D-XXXXXXXX勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

引言&#xff1a; 在数字时代&#xff0c;数据安全成为一项至关重要的挑战。DevicData-D-XXXXXXXX勒索病毒&#xff08;以下简称DevicData病毒&#xff09;是这场战斗中的新敌人&#xff0c;它能够以毁灭性的方式加密您的数据&#xff0c;迫使您在数据和时间之间做出艰难的选择…

XC5013 马达驱动和充电集成一体的控制芯片 一档输出芯片

XC5013 是一款应用于马达驱动或 LED 驱动的控制芯片&#xff0c;集成了锂电池充电管理系统&#xff0c;设定一档高电平输 出&#xff0c;并带有对不同状态的 LED 指示功能。 XC5013 集成了涓流充电、恒流充电和恒压充电全过程的充电方式&#xff0c;浮充电压精度在全温度范…