八大排序(一)冒泡排序,选择排序,插入排序,希尔排序

news2024/9/30 21:35:06

一、冒泡排序

冒泡排序的原理是:从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。

以从小到大排序为例,第一轮比较后,所有数中最大的那个数就会浮到最右边;第二轮比较后,所有数中第二大的那个数就会浮到倒数第二个位置……就这样一轮一轮地比较,最后实现从小到大排序。

95b4e127dcdf46aeb00895cea64cfffa.gif

代码如下:

void BubbleSort(int* a, int n)
{
	for (size_t j = 0; j < n; j++)
	{
		int exchange = 0;
		for (size_t i = 1; i < n-j; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				exchange = 1;
			}
		}

		if (exchange == 0)
		{
			break;
		}
	}
}

冒泡排序时间复杂度

如果待排序序列的初始状态恰好是我们希望的排序结果(如升序或降序),一趟扫描即可完成排序。

所需的关键字比较次数C和记录移动次数M均达到最小值:

                                       e38b2c98c7fc40dc8f65c5d45cace00b.png

冒泡排序最好的时间复杂度为O(n)。

如果待排序序列是反序(如我们希望的结果是升序,待排序序列是降序)的,需要进行n-1趟排序。每趟排序要进行n-i次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:

                                    0293cfb6ce314486889177adc2ce3045.png  

冒泡排序的最坏时间复杂度为O(N^2)
综上,因此冒泡排序总的平均时间复杂度为O(N^2)

冒泡排序是稳定的排序

 

二、选择排序

选择排序的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,继续放在起始位置知道未排序元素个数为0。

选择排序的步骤:

1>首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

2>再从剩余未排序元素中继续寻找最小(大)元素,然后放到未排序序列的起始位置。

3>重复第二步,直到所有元素均排序完毕。

20210808223821944.gif

选择排序代码实现:

