首页 > 编程语言 >十大排序算法的特点及应用场景

十大排序算法的特点及应用场景

时间:2024-09-11 20:24:17浏览次数:13  
标签:arr 场景 int 复杂度 range len 算法 排序

一.十大经典排序算法介绍

1. 冒泡排序(Bubble Sort)

原理:通过重复遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,直到没有再需要交换的元素为止。

特点:简单但效率低,适合小数据量的排序。

2. 选择排序(Selection Sort)

原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

特点:不稳定排序,时间复杂度为O(n^2),但不需要额外的存储空间。

3. 插入排序(Insertion Sort)

原理:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

特点:适合少量数据的排序,时间复杂度为O(n^2),但在部分已排序的数据集上效率较高。

4. 希尔排序(Shell Sort)

原理:是插入排序的一种更高效的改进版本。希尔排序通过将原来要排序的数组元素按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至1时,整个文件恰被分成一组,算法终止。

特点:是第一个突破O(n^2)的排序算法,但时间复杂度依赖于增量序列的选择。

5. 归并排序(Merge Sort)

原理:采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

特点:稳定排序,时间复杂度为O(n log n),但需要额外的存储空间。

6. 快速排序(Quick Sort)

原理:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

特点:平均时间复杂度为O(n log n),但在最坏情况下(如数组已经有序)时间复杂度为O(n^2)。

7. 堆排序(Heap Sort)

原理:是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或者大于)它的父节点。

特点:不稳定排序,时间复杂度为O(n log n),不需要额外的存储空间。

8. 计数排序(Counting Sort)

原理:不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

特点:稳定排序,时间复杂度为O(n+k),其中k是整数的范围。

9. 桶排序(Bucket Sort)

原理:将数组分到有限数量的桶里。每个桶再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。

特点:平均时间复杂度为O(n+k),其中k是桶的数量。

10. 基数排序(Radix Sort)

原理:是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。

特点:稳定排序,时间复杂度为O(nk),其中n是排序元素个数,k是数字位数。

每种排序算法都有其适用的场景和优缺点,选择合适的排序算法可以大大提高程序的效率。

二.算法效率对比

三.综合效率对比建议

1.如果数据量小,用哪种排序方法都可以,效率差别不大

2.如果数据量大;内存充裕建议用快速排序,内存不充裕建议用堆排序。

四.代码示例

1.快速排序c代码

#include <stdio.h>

#include <stdlib.h>

typedef struct _Range {

int start, end;

} Range;

Range new_Range(int s, int e) {

Range r;

r.start = s;

r.end = e;

return r;

}

void swap(int* x, int* y) {

int t = *x;

*x = *y;

*y = t;

}

void quick_sort(int arr[], const int len) {

if (len <= 0)

return; // 避免len等於負值時引發段錯誤(Segment Fault)

// r[]模擬列表,p為數量,r[p++]為push,r[--p]為pop且取得元素

Range r[len];

int p = 0;

r[p++] = new_Range(0, len - 1);

while (p) {

Range range = r[--p];

if (range.start >= range.end)

continue;

int mid = arr[(range.start + range.end) / 2]; // 選取中間點為基準點

int left = range.start, right = range.end;

do {

while (arr[left] < mid) ++left;   // 檢測基準點左側是否符合要求

while (arr[right] > mid) --right; //檢測基準點右側是否符合要求

if (left <= right) {

swap(&arr[left], &arr[right]);

left++;

right--;               // 移動指針以繼續

}

} while (left <= right);

if (range.start < right) r[p++] = new_Range(range.start, right);

if (range.end > left) r[p++] = new_Range(left, range.end);

}

}

int main() {

int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };

int len = (int)sizeof(arr) / sizeof(*arr);

quick_sort(arr, len);

int i;

printf("start:\r\n");

for (i = 0; i < len; i++)

printf("%d ", arr[i]);

printf("\n");

return 0;

}

2.堆排序c代码

#include <stdio.h>

#include <stdlib.h>

void swap(int *a, int *b) {

    int temp = *b;

    *b = *a;

    *a = temp;

}

