【数据结构与算法】排序算法:冒泡排序,冒泡排序优化,选择排序、选择排序优化

news2024/9/22 20:41:23

目录

一、冒泡排序

1、冒泡排序思想

2、冒泡排序算法的性能分析

代码实现:

二、选择排序

1、选择排序思想

2、选择排序算法的性能分析 

代码实现:


一、冒泡排序

1、冒泡排序思想

冒泡排序的基本思想是通过相邻元素之间的比较和交换来逐步将最大(或最小)的元素移到右边(或左边)。具体来说,冒泡排序的步骤如下:

  1. 从数组的第一个元素开始,依次比较相邻的两个元素。如果前面的元素大于后面的元素,则交换它们的位置,以使较大的元素向右移动。
  2. 继续向数组的下一个相邻元素进行比较和交换,直到最后一个元素,此时最大的元素已经移到了数组的最右侧。
  3. 重复以上步骤,但这次只需要比较和交换前 n-1 个元素,因为最大的元素已经在正确的位置上。
  4. 重复进行 n-1 轮比较和交换,直到所有元素都按照从小到大(或从大到小)的顺序排列。

2、冒泡排序算法的性能分析

  • 最好的情况下,当输入数组已经是有序的,冒泡排序只需进行一轮比较,时间复杂度为 O(n)。
  • 最坏的情况下,当输入数组是逆序的,冒泡排序需要进行 n-1 轮比较和交换,时间复杂度为 O(n^2)。
  • 平均情况下,冒泡排序的时间复杂度为 O(n^2)。
  • 冒泡排序是一种稳定排序算法,不会改变相等元素的相对顺序。
  • 冒泡排序是一种原地排序算法,不需要额外的空间。

代码实现:

1、普通版本:

// 定义一个交换函数,用于交换两个整数的值
void swap(int* a, int* b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

// 冒泡排序函数,对数组进行排序
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]);
            }
        }
    }
}

2、优化版本 :

思想:在优化版本的冒泡排序算法中,通过添加一个标记变量flag,可以在一轮排序过程中标记是否有进行过交换操作,如果某一轮排序中没有进行过任何交换,说明数组已经有序,可以提前结束排序。

