C语言数据结构(排序算法总结)

目录

算法类型

算法比较

稳定性描述

插入排序

选择排序

冒泡排序

希尔排序

堆排序

快速排序

霍尔排序(递归)

挖坑法(递归)

双指针(递归)

快排(非递归)

归并排序

计数排序

总结(速度比较)


算法类型

插入排序,选择排序,冒泡排序,希尔排序,堆排序,快速排序(递归霍尔,挖坑,双指针,非递归),归并排序(递归,非递归),计数排序

算法比较

稳定性描述

数组相同大小元素顺序是否发生变化

插入排序

// 插入排序
void InsertSort(int* a, int n) {int i,tmp,j;for (i = 0; i < n - 1; i++) {tmp = a[i + 1];for (j = i; j >= 0; j--) {if (a[j] > tmp)a[j + 1] = a[j];elsebreak;}a[j + 1] = tmp;}
}

特性:

越有序越快,算法稳定

时间复杂度:

O(N^2)

空间复杂度:

O(1)

选择排序

// 选择排序
void SelectSort(int* a, int n) {int i, j, max, min,mid=n/2;for (i = 0; i < mid; i++) {max = min = i;for (j = i; j < n - i; j++) {if (a[j] > a[max])max = j;if (a[j] < a[min])min = j;}swap(&a[i], &a[min]);if (max == i)max = min;swap(&a[n - i - 1], &a[max]);}
}

特性:

效率比较稳定,算法不稳定(看自己写的算法取值)

时间复杂度:

O(N^2)

空间复杂度:

O(1)

冒泡排序

// 冒泡排序
void BubbleSort(int* a, int n) {int i, j;for (i = 0; i < n - 1; i++) {for (j = 0; j < n - i - 1; j++) {if (a[j] > a[j + 1])swap(&a[j], &a[j + 1]);}}
}

特性:

算法稳定,效率一般,有教学意义

时间复杂度:
O(N^2)

空间复杂度:

O(1)

希尔排序

void ShellSort(int* a, int n) {int i, j, gap=n, tmp,k;while (gap > 1) {gap = gap / 3 + 1;for (i = 0; i < gap; i++) {for (k = i; k < n - gap; k += gap) {tmp = a[k + gap];for (j = k; j >= 0; j -= gap) {if (a[j] > tmp)a[j + gap] = a[j];elsebreak;}a[j + gap] = tmp;}}}
}

特性:

算法非常不稳定,无法预测

是插入排序的升级版,针对无序情况

时间复杂度:
O(N^1.3)

空间复杂度:

O(1)

堆排序

// 堆排序
void AdjustDown(int* a, int n, int root) {//大堆int parent=root,child=parent*2+1;while (child < n) {if (child + 1 < n && a[child + 1] > a[child])child++;if (a[child] > a[parent])swap(&a[child], &a[parent]);elsebreak;parent = child;child = child * 2 + 1;}
}
void HeapSort(int* a, int n) {int i;for (i = (n - 1 - 1) / 2; i >= 0; i--)AdjustDown(a, n, i);for (i = n - 1; i > 0; i--) {swap(&a[i], &a[0]);AdjustDown(a, i, 0);}
}

特性:

排序时间比较稳定,算法不稳定

时间复杂度:

向上整理成堆:O(NlogN)

向下整理成堆堆:O(N)

堆排序:O(NlogN)

空间复杂度:

O(1)

快速排序

特性:

算法不稳定,越有序越慢

时间复杂度:

O(NlogN)

空间复杂度:

O(1)

优化:

越有序越慢,我们可以找到一个值不是最大也不是最小,与首元素进行交换提升效率

在元素个数比较少时使用插入排序

霍尔排序(递归)

// 快速排序递归实现
// 快速排序hoare版本
void PartSort1(int* a, int left, int right) {if (left >= right)return;int begin = left, end = right,key=left;while (begin < end) {while (begin<end&&a[end] >= a[key])end--;while (begin<end&&a[begin] <= a[key])begin++;swap(&a[begin], &a[end]);}swap(&a[key], &a[end]);key = begin;PartSort1(a, left, key - 1);PartSort1(a, key + 1, right);
}

