数据结构从入门到精通——排序的概念及运用

排序的概念及运用

  • 前言
  • 一、排序的概念
    • 排序
    • 稳定性
    • 内部排序
    • 外部排序
  • 二、排序运用
  • 三、常见的排序算法
  • 四、排序性能检测代码
    • srand()
    • clock()
  • 五、oj排序测试代码


前言

排序是将数据按照一定规则重新排列的过程,常见规则有升序、降序等。排序算法如冒泡排序、快速排序等,广泛用于数据库、搜索引擎等场景,提高数据检索效率。此外,排序也应用于统计分析、机器学习等领域,以获取有序数据集或发现数据间的关联。

排序是一种将一组数据按照一定的规则重新排列的操作。通常,排序的目标是将数据按照某种顺序进行排列,比如按照升序或降序排列。排序算法是对数据进行排序的具体步骤和方法。

排序算法在计算机科学和数据结构中具有广泛的应用。在实际生活中,排序也随处可见。比如在图书馆中,图书按照作者姓名或图书编号进行排序,使得读者能够更方便地查找所需的图书。在金融领域,股票交易价格也需要按照时间顺序进行排序。

排序算法的选择根据数据规模和性质的不同而有所差异。常见的排序算法包括冒泡排序、插入排序、选择排序、快速排序、归并排序等。这些算法在时间复杂度和空间复杂度上有各种差异,因此在实际应用中需要根据具体情况选择适合的算法。

排序算法的效率对于处理大量数据的程序非常重要。在一些场景下,排序算法的效率甚至可以决定整个程序的性能。因此,研究和优化排序算法是计算机科学领域的重要课题之一。


一、排序的概念

排序

排序的概念,简而言之,就是对一组数据元素按照某种特定的顺序进行重新排列的过程。这种顺序可以是升序、降序,或者是根据某种特定的规则进行排序。排序算法是计算机科学中的一个重要分支,广泛应用于数据处理、搜索引擎、数据库管理等领域。

在日常生活和工作中,排序的概念也无处不在。例如,在超市购物时,商品按照价格或类别进行排序,方便顾客快速找到所需商品;在图书馆中,书籍按照书名或作者进行排序,便于读者查找;在学校的成绩管理中,学生的成绩按照分数从高到低或从低到高进行排序,方便教师进行评估和比较。

在计算机科学中,排序算法的种类繁多,各有其优缺点。常见的排序算法有冒泡排序、选择排序、插入排序、归并排序、快速排序等。冒泡排序通过相邻元素之间的比较和交换,逐步将最大的元素“冒”到序列的末尾;选择排序则通过每次选择剩余元素中的最小(或最大)元素,将其放到序列的起始位置;插入排序则是将每个元素插入到已排序的序列中的适当位置,从而保持整个序列的有序性。归并排序和快速排序则采用了分治的思想,将待排序的序列划分为若干个子序列,分别对子序列进行排序,然后将排序结果合并起来,得到最终的有序序列。

不同的排序算法在不同的应用场景下具有不同的性能表现。例如,对于小规模的数据集,冒泡排序和选择排序等简单算法可能更加适用,因为它们的时间复杂度相对较低;而对于大规模的数据集,归并排序和快速排序等高效算法则更具优势,因为它们可以在更短的时间内完成排序任务。

除了算法本身的性能外,排序的效果还受到数据特性、排序规则等多种因素的影响。例如,对于已经部分有序的数据集,插入排序等算法可能具有更好的性能表现;而对于包含大量重复元素的数据集,桶排序等算法则可能更加高效。

总之,排序的概念在日常生活和计算机科学中都具有广泛的应用。通过选择合适的排序算法和考虑各种影响因素,我们可以实现高效、准确的数据排序,为数据分析和处理提供有力支持。同时,对排序算法的研究和改进也是计算机科学领域的一个重要课题,有助于推动相关技术的发展和创新。

稳定性

假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

内部排序

数据元素全部放在内存中的排序。

内部排序是数据处理过程中的重要环节,它指的是在没有外部存储设备辅助的情况下,仅依靠计算机的内存对数据进行排序的过程。这一过程对于提高数据处理效率、优化数据结构、以及实现高效算法都至关重要。