// 定义一个交换函数,用于交换两个整数的值
void swap(int* a, int* b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

// 冒泡排序函数,对数组进行排序
void BubbleSortPro(int* a, int n)
{
    int i, j, flag = 0; 
    // flag用于标记是否有交换发生,初始值为0
    
    // 外层循环控制排序的轮数
    for (i = 0; i < n - 1; i++)
    {
        flag = 0; // 在每一轮开始时,将flag重置为0
        
        // 内层循环进行相邻元素的比较和交换
        for (j = 0; j < n - i - 1; j++)
        {
            // 如果前一个元素大于后一个元素,则交换它们的位置,并将flag设置为1
            if (a[j] > a[j + 1])
            {
                swap(&a[j], &a[j + 1]);
                flag = 1;
            }
        }
        
        // 如果在一轮排序中没有进行过任何交换,说明数组已经有序,可以提前结束排序
        if (flag == 0)
        {
            break;
        }
    }
}

二、选择排序

1、选择排序思想

选择排序的基本思想可以概括为以下几个步骤:

  1. 遍历待排序的数组,将数组中的第一个元素视为当前最小值。
  2. 在剩余的未排序部分中,依次查找比当前最小值更小的元素。
  3. 如果找到了比当前最小值更小的元素,则将其标记为新的最小值。
  4. 遍历完未排序部分,将新的最小值与当前最小值交换位置。
  5. 如此循环,直到所有元素都被排序。

通过每次从剩余未排序部分选择最小的元素,并将其放在已排序部分的末尾,逐步构建有序序列。

2、选择排序算法的性能分析 

  • 选择排序的时间复杂度为O(n^2),其中n是待排序数组的元素个数。这是因为在每一轮遍历中,需要比较剩余未排序部分的所有元素,最坏情况下要进行n-1次比较。总共需要进行n-1轮遍历,因此时间复杂度为O(n^2)。
  • 选择排序是一种不稳定的排序算法。当待排序数组中存在相同元素时,选择排序可能会改变相同元素的相对顺序。具体来说,在选择过程中,如果当前的最小元素与其他相同元素交换位置,可能会改变它们的相对顺序。
  • 选择排序是一种原地排序算法,即排序过程中不需要额外的空间。它只需要一个额外的变量来记录最小(或最大)元素的位置,通过交换元素位置来实现排序,所以空间复杂度为O(1)。

综上所述,选择排序的时间复杂度为O(n^2),空间复杂度为O(1),并且是一种不稳定的排序算法。

 

代码实现:

1、普通版本:

void swap(int* a,int* b)
{
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;
}

void SelctSort(int* a, int n)
{
    int i, j, key;

    // 遍历数组,i表示已排序部分的末尾元素的索引
    for (i = 0; i < n - 1; i++)
    {
        key = i; // 将当前位置视为最小值的索引

        // 在未排序部分中查找最小值
        for (j = i + 1; j < n; j++)
        {
            if (a[key] > a[j])
            {
                key = j; // 更新最小值的索引
            }
        }

        // 如果最小值不是当前位置的元素,则交换位置
        if (key != i)
        {
            swap(&a[i], &a[key]);
        }
    }
}

 2、优化版本

 优化版本的思想是在选择排序的基础上,同时追踪并找出未排序部分的最大值和最小值,并将它们分别放置在已排序部分的末尾和开头。通过这种方式,可以减少交换的次数,从而提高排序的效率。

void swap(int* a,int* b)
{
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;
}

void SelctSortPro(int* a, int n)
{
    int i, j;
    int begin = 0, end = n - 1;
    int maxi = end, mini = begin;

    // 在每一次循环中,将未排序部分的最大值和最小值分别放置在已排序部分的末尾和开头
    while (begin < end)
    {
        i = begin;
        j = end;
        maxi = end;
        mini = begin;

        // 在未排序部分中查找最大值和最小值
        while (i <= end)
        {
            if (a[maxi] < a[i])
            {
                maxi = i; // 更新最大值的索引
            }
            if (a[mini] > a[i])
            {
                mini = i; // 更新最小值的索引
            }
            i++;
        }

        // 将最小值放置在已排序部分的开头
        swap(&a[begin], &a[mini]);
        
        // 如果最大值所在位置等于begin,更新最大值所在位置为mini
        if (maxi == begin)
        {
            maxi = mini;
        }
        
        // 将最大值放置在已排序部分的末尾
        swap(&a[end], &a[maxi]);

        // 更新已排序部分和未排序部分的起始和结束位置
        begin++;
        end--;
    }
}

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

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

相关文章

前端JavaScript篇之实现有序数组原地去重方法有哪些?

目录 实现有序数组原地去重方法有哪些&#xff1f;方法一&#xff1a;使用 Set 数据结构代码实现&#xff1a;思路说明&#xff1a; 方法二&#xff1a;使用双指针遍历代码实现&#xff1a;思路说明&#xff1a; 实现有序数组原地去重方法有哪些&#xff1f; 在 JavaScript 中…

Dockerfile-xxxx

1、Dockerfile-server FROM openjdk:8-jdk-alpine WORKDIR /app COPY . . CMD java -Xms1536M -Xmx1536M -XX:UseG1GC -jar -Dlog4j2.formatMsgNoLookupstrue -Dloader.pathresources,lib -Duser.timezoneGMT-05 /app/server-main-1.0.0.jar 2、Dockerfile-bgd #FROM openjdk…

(笔记总结)C/C++语言的常用库函数(持续记录,积累量变)

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

代码+视频R语言绘制逆概率加权后的基线表

基于 PS &#xff08;倾向评分&#xff09;的逆概率加权(IPTW )法首先由&#xff32;osenbaum作为一种以模型为基础的直接标准化法提出&#xff0c;属于边际结构模型。简单来说&#xff0c;就是把许多协变量和混杂因素打包成一个概率并进行加权&#xff0c;这样的话&#xff0c…

Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心,Kotlin

Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心&#xff0c;Kotlin 在 Android双击图片放大移动图中双击点到ImageView区域中心&#xff0c;Kotlin-CSDN博客 基础上&#xff0c;这次使用ScaleGestureDetector检测两根手指的缩放动作&a…

开源人工智能AI壁纸生成器--AI Wallpaper Generator

AI Wallpaper Generator AI Wallpaper Generator&#xff1a;AI Wallpaper Generator | AI Wallpaper Shop GitHub地址&#xff1a;https://github.com/all-in-aigc/aiwallpaper 一款开源人工智能AI壁纸生成器&#xff0c;根据用户的输入提示词&#xff0c;即可生成对应的高…

Python Tornado 实现SSE服务端主动推送方案

一、SSE 服务端消息推送 SSE 是 Server-Sent Events 的简称&#xff0c; 是一种服务器端到客户端(浏览器)的单项消息推送。对应的浏览器端实现 Event Source 接口被制定为HTML5 的一部分。相比于 WebSocket&#xff0c;服务器端和客户端工作量都要小很多、简单很多&#xff0c…

使用Bitcoin Core钱包启动signet测试网络

使用Bitcoin Core钱包启动signet测试网络 为什么要启动测试网络 我们的目的是了解BTC网络的运行原理&#xff0c;学习BTC相关技术。在主网中有较高的手续费和大量的区块数据&#xff0c;不利于我们进行测试。 下载钱包 一定要去可信的网站下载钱包&#xff0c;否则非常容易…

java web servlet 学习系统进度管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web学习系统进度管理系统是一套完善的java web信息管理系统 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环 境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为…

go语言(十四)----反射

变量的结构 2 举个例子 package mainimport "fmt"type Reader interface {ReadBook() }type Writer interface {WriteBook() }//具体类型 type Book struct {}func (this *Book) ReadBook() {fmt.Println("Read a Book")}func (this *Book) WriteBook() {…

Mac上如何设置映射某个网站站点域名的IP

最近某常用的站点换 IP 了&#xff0c;但是 DNS 服务器还没有修改&#xff0c;这就导致无法访问&#xff08;换 DNS 服务器也不行&#xff09;。在用了一段时间的 IP 访问之后&#xff0c;还是没好&#xff0c;不知道是 DNS 污染还是咋了&#xff0c;所以最后还是手动改一下吧。…

【LeetCode】每日一题 2024_1_22 最大交换(模拟)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;最大交换题目描述&#xff1a;代码与解题思路 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 几百年没有见到题目描述这么短的题目了&#xff0c;泪目了 题目&#x…

电商平台接口自动化框架实践

技术栈 Mimproxy(抓包)pytestalluredockerJenkinsgitlab 语言&#xff1a;电商API接口自动化实现流程 红色为可实现/尚未完成 绿色为需要人工干预部分 自动生成测试用例模板&#xff08;俩种方式二选一&#xff09;&#xff1a; mimproxy&#xff0c;通过浏览器代理抓包方式…

074:vue+mapbox 加载here地图(影像瓦片图 v2版)

第074个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中加载here地图的影像瓦片图 v2软件版本。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共77行)相关API参考:专栏目标示例效果