挖坑法(递归)

// 快速排序挖坑法
void PartSort2(int* a, int left, int right) {if (left >= right)return;int begin = left, end = right, tmp = a[left];while (begin < end) {while (begin<end&&a[end] >= tmp)end--;a[begin] = a[end];tmp = a[end];while (begin<end&&a[begin] <= tmp)begin++;a[end] = a[begin];tmp = a[end];}a[end] = tmp;PartSort2(a, left, begin - 1);PartSort2(a, end + 1, right);
}

双指针(递归)

void QuickSort(int* a, int left, int right) {if (left >= right)return;int cur = left + 1, pre = left;while (cur <= right) {if (a[cur] < a[left] && ++pre < cur)swap(&a[cur], &a[pre]);cur++;}swap(&a[left], &a[pre]);QuickSort(a, pre + 1, right);QuickSort(a, left, pre - 1);
}

快排(非递归)

选择一种快排方法,返回修正位置key

int PartSort3(int* a, int left, int right) {if (left >= right)return -1;int cur = left + 1, pre = left;while (cur <= right) {if (a[cur] < a[left] && ++pre < cur)swap(&a[cur], &a[pre]);cur++;}swap(&a[left], &a[pre]);return pre;
}
// 快速排序 非递归实现
void QuickSortNonR(int* a, int left, int right) {Stack stack;StackInit(&stack);StackPush(&stack, right);StackPush(&stack, left);while (!StackEmpty(&stack)) {int begin = StackTop(&stack);StackPop(&stack);int end = StackTop(&stack);StackPop(&stack);int key = PartSort3(a, begin, end);if (key - 1 > begin) {StackPush(&stack, key-1);StackPush(&stack, begin);}if (key + 1 < end) {StackPush(&stack, end);StackPush(&stack, key+1);}}
}

归并排序

特性:

稳定,时间复杂度也稳定

时间复杂度:

O(NlogN)

空间复杂度:

O(N)

递归

void _merge(int* a, int* tmp, int left, int right) {if (left >= right)return;int mid = (left + right) / 2;_merge(a, tmp,left, mid);_merge(a, tmp, mid + 1, right);int begin1 = left, begin2 = mid + 1,i=left;while (begin1 <= mid && begin2 <= right) {if (a[begin1] > a[begin2])tmp[i++] = a[begin2++];elsetmp[i++] = a[begin1++];}while(begin1 <= mid)tmp[i++] = a[begin1++];while (begin2 <= right)tmp[i++] = a[begin2++];memcpy(a + left, tmp + left, sizeof(int) * (right - left + 1));
}
// 归并排序递归实现
void MergeSort(int* a, int n) {int* tmp = (int*)malloc(sizeof(int) * n);_merge(a, tmp, 0, n - 1);free(tmp);tmp = NULL;
}

非递归

// 归并排序非递归实现
void MergeSortNonR(int* a, int n) {int gap = 1,i,begin,*tmp=(int*)malloc(sizeof(int)*n);while (gap < n) {for (begin = 0; begin < n - gap; begin+=2*gap) {int begin1 = begin,end1=begin+gap-1,begin2=begin+gap,end2=begin2+gap-1;if (begin2 >= n)break;if (end2 >= n)end2 = n - 1;i = begin;while (begin1 <= end1 && begin2 <= end2) {if (a[begin1] < a[begin2])tmp[i++] = a[begin1++];elsetmp[i++] = a[begin2++];}while (begin1 <= end1)tmp[i++] = a[begin1++];while (begin2 <= end2)tmp[i++] = a[begin2++];}memcpy(a, tmp, sizeof(int) * n);gap *= 2;}
}

计数排序

// 计数排序
void CountSort(int* a, int n) {int max, min, i,j=0;max = min = a[0];for (i = 1; i < n; i++) {if (a[i] > max)max = a[i];if (a[i] < min)min = a[i];}int* arr = (int*)calloc(max - min + 1, sizeof(int));for (i = 0; i < n; i++)arr[a[i] - min]++;for (i = 0; i < max - min + 1; i++) {while (arr[i]--)a[j++] = min+i;}
}