内部排序算法的选择依赖于数据的特性,如数据量的大小、数据类型的复杂性以及排序要求的严格程度等。常见的内部排序算法有冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序等。这些算法各有优缺点,适用于不同的场景。

例如,对于数据量较小的情况,冒泡排序和插入排序等简单算法可能就足够高效;而对于大数据量的处理,快速排序、归并排序等更为复杂的算法则可能更加适合。此外,对于某些特定类型的数据,如已经部分排序的数据或具有特殊分布规律的数据,还可以采用更为高效的特定算法。

在实际应用中,内部排序算法的选择还需要考虑内存使用的效率。因为内部排序完全依赖于内存,如果算法的内存使用效率不高,即使排序速度再快,也可能因为内存占用过多而导致整体性能下降。因此,在实际应用中,我们需要根据具体情况综合考虑算法的时间复杂度和空间复杂度,选择最合适的排序算法。

总的来说,内部排序是数据处理中不可或缺的一环。了解和掌握各种内部排序算法的特点和适用场景,对于提高数据处理效率、优化数据结构、以及实现高效算法都具有重要的意义。在未来的数据处理工作中,我们需要不断学习和研究新的排序算法和技术,以适应不断变化的数据处理需求。

外部排序

数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

外部排序,指的是当待排序的数据量过大,无法一次性装入内存时,需要使用外部存储设备如磁盘等进行排序的过程。这种排序方法通常涉及数据的分块、部分排序、归并等步骤,以适应大数据量的处理需求。

在现代数据处理的场景中,外部排序的应用非常广泛。例如,在处理海量日志文件、数据库查询结果、大数据分析等任务时,由于数据量庞大,无法一次性加载到内存中进行排序,因此需要使用外部排序算法。

外部排序的一个典型算法是k路归并排序。首先,将数据分割成若干个小块,每块的大小刚好能够装入内存。然后,使用内部排序算法(如快速排序、归并排序等)对每块数据进行排序,并将排序后的数据写回磁盘。接下来,使用多路归并算法将这些已排序的数据块合并成一个有序的大文件。在归并过程中,每次从各个数据块中读取一定数量的数据到内存中,进行比较和合并,然后将合并后的数据写回磁盘。这个过程不断重复,直到所有的数据块都被合并成一个有序的文件。

外部排序不仅需要考虑排序算法的效率,还需要考虑磁盘I/O操作、内存使用等因素。为了提高排序速度,可以采用一些优化策略,如增加归并路数、使用缓冲区来减少磁盘I/O次数、利用并行计算等。

此外,随着技术的发展,外部排序算法也在不断演进。例如,利用分布式存储和计算框架(如Hadoop、Spark等)进行外部排序,可以处理更大规模的数据集,并且提高排序的并行度和效率。

总的来说,外部排序是处理大数据量排序问题的重要手段。通过合理的算法设计和优化,可以在有限的内存和磁盘空间下,实现高效、稳定的数据排序。

二、排序运用

在这里插入图片描述

在这里插入图片描述

三、常见的排序算法

在这里插入图片描述
直接插入排序

希尔排序

选择排序

堆排序

冒泡排序

快速排序

归并排序

四、排序性能检测代码

排序性能检测代码是用于评估不同排序算法性能的代码。它通常包括生成随机数据集、实现多种排序算法、计时每种算法的执行时间,并比较它们的性能。这种代码可以帮助开发者选择最适合特定应用场景的排序算法。

总结:排序性能检测代码通过生成随机数据、实现多种排序算法并比较它们的执行时间,来评估不同排序算法的性能,帮助开发者选择最佳算法。

// 排序实现的接口
 
// 插入排序
	void InsertSort(int* a, int n);
 
// 希尔排序
	void ShellSort(int* a, int n);
 
// 选择排序
	void SelectSort(int* a, int n);
 
// 堆排序
	void AdjustDwon(int* a, int n, int root);
	void HeapSort(int* a, int n);
 
// 冒泡排序
	void BubbleSort(int* a, int n)
 
// 快速排序递归实现
// 快速排序hoare版本
	int PartSort1(int* a, int left, int right);