区块链游戏:Web3时代玩法的全新演绎

随着区块链技术的蓬勃发展&#xff0c;区块链游戏正成为数字娱乐领域的一颗璀璨明珠。在Web3时代&#xff0c;区块链游戏以其去中心化、透明、可验证的特性&#xff0c;为玩家带来了全新的游戏体验。本文将深入探讨区块链游戏在Web3时代的崭新玩法和引领未来的可能性。 1. 去中…

GPTBots:利用FlowBot中的卡片和表单信息,提供丰富的客服体验

在当今的数字化时代&#xff0c;客户服务的形式和体验正在经历着前所未有的变革。传统的文字消息方式已经无法满足现代用户对于服务体验的多元化需求。那么&#xff0c;如何才能在这个信息爆炸的时代&#xff0c;让我们的服务方式更加个性化、多样化&#xff0c;从而提供更丰富…

分享一个“产业级,开箱即用”的NLP自然语言处理工具

NLP的全称是Natuarl Language Processing&#xff0c;中文意思是自然语言处理&#xff0c;是人工智能领域的一个重要方向 自然语言处理&#xff08;NLP&#xff09;的一个最伟大的方面是跨越多个领域的计算研究&#xff0c;从人工智能到计算语言学的多个计算研究领域都在研究计…

记录一次从有道云笔记迁移到语雀笔记

推荐阅读 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;一&#xff09; 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;二&#xff09; 1、安装git&#xff0c;python3等准备工作 文章中标注python3&#xff0c;为避免与python2 冲…

【正点原子STM32】C语言重点知识(配置MDK支持C99、位操作清零置一、带参数的宏定义、头文件的条件编译和代码条件编译、关键字、结构体指针、代码规范)

一、stdint.h简介 配置MDK支持C99 二、位操作 如何给寄存器某个位赋值&#xff08;清零置一&#xff09; 三、宏定义 带参数的宏定义 四、条件编译 头文件的条件编译和代码条件编译 五、extern声明 六、类型别名(typedef) 类型别名应用 七、结构体 应用举例&#xf…

muduo网络库剖析——线程Thread类

muduo网络库剖析——线程Thread类 前情从muduo到my_muduo 概要框架与细节成员函数使用方法 源码结尾 前情 从muduo到my_muduo 作为一个宏大的、功能健全的muduo库&#xff0c;考虑的肯定是众多情况是否可以高效满足&#xff1b;而作为学习者&#xff0c;我们需要抽取其中的精…