特性:

空间复杂度仅与最大最小数有关,只可用于排列数

数越均衡越快

时间复杂度:

O(N)//均衡的话

总结(速度比较)

先比较插入,选择,冒泡排序,放置1w个随机数

比较剩下几个排序,每个放入1000w个数

由于伪随机数非常均衡,因此相对来说计数排序效率相对来说非常高

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

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

相关文章

Android Lottie 体积优化实践:从 6.4 MB 降到 530 KB

一、说明 产品提出需求&#xff1a;用户有 8 个等级&#xff0c;每个等级对应一个奖牌动画。 按照常用的实现方式&#xff1a; 设计提供 8 个 lottie 动画&#xff08;8 个 json 文件&#xff09;。研发将 json 文件打包进入 APK 中。根据不同等级播放指定的动画。 每一个 …

大模型训练学习笔记

目录 大模型的结构主要分为三种 大模型分布式训练方法主要包括以下几种&#xff1a; token Token是构成句子的基本单元 1. 词级别的分词 2. 字符级别的分词 结巴分词 GPT-3/4训练流程 更细致的教程&#xff0c;含公式推理 大模型的结构主要分为三种 Encoder-only(自编…

Unity ShaderGraph 扭曲

需要注意的是&#xff1a; HDRP ShaderGraph中 你不能扭曲UI&#xff0c;所以假如你要扭曲视频&#xff0c;请把视频在材质上渲染 播放&#xff0c;这样就可以扭曲视频了喔&#xff0c; ShaderGraph扭曲

Vue3 响应式 API:工具函数(一)

isRef() isRef 是一个简单的工具函数&#xff0c;它接受一个参数并返回一个布尔值&#xff0c;指示该参数是否是一个由 ref 创建的响应式引用。 在某些情况下&#xff0c;你可能需要编写一些通用逻辑或函数&#xff0c;这些逻辑或函数需要处理不同类型的响应式数据&#xff08…

C++STL---stack queue模拟实现

前言 对于这两个容器适配器的模拟实现非常简单&#xff0c;因为stack和queue只是对其他容器的接口进行了包装&#xff0c;在STL中&#xff0c;若我们不指明用哪种容器作为底层实现&#xff0c;栈和队列都默认是又deque作为底层实现的。 也就是说&#xff0c;stack和queue不管是…

React@16.x(22)HOOK,useState 的原理

目录 1&#xff0c;介绍2&#xff0c;useState2.1&#xff0c;使用2.2&#xff0c;原理2.3&#xff0c;注意点 1&#xff0c;介绍 1&#xff0c;出现时间点&#xff1a;在 React16.8.0 出现。 2&#xff0c;目的&#xff1a;为了增强函数组件的功能&#xff0c;用于替代类组件…

数据挖掘实战-基于Catboost算法的艾滋病数据可视化与建模分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

C++中的sizeof和strlen详解

在C中&#xff0c;sizeof和strlen都是用于获取长度或大小的运算符/函数&#xff0c;但它们的用途和工作方式有所不同。以下是对它们的详细解释&#xff1a; sizeof 运算符 sizeof 是一个编译时运算符&#xff0c;用于计算数据类型或对象的大小&#xff08;以字节为单位&#…

FANUC机器人SRVO-348 DCS MCC关闭报警处理方法总结

FANUC机器人SRVO-348 DCS MCC关闭报警处理方法总结 如下图所示,由于操作人员在操机时误打开了安全门,导致机器人紧急制动停止,示教器上显示: SRV0-348 DCS MCC关闭报警0,1, 如下图所示,查看手册中关于SRVO-348报警的具体内容: 原因分析:给机器人主电源上电的接触器在紧…

PLS_INTEGER:Oracle PL/SQL中的整数类型深度解析