// 快速排序挖坑法
	int PartSort2(int* a, int left, int right);
// 快速排序前后指针法
	int PartSort3(int* a, int left, int right);
	void QuickSort(int* a, int left, int right);
 
// 快速排序 非递归实现
	void QuickSortNonR(int* a, int left, int right)
 
// 归并排序递归实现
	void MergeSort(int* a, int n)
// 归并排序非递归实现
	void MergeSortNonR(int* a, int n)
 
// 计数排序
	void CountSort(int* a, int n)
 
// 测试排序的性能对比
	void TestOP()
	{
	 srand(time(0));
	 const int N = 100000;
	 int* a1 = (int*)malloc(sizeof(int)*N);
	 int* a2 = (int*)malloc(sizeof(int)*N);
	 int* a3 = (int*)malloc(sizeof(int)*N);
	 int* a4 = (int*)malloc(sizeof(int)*N);
	 int* a5 = (int*)malloc(sizeof(int)*N);
	 int* a6 = (int*)malloc(sizeof(int)*N);
	 int* a7 = (int*)malloc(sizeof(int)*N);
 
	 for (int i = 0; i < N; ++i)
	 {
	 	a1[i] = rand();
	 	a2[i] = a1[i];
	 	a3[i] = a1[i];
	 	a4[i] = a1[i];
	 	a5[i] = a1[i];
	 	a6[i] = a1[i];
	 	a7[i] = a1[i];
 	} 
	int begin1 = clock();// 插入排序
	InsertSort(a1, N);
	int end1 = clock();

	int begin7 = clock();// 冒泡排序
	BubbleSort(a7, N);
	int end7 = clock();

	int begin2 = clock();// 希尔排序
	ShellSort(a2, N);
	int end2 = clock();

	int begin3 = clock();// 选择排序
	SelectSort(a3, N);
	int end3 = clock();

	int begin4 = clock();// 堆排序
	HeapSort(a4, N);
	int end4 = clock();

	int begin5 = clock();// 快速排序前后指针法
	QuickSort(a5, 0, N - 1);
	int end5 = clock();

	int begin6 = clock();// 归并排序递归实现
	MergeSort(a6, N);
	int end6 = clock();

	printf("InsertSort:%d\n", end1 - begin1);
	printf("BubbleSort:%d\n", end7 - begin7);

	printf("ShellSort:%d\n", end2 - begin2);
	printf("SelectSort:%d\n", end3 - begin3);
	printf("HeapSort:%d\n", end4 - begin4);
	printf("QuickSort:%d\n", end5 - begin5);
	printf("MergeSort:%d\n", end6 - begin6);

	free(a1);
	free(a2);
	free(a3);
	free(a4);
	free(a5);
	free(a6);
	free(a7);
	}

下面是对该代码的详细解释:

函数定义:void TestOP() 是一个函数,它没有返回值(void)并且不接受任何参数。

  1. 初始化随机数生成器:
    srand(time(0));:使用当前时间作为种子初始化随机数生成器。这样每次运行程序时,生成的随机数序列都会不同。

  2. 内存分配:
    代码为7个整数数组(a1 到 a7)分配了内存,每个数组都有 N(100,000)个整数。这些数组用于存储要排序的数据。

  3. 填充数组:
    在一个for循环中,所有数组(除了 a7)都被填充了随机数。a7 数组没有被正确初始化,这是一个错误。

  4. 排序和计时:
    代码使用 clock() 函数来测量每种排序算法的执行时间。clock() 函数返回程序执行的时钟周期数。

每种排序算法(插入排序、冒泡排序、希尔排序、选择排序、堆排序、快速排序和归并排序)都被调用一次,并计算其执行时间。

  1. 输出结果:
    使用 printf 函数输出每种排序算法的执行时间。

  2. 释放内存:
    使用 free() 函数释放之前为数组分配的内存。

注意
由于所有数组(除了 a7)都使用了相同的随机数序列进行初始化,因此这些排序算法的比较是公平的。

clock() 函数的结果可能受到多种因素的影响,包括CPU速度、负载和其他正在运行的程序。因此,这些结果只能作为大致的性能比较,而不是精确的性能指标。

srand()