//交换两个数据
void Swap(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

//选择排序
void SelectSort(int* arr, int size)
{
	int i = 0;
    for (i = 0; i < size-1; i++)
    {
        int min = i;
        int j = 0;
        for (j = i+1; j < size; j++)
        {
            if (arr[j] < arr[min])
            {
                min = j;
            }
        }
        Swap(&arr[i], &arr[min]);
    }
}

思路优化:

以上算法是每次找出最小的放在指定位置,一共要找n-1次,如果我们每次不但找到最小的,还找到最大的,将最小的与左端交换,最大的与右端交换,那么就少了一半的遍历次数,从而提高效率。

  1. 变量begin和变量end是数组的两端,minmax分别找小和大的下标
  2. 先交换minbegin位置的数值,再交换maxend位置的数值
  3. begin右移,end左移,继续找大找小,继续交换
  4. 重复上述操作,直到遍历完所有数组

排序优化后问题

若是max的位置与begin重合,则begin先与min的位置交换,此时max位置的最大值被交换走,导致endmax交换的数值是错误的。

问题解决:

maxbegin重合时,beginmin交换后导致max指向的不再是最大值,所以当我们对begin交换后,就要对max进行一个修正,让max指向最大值,然后完成end的交换

1、max与begin重合,并且begin此时完成了交换,此时最大值已经交换到了min所指向的位置

2、对max进行修正并完成与end的交换

优化后代码: 

//交换两个数据
void Swap(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

//选择排序
void SelectSort(int* arr, int size)
{
	int begin = 0;
    int end = size - 1;
    while (begin < end)
    {
        int max = begin;
        int min = begin;
        int i = 0;
        for (i = begin+1; i <= end; i++)
        {
            if (arr[i] < arr[min])
            {
                min = i;
            }
            
            if (arr[i] > arr[max])
            {
                max = i;
            }
        }
        
        Swap(&arr[begin], &arr[min]);
        if (begin == max)				//修正max
        {
            max = min;
        }
        Swap(&arr[end], &arr[max]);
        
        begin++;
        end--;
    }
}

选择排序时间复杂度:

时间复杂度:O(n^2)
空间复杂度:O ( 1 )
​选择排序是不稳定的排序

三、插入排序

直接插入排序是一种简单的插入排序法,对数组进行一个遍历,每次都对待排的数据按照大小顺序插入到一个有序数组中的特定位置,直到所有的数据全部插入完毕,就得到一个有序数列。

​ 插入排序的算法非常简单,依次对每一个元素进行单趟排序就行了,由于要前一个数比较则只需要从1开始遍历n-1

                                   813242d2ff544526b82a2ee67f06d5bc.png   

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的

元素顺序后移

20210223174254141.gif

插入排序代码:

void InsertSort(int* arr, int size)
{
	int i = 0;
	for (i = 1; i < size; i++)
	{
	    int end = i;
        int temp = arr[end];	//记录待排数值
        while (end > 0)
        {
            if (arr[end-1] > temp)	//若前一个数大于待排数值,则后移一位
            {
                arr[end] = arr[end-1];
            	end--;
            }
            else
            {
                break;
            }
        }
        // arr[end-1] = temp;是之前的错误,现已修正
        arr[end] = temp;	//将数据放入插入位置
	}
}

插入排序的时间复杂度:

1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1),它是一种稳定的排序算法
4. 稳定性:稳定

四、希尔排序

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

0b5e3b84b85d427d84e260a1f6733a5e.png

1. 希尔排序是对直接插入排序的优化。

2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。

3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的

14642c0b17cc41a496c808ed6214b234.gif#pic_center

希尔排序代码实现:

void ShellSort(int* arr, int size)
{
    int gap = size;
    while (gap > 1)
    {
        gap = gap / 2;	//调整希尔增量
        int i = 0;
        for (i = 0; i < size - gap; i++)	//从0遍历到size-gap-1
        {
            int end = i;
            int temp = arr[end + gap];
            while (end >= 0)
            {
                if (arr[end] > temp)
                {
                    arr[end + gap] = arr[end];
                    end -= gap;
                }
                else
                {
                    break;
                }
            }
            arr[end + gap] = temp;	//以 end+gap 作为插入位置
        }
    }
}

希尔排序的时间复杂度:

希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些书中给出的希尔排序的时间复杂度都不固定:

 

1e38ca2f0beb4bebb4be6a06a8edcabf.png

 

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

稳定性:不稳定

 

 

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

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

相关文章

软件测试之性能测试详解(含文档+视频讲解)

性能测试基础 为什么要进行性能测试&#xff08;WHY&#xff09;&#xff08;最重要&#xff09; 应用程序是否能够很快的响应用户的要求&#xff1f;应用程序是否能处理预期的用户负载并有盈余能力&#xff1f;应用程序是否能处理业务所需要的事务数量&#xff1f;在预期和非…

基于Python flask 的某招聘网站爬虫,招聘岗位可视化系统

招聘信息可视化系统 一、介绍 原文地址 今天为大家带来的是Python基于Flask的招聘信息爬取&#xff0c;招聘岗位分析、招聘可视化系统。 此系统是一个实时分析招聘信息的系统&#xff0c;应用Python爬虫、Flask框架、Echarts、VUE等技术实现。 本项目利用 Python 从某招聘网…

【C++】动静态库的生成与调用

目录层级 lib/Deal.cpp #include "Deal.hpp" #include <iostream>int DataInc(int num) {std::cout << __FUNCTION__ << " Dealing " << num << "..." << std::endl;return num; }int DataDec(int num)…

小程序大作用:教师得力助手

学生成绩查询小程序&#xff0c;一种快捷便利的工具&#xff0c;可以帮助老师们更好地了解学生的学习状况。今天教给各位老师如何制作这样一个小程序&#xff0c;并提供实用的建议。当然&#xff0c;对于许多老师而言&#xff0c;使用现成的工具是更为高效便捷的选择。 今天我为…

for forin forof forEach map区别

一、总结 相同点&#xff1a;都是串行遍历。不同点&#xff1a; 二、for of循环 设计目的&#xff1a;遍历所有数据结构的统一方法。原理&#xff1a;会调用数据结构的Symbol.iterator方法。 只要数据结构定义了Symbol.iterator属性&#xff0c;就能用for of遍历它的成员。…

循环神经网络-简洁实现

参考&#xff1a; https://zh-v2.d2l.ai/chapter_recurrent-neural-networks/rnn-concise.html https://pytorch.org/docs/stable/generated/torch.nn.RNN.html?highlightrnn#torch.nn.RNN RNN import torch from torch import nn from torch.nn import functional as F from…

安防监控视频云存储平台EasyNVR对接EasyNVS时,一直不上线该如何解决?

视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入&#xff0c;并能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。 近期有用户在使用安防视频平台EasyNVR对接上级平台EasyNVS时&#xff0c;出现了一直不上线…

文档丢失怎么找回?学会这3个方法就足够!

场景1&#xff1a;“不是吧&#xff01;我辛辛苦苦写的文档好像忘记保存就退出了&#xff01;谁能救救我&#xff01;帮我找回丢失的文档&#xff1f;” 场景2&#xff1a;“电脑里的文档太多了&#xff0c;每次在清理时都容易误删。有什么方法可以找回我丢失的文档吗&#xff…

iPhone密码忘了怎么办?这3招已足矣

很急&#xff01;之前改了手机密码&#xff0c;现在完全想不起来。该试的数字也都试过了&#xff0c;根本没用&#xff0c;求一个能解锁iPhone手机的方法&#xff01;感谢&#xff01; iPhone手机的锁屏密码是一个保护用户隐私的功能。如果没有锁屏密码给手机上一道“锁”&…

JavaScript系列从入门到精通系列第二篇:JavaScript书写位置、注释和结束符

文章目录 一&#xff1a;JavaScript书写位置 1&#xff1a;CSS书写位置 (一)&#xff1a;行内样式表 (二)&#xff1a;内部样式表 (三)&#xff1a;外部样式表 2&#xff1a;Js书写位置 (一)&#xff1a;行内样式表 (二)&#xff1a;内部样式表 (三)&#xff1a;外部样…

Cesium 地球(1)-概览

​ 参考: CesiumJS 2022^ 源码解读[4] - 最复杂的地球皮肤 影像与地形的渲染与下载过程 Cesium 地球(1)-概览 相关类的从属关系: 地球由 影像数据&#xff0c;和地形数据共同组成。 流程概览: // Scene.jsfunction render() {// ① 更新影像图层的可见性globe.update();/…

java-decompiler

Java Decompiler GitHub F:\Document_JD-GUI\jd-gui-windows-1.4.0

73家央国企专场培训|第38期信创专业人员-精华班在京成功举办

9月8日-10日&#xff0c;由太极计算机股份有限公司-太极信创研习院(以下简称“太极股份”&#xff09;主办&#xff0c;北京慧点科技有限公司协办的“信息技术应用创新专业人员&#xff08;ITAIP&#xff09;-第38期信创精华班&#xff08;央国企专场培训&#xff09;”在北京市…

[游戏开发][Shader]ShaderToy通用模板转Unity-CG语言

这个通用模板貌似是Candcat写的&#xff0c;漏了几个宏定义&#xff0c;我这给补一下&#xff0c;例如&#xff1a; #define iTime _Time.y #define atan atan2 对照表如下 代码如下 Shader "Shadertoy/Template" {Properties{iMouse("Mouse Pos", Vec…

恩智浦为稳固地位,将扩大投资4国家 | 百能云芯

车用芯片制造商恩智浦&#xff0c;今天宣布了一项重大计划&#xff0c;旨在进一步深耕欧洲市场。该公司将利用欧洲微电子和通信技术共同利益重点计划&#xff08;IPCEI ME/CT&#xff09;的支持&#xff0c;加强其在奥地利、德国、荷兰和罗马尼亚的研发能力&#xff0c;并将根据…

MySQL数据库详解 五:用户管理

文章目录 1. 数据库的用户管理1.1 新建用户1.2 重命名用户1.3 删除用户1.4 修改用户密码1.5 忘记用户密码的解决方法1.6 数据库用户授权1.6.1 授权用户权限类别1.6.2 添加权限1.6.2 撤销权限 2. mysql命令 1. 数据库的用户管理 1.1 新建用户 create user 用户名来源地址 [ide…

性能测试必备知识-使用MySQL存储过程构造大量数据:实例解析

在软件开发过程中&#xff0c;测试是一个不可或缺的环节。通过测试&#xff0c;我们可以发现并修复软件中的各种问题&#xff0c;提高软件的质量和稳定性。然而&#xff0c;手动编写大量的测试用例是一项耗时且容易出错的任务。为了解决这个问题&#xff0c;我们需要学会使用批…

一文了解线上展厅设计与搭建要点,线上展厅有哪些应用

引言&#xff1a; 线上展厅已经成为了现代营销领域中不可或缺的一部分。通过巧妙的设计与搭建&#xff0c;企业可以与潜在客户建立更深入的联系&#xff0c;提高品牌知名度&#xff0c;从而提高商务成交量。 一、线上展厅设计要点 线上展厅的设计是关键的一步&#xff0c;因为…

架构师面试必备:高并发限流算法全攻略

Hello大家好&#xff0c;我是小米&#xff01;今天我要和大家聊一聊一个在技术面试中经常被问到的问题——高并发限流算法&#xff01;这个话题非常有趣&#xff0c;也是我们在日常工作中经常会碰到的挑战之一。在本文中&#xff0c;我将详细介绍一些常见的高并发限流算法&…

无涯教程-JavaScript - SUMIF函数

描述 您可以使用SUMIF函数对满足指定条件的范围内的值求和。 语法 SUMIF (range, criteria, [sum_range])争论 Argument描述Required/Optionalrange 您要通过条件判断的单元格范围。 每个范围中的单元格必须是数字或包含数字的名称,数组或引用。 空白和文本值将被忽略。 所…