PLS_INTEGER&#xff1a;Oracle PL/SQL中的整数类型深度解析 一、概述二、PLS_INTEGER简介三、PLS_INTEGER的优点四、PLS_INTEGER的简单示例示例1&#xff1a;声明并使用PLS_INTEGER变量示例2&#xff1a;在存储过程中使用PLS_INTEGER 五、资深应用的代码示例示例3&#xff1a;…

《机器学习特征提取》

书籍&#xff1a;Building Feature Extraction with Machine Learning: Geospatial Applications 作者&#xff1a;Bharath.H. Aithal&#xff0c;Prakash P.S. 出版&#xff1a;CRC Press 书籍下载-《机器学习特征提取》这是一本面向专业人士和研究生的实用指南&#xff0c…

SSM框架整合,内嵌Tomcat。基于注解的方式集成

介绍&#xff1a; SSM相信大家都不陌生&#xff0c;在spring boot出现之前&#xff0c;SSM一直是Java在web开发中的老大哥。现在虽说有了spring boot能自动整合第三方框架了&#xff0c;但是现在市面上任然有很多老项目是基于SSM技术的。因此&#xff0c;能熟练掌握SSM进行开发…

DALL-E2详解

标题&#xff1a; DALL-E2详解 摘要&#xff1a; 本文将详细介绍DALL-E2&#xff0c;OpenAI最新推出的人工智能图像生成模型。DALL-E2在图像生成领域取得了显著进展&#xff0c;它不仅能够生成逼真的图像&#xff0c;还能根据文本描述创造出新颖且具有创意的视觉内容。本文将探…

队列的讲解与实现

这里写目录标题 一、队列的概念及结构二、队列的实现(使用VS2022的C语言)1.初始化、销毁2.入队、出队3.返回队头元素、返回队尾元素、判空、返回有效元素个数 三、完整 Queue.c 源代码 一、队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端…

【Linux】进程(8):Linux真正是如何调度的

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解Linux进程&#xff08;8&#xff09;&#xff1a;Linux真正是如何调度的&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 之前我们讲过&#xff0c;在大…

conda虚拟环境如何卸载pip

要在conda虚拟环境中卸载pip&#xff0c;你可以使用conda命令来移除它。以下是具体步骤&#xff1a; 激活你想要移除pip的conda虚拟环境。 使用conda命令移除pip。 下面是具体的命令&#xff1a; bash conda activate your_env_name # 替换your_env_name为你的环境名称 cond…

代码随想录算法训练营第四十九天 | 139.单词拆分、多重背包、背包问题总结

139.单词拆分 视频讲解&#xff1a; 动态规划之完全背包&#xff0c;你的背包如何装满&#xff1f;| LeetCode&#xff1a;139.单词拆分_哔哩哔哩_bilibili 代码随想录 解题思路 1.dp[i] 字符串的长度为i&#xff0c;dp[i]是否可以被组成 2.递推公式 if( [j,i] && d…

硬件IIC和软件IIC的比较

&#xff08;一&#xff09;硬件IIC 硬件IIC是由STM32内部的硬件模块实现的&#xff0c;使用CPU的时钟信号来控制数据传输和时序&#xff0c;通信速度较快&#xff0c;可以达到几十MHz的速度。硬件IIC的实现相对简单&#xff0c;无需编写复杂的代码&#xff0c;因此在实现IIC通…

如何理解与学习数学分析——第二部分——数学分析中的基本概念——第5章——序列

第2 部分&#xff1a;数学分析中的基本概念 (Concepts in Analysis) 5. 序列(Sequences) 本章介绍了序列属性&#xff0c;例如单调性、有界性和收敛性&#xff0c;使用图表和示例来解释这些属性&#xff0c;并演示如何在各种证明中使用它们的定义。讨论了趋于无穷大的序列出…

API key学习笔记

API Key 基本上可以认为是一个长字符串&#xff0c;允许 API 消费者&#xff08;即使用 API 的人&#xff09;访问受限的功能和数据。它作为一种安全措施&#xff0c;确保了 API 服务能够控制谁有权限访问什么数据&#xff0c;同时也帮助跟踪API的使用情况。生成API key来调用A…