srand()是C语言中的一个函数,用于设置随机数生成器的种子。它的原型是:

void srand(unsigned int seed);

其中,seed是一个整数作为种子。通过设置种子,srand()函数可以改变随机数序列的起点。每次调用srand()函数,生成的随机数序列将会根据种子重新开始。

一般情况下,我们可以使用系统时间作为种子,以使生成的随机数序列每次都不一样,例如:

srand(time(NULL));

在调用srand()函数之后,我们可以使用rand()函数来生成随机数。每次调用rand()函数,都会返回一个伪随机数,这个数的取值范围通常是0RAND_MAX。需要注意的是,生成的随机数是伪随机数,其实质是通过算法计算得到的,并非真正意义上的随机数。

总结来说,srand()函数用于设置随机数生成器的种子,以改变随机数序列的起点;而rand()函数用于生成伪随机数序列。

clock()

clock() 函数是C和C++中的一个标准库函数,用于返回程序运行的CPU时间。它的原型如下所示:

#include <time.h>

clock_t clock(void);

clock() 函数返回一个 clock_t 类型的值,表示自程序开始执行以来所经过的时钟周期数。时钟周期的长度取决于系统和编译器的实现。

需要注意的是,clock() 函数返回的是CPU时间,而不是实际的墙钟时间(即现实世界中的时间)。CPU时间是指程序运行所消耗的CPU时间,包括程序执行和系统调用等。因此,如果程序在多个CPU核心上运行,clock() 函数返回的值可能会大于墙钟时间。

使用 clock() 函数可以用来测量程序的执行时间,例如用于性能分析和优化。可以通过在程序的开始和结束处调用 clock() 函数并计算差值来获得程序的CPU时间消耗。

需要注意的是,clock() 函数返回的值是一个CPU时间计数器的累积值,因此不能直接用于表示程序执行的实际时间。如果需要测量实际时间,可以使用其他函数和方法,如 time() 函数和 chrono 库中的类。

五、oj排序测试代码

排序OJ(可使用各种排序跑这个OJ)


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript中的继承方式详细解析

什么是继承 继承是面向对象编程中的一个重要概念&#xff0c;它指的是一个对象&#xff08;或类&#xff09;可以获得另一个对象&#xff08;或类&#xff09;的属性和方法。在继承中&#xff0c;被继承的对象通常称为父类&#xff08;或基类、超类&#xff09;&#xff0c;继…

C++关键字:static

文章目录 一、static的四大用法1.静态局部变量2.静态全局变量3.静态函数4.类中的 静态成员变量、静态成员函数 一、static的四大用法 1.静态局部变量 延长局部变量的生命周期。 1.与普通的局部变量不同&#xff0c;局部静态变量在函数调用结束之后&#xff0c;不会被销毁&am…

中国银联订单支付产品实施指南(2022.A 版)

为落实总行提出以银行账户为基础&#xff0c;全面提升对小微企业、民营企业的支付结算服务能力和水平的总体思路要求&#xff0c;践行支付为民&#xff0c;银联提出建设订单支付产品&#xff0c;通过深度融合企业线上线下支付场景&#xff0c;充分赋能商业银行B2B业务支付结算&…

数据结构奇妙旅程之红黑树

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

“团团活力圈”--“书香润童心 阅读伴成长”青少年读书分享活动

书籍是人类进步的阶梯&#xff0c;读书能够陶冶人的情操、开阔眼界&#xff0c;同时&#xff0c;通过读书&#xff0c;能够帮助人们增长知识&#xff0c;培养正确的人生观、价值观。为了帮助青少年多读书&#xff0c;感受读书的乐趣&#xff0c;3月17日&#xff0c;在共青团中央…

【代码】YOLOv8标注信息验证

此代码的功能是标注信息验证&#xff0c;将原图和YOLOv8标注文件&#xff08;txt&#xff09;放在同一个文件夹中&#xff0c;作为输入文件夹 程序将标注的信息还原到原图中&#xff0c;并将原图和标注后的图像一同保存&#xff0c;以便查看 两个draw_labels函数&#xff0c;分…

Ubuntu Desktop - Desktop