void max_heapify(int arr[], int start, int end) {

    // 建立父節點指標和子節點指標

    int dad = start;

    int son = dad * 2 + 1;

    while (son <= end) { // 若子節點指標在範圍內才做比較

        if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的

            son++;

        if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數

            return;

        else { // 否則交換父子內容再繼續子節點和孫節點比較

            swap(&arr[dad], &arr[son]);

            dad = son;

            son = dad * 2 + 1;

        }

    }

}

void heap_sort(int arr[], int len) {

    int i;

    // 初始化,i從最後一個父節點開始調整

    for (i = len / 2 - 1; i >= 0; i--)

        max_heapify(arr, i, len - 1);

    // 先將第一個元素和已排好元素前一位做交換,再重新調整,直到排序完畢

    for (i = len - 1; i > 0; i--) {

        swap(&arr[0], &arr[i]);

        max_heapify(arr, 0, i - 1);

    }

}

int main() {

    int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };

    int len = (int) sizeof(arr) / sizeof(*arr);

    heap_sort(arr, len);

    int i;

    for (i = 0; i < len; i++)

        printf("%d ", arr[i]);

    printf("\n");

    return 0;

}

参考资料:

https://www.runoob.com/w3cnote/ten-sorting-algorithm.html

标签:arr,场景,int,复杂度,range,len,算法,排序
From: https://blog.csdn.net/xieliru/article/details/142149277

相关文章

  • 如何快速构建RTMP直播推送业务场景?
    大牛直播SDK跨平台RTMP直播推送模块,始于2015年,支持Windows、Linux(x64_64架构|aarch64)、Android、iOS平台,支持采集推送摄像头、屏幕、麦克风、扬声器、编码前、编码后数据对接,功能强大,性能优异,配合大牛直播SDK的SmartPlayer播放器,轻松实现毫秒级的延迟体验,满足大多数行业的使用场景......
  • LeetCode算法—滑动窗口
    一:滑动窗口1、窗口:滑动窗口的核心就是一个窗口;通常使用两个指针表示(一个指向左边界;一个指向右边界);窗口中的元素就是当前字串2、滑动:窗口从数组或字符串的起始位置开始,逐步向右滑动。当窗口无法满足条件时,调整左边界以缩小窗口;当窗口满足条件时,尝试记录当前窗口的结果,并继续调整......
  • 基于python+flask框架的基于内容推荐算法的点餐系统(开题+程序+论文) 计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在数字化时代,随着餐饮行业的蓬勃发展,消费者对于个性化、便捷化就餐体验的需求日益增长。传统的点餐方式已难以满足顾客对菜品多样性和个性......
  • 【面试经验】京东 算法工程 广告反作弊 一面 凉经
    一面:HR面+技术面,时长大概1小时多点,HR面15-20分钟HR面:略技术面:c/c++代码片段问题:voidfun(char*p){p=(char*)malloc(100);}intmain(){char*str=NULL;fun(str);strcpy(str,"helloworld");return0;}智能指针相关,和引用的区别C......
  • 遗传与进化计算会议(Genetic and Evolutionary Computation Conference,简称GECCO)多目标
    遗传与进化计算会议(GeneticandEvolutionaryComputationConference,简称GECCO)是进化计算领域内最大的同行评审会议,也是计算机学会(ACM)遗传与进化计算特别兴趣小组(SIGEVO)的主要会议。它涵盖了遗传算法、遗传编程、蚁群优化和群体智能、复杂系统、进化组合优化和元启发式、进......
  • AdaBoost算法(AdbBoost Algorithm)—有监督学习方法、非概率模型、判别模型、非线性模型
    定义输入:训练数据集T={(x1......
  • Vue与React的Diff算法
    虚拟DOM定义虚拟DOM是一种用于在前端开发中模拟真实DOM的技术。它是一种抽象的数据结构(简单来说就是一个Javascript对象),用于描述HTML或XML文档的结构和内容。通过将页面的状态和结构保存在内存中,而不是直接操作真实的DOM,虚拟DOM能够减少不必要的DOM操作,从而提高页面性能。......
  • 基于协同过滤算法实现的同城玩乐推荐系统
    作者主页:编程千纸鹤作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与......
  • 文心一言 VS 讯飞星火 VS chatgpt (344)-- 算法导论23.2 3题
    三、对于稀疏图G=(V,E)......
  • 文心一言 VS 讯飞星火 VS chatgpt (343)-- 算法导论23.2 2题
    二、假定我们用邻接矩阵来表示图G=(V,E)......