Ubuntu Desktop - Desktop 1. Amazon2. Ubuntu Software3. Desktop4. 系统桌面快捷方式5. 用户桌面快捷方式References 1. Amazon Amazon -> Unlock from Launcher 2. Ubuntu Software Installed -> Games -> Remove 3. Desktop /home/strong/Desktop 4. 系统桌面…

Java项目:65 ssm社区文化宣传网站+jsp

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本选题则旨在通过标签分类管理等方式&#xff0c; 实现管理员&#xff1b;个人中心、用户管理、社区新闻管理、社区公告管理、社区活动管理、…

React——开发者工具

浏览器插件&#xff1a;谷歌浏览器插件react-devtools 方式1&#xff1a;chrome应用商店添加 方式2&#xff1a;下载安装包放在浏览器上

32串口学习

基于之前的GPIO等工程&#xff0c;后面的上手难度就简单多了&#xff0c;主要是相关寄存器的设置。 void USART1_Config(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;/* config USART1 clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph…

可视化图表:雷达图的全面介绍,一篇就够了。

一、什么是雷达图 雷达图&#xff08;Radar Chart&#xff09;是一种可视化图表&#xff0c;也被称为蛛网图、星形图或极坐标图。它以一个中心点为起点&#xff0c;从中心点向外延伸出多条射线&#xff0c;每条射线代表一个特定的变量或指标。每条射线上的点或线段表示该变量在…

Linux常用命令之搜索查找类

1.1find查找文件或目录 1&#xff09;基本语法 find [搜索范围] [ 选项] find -name&#xff1a;按照名字查找 find -user&#xff1a;按用户相关查找 find -size&#xff1a;按照文件大小查找 1.2locate快速定位文件路径 经验技巧&#xff1a;由于locate指令基于数据库进行…

Ubuntu上搭建TFTP服务

Ubuntu上搭建TFTP服务 TFTP服务简介搭建TFTP服务安装TFTP服务修改配置文件 重启服务 TFTP服务简介 TFTP是一个基于UDP协议实现的用于在客户机和服务器之间进行简单文件传输的协议&#xff0c;适用于开销不大、不复杂的应用场合。TFTP协议专门为小文件传输而设计&#xff0c;只…

信息学奥赛之C++ cstdlib – 概览

什么是 C cstdlib&#xff1f; C 标准库头文件 (cstdlib in C) 是 C 程序员使用最广泛的库头文件。即&#xff1a;standard librarian。它定义了一系列函数和宏&#xff0c;以实现跨团队、跨平台的高效且具有卓越表现的标准化 C 代码。 C 是一种广受欢迎的程序语言&#xff0c…

总结

文章目录 1. GateWay&#xff1a;100102. Docker3. ES&#xff1a;海量数据的存储、搜索、计算3.1 数据搜索3.2 数据同步 4. 微服务保护&#xff1a;Sentinel4. 分布式事务&#xff1a;&#xff08;二阶段提交&#xff09;5. Redis6. 多级缓存 1. GateWay&#xff1a;10010 2. …

【工具】Mermaid + 大模型画流程图

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 引入使用画TCP三次握手了解历史人物 总结 引入 最近看面试文章关于TCP三次握手和…

【数据结构】链表力扣刷题详解

前言 题目链接 移除链表元素 链表的中间结点 反转链表 分割链表 环形链表的约瑟夫问题 ​ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 移除链表元素 题述 给你一个链表的头节点 head 和一个整数 val &#xff0c;请…

基于python的在线学习与推荐系统

技术&#xff1a;pythonmysqlvue 一、系统背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。这样的大…

大模型知识库

一种利用 langchain 思想实现的基于本地知识库的问答应用&#xff0c;目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。 1. 下载Langchain-chatchat git clone https://github.com/chatchat-space/Langchain-Chatchat/ 2. 下载大模型和embe…

从零开始学习在VUE3中使用canvas(一):实现一个基础的canvas画布

一、步骤 1.写一个canvas元素 2.获取虚拟dom 3.获取绘制环境 4.绘制想要的效果 5.在挂载后执行 二、代码 <template><div class"canvasPage"><!-- 写一个canvas标签 --><canvas class"main" ref"main"></canv…