数据结构之排序了如指掌(二)

news2024/11/16 16:35:59

目录

题外话

正题

选择排序

选择排序思路

选择排序代码详解

选择排序复杂度

双向选择排序

双向选择排序思路

双向选择排序代码详解

堆排序

堆排序思路

堆排序代码详解

堆排序复杂度

冒泡排序

冒泡排序思路

冒泡排序代码详解

冒泡排序复杂度

小结


题外话

今天状态超级好,废话不说直接写博客!!

先说下,我会尽力将博客中的各种问题,通过文字和图形和代码结合的方式让大家更直观清晰的去理解,毕竟写博客不是看视频,我只能尽量让大家明白这些知识

想学的人自然会去琢磨,不想学的人你就喂到他嘴里,他都不想咀嚼一下

正题

上篇我们写完了直接插入排序和希尔排序,让我们继续写排序内容

选择排序

选择排序思路

创建i和j

i从0下标开始,j从i+1开始

j在数组中寻找剩余元素的最小值

找到之后把最小值和i交换

循环此过程,直到i走到数组倒数第1个元素结束,倒数第一个元素不需要再排序,因为前面都排序完成,最后一个肯定是有序的

觉得上面讲的不清晰可以看下图

选择排序代码详解

public void selectSort(int[] arr)
{
    //创建tmp作为临时变量,swap作为交换变量
    int tmp;
    int swap;

    //i从0下标开始,i走到倒数第二个元素排完序就结束,最后一个元素必然有序!!
    for (int i=0;i<arr.length-1;i++) {
        //tmp是记录最小元素下标值,先将i下标放入tmp中
        tmp=i;

        //j下标就等于i+1
        int j = i + 1;

        //j每趟肯定是从i+1开始到数组最后一个元素结束
        for (; j <arr.length; j++) {

            //当tmp中元素大于j中元素,就说明tmp不是剩余数组中最小的元素
            if (arr[tmp] > arr[j]) {
                //将j下标传给tmp
                tmp = j;
            }
        }
        //如果i==tmp说明i此时就是剩余数组元素中最小的,不需要再交换位置
        //否则再交换位置
        if(i!=tmp)
        {
            swap = arr[tmp];
            arr[tmp] = arr[i];
            arr[i] = swap;
        }
    }
}

选择排序复杂度

时间复杂度:O(n^2)无论数组是否有序,i都会从0下标开始到arr.length-2下标结束

j总共会走n-1,n-2,n-3,.......1,相当于等差数列,所以计算出来为O(n^2)

空间复杂度:O(1),因为就一个数组

稳定性:不稳定,相同元素的位置可能会改变

双向选择排序

上面属于是单向的选择排序,下面我们说说另一个版本双向选择排序

双向选择排序思路

1.创建left,right两个变量,让left从0下标开始向后面走,让right从arr.lenght-1开始向前面走

2.创建minIndex,和maxIndex两个变量,并把left下标传给这两个变量

3.i从letf+1下标往后走,如果遇到比minIndex小的下标元素,就把i下标传给minIndex

4.如果遇到比maxIndex大的下标元素,就把i下标传给maxIndex

5.最后minIndex中的元素一定是剩余数组中最小的元素,maxIndex中的元素一定是剩余数组中最大的元素

6.将minIndex中的元素与left交换,maxIndex中的元素与right交换

7.left++,right--,循环上述过程,最后数组实现从小到大排序

注意!!! 如下图

双向选择排序代码详解

public void DoubleSelectSort(int[] arr)
{
    //创建left让其指向0下标
    int left=0;

    //创建right让其指向arr.length-1下标
    int right=arr.length-1;

    //left等于right说明排序已经结束,所以left小于right
    while (left<right) {

        //创建minIndex和maxIndex每次循环将left传给他们
        int minIndex=left;
        int maxIndex=left;

        //i从left+1开始,每趟到right结束,一定要包括right所以i小于等于right
        for (int i = left + 1; i <= right; i++) {
    //如果遇到i下标元素值小于minIndex下标元素值,说明minIndex不是剩余数组元素最小值,将i传给minIndex
            if (arr[i] < arr[minIndex]) {
                minIndex = i;
            }
   //如果遇到i下标元素值大于maxIndex下标元素值,说明maxIndex不是剩余数组元素最大值,将i传给maxIndex
            if (arr[i] > arr[maxIndex]) {
                maxIndex = i;
            }
        }
        //将最小值和left交换
        swap(arr,left,minIndex);

        //如果maxIndex==left的话,而且left在上面已经和minIndex交换了
        if (maxIndex==left)
        {
            //我们需要将left交换的mainIndex传入maxIndex,这样maxIndex才是我们需要的
            maxIndex=minIndex;
        }
        //将最大值和right交换
        swap(arr,right,maxIndex);
            //left往前继续排序
            left++;
            //right往后继续排序
            right--;

    }
}
//下标元素交换代码
public void swap(int[] arr,int a,int b)
{
    int tmp=arr[a];
    arr[a]=arr[b];
    arr[b]=tmp;
}

堆排序

堆排序思路

1.先向下调整创建大根堆

2.堆排序,创建好的大根堆,堆顶元素和最后一个没有交换过位置的元素交换位置,然后将没有交换位置的元素,再向下调整成大根堆,然后循环这个过程

之前在堆的那篇博客中讲过堆排序这里就不说太多

堆排序代码详解

//建立大根堆
private void creatHeap(int[] arr)
 {
     //父亲结点从最后往上依次建立大根堆
     for (int parent=(arr.length-1-1)/2;parent>=0;parent--)
     {
         //向下调整成大根堆
    siftDown(arr,parent,arr.length);
     }
 }
 //向下调整
 private void siftDown(int[] arr,int parent,int len)
 {
     //找到孩子节点
     int child=parent*2+1;
     //孩子节点一定不能超过数组元素数量
     while (child<len)
     {
         //孩子结点+1也不能超过数组元素数量并且child下标元素小于child+1下标元素
         if (child+1<len&&arr[child]<arr[child+1])
         {
             //child++,child指向孩子中最大的那个
             child++;
         }
         //如果孩子中最大的那个大于父亲结点
         if (arr[child]>arr[parent])
         {
             //交换父亲和孩子结点的位置
             swap(arr,parent,child);
             //继续向下调整
             parent=child;
             child=parent*2+1;
         }else
         //如果孩子中最大的不大于父亲结点则说明建立成大根堆,直接退出
         {
             break;
         }
     }
 }
 //从小到大排序,堆排序
 public void heapSort(int[] arr)
 { //创建成大根堆
     creatHeap(arr);
     //从最后一个结点开始
     int end=arr.length-1;
     //当end>0的时候
     while (end>0) {
         //交换堆顶元素和最后一个元素位置,这样end位置会是整个堆最大的元素
         swap(arr,0,end);
         //向下排序,把除去end下标的往后元素,建立成大根堆
         siftDown(arr,0,end);
         //end--继续循环
         end--;
     }
 }

堆排序复杂度

时间复杂度:O(n*logn),

建立大根堆时间复杂度为O(n),

而堆排序交换堆顶元素和最后一个没有交换元素的位置(交换n次)并且要向下调整为大根堆(相当于根的深度也就是logn),时间复杂度为O(nlogn)

所以时间复杂度为O(nlogn)

空间复杂度:o(1),就一个数组

稳定性:不稳定,相同元素的位置可能会改变

冒泡排序

冒泡排序思路

1.如果相邻的两个元素,前面的大于后面的元素,那么就把这两个元素调换位置
2.继续往后走,按照以上的方式进行循环,可以保证每一趟最后一个元素一定是数组中最大的元素
3.n个元素要走n-1趟

上面看不懂请看下图

冒泡排序代码详解

public void bubbleSort(int[] arr)
{
//i为趟数,n个元素只需要n-1趟
for (int i=0;i<arr.length-1;i++)
{//创建一个flg将false传入
    boolean flg=false;
    //莓走完一趟,最后一个元素一定为最大值,最后一个元素不需要再交换
    for (int j=0;j<arr.length-1-i;j++)
    {
        //如果相邻元素前面的比后面的大
    if (arr[j]>arr[j+1])
    {
        //交换两个元素位置
       swap(arr,j,j+1);
       //如果交换顺序了,就把flg变为true
       flg=true;
    }
    }
    //如果!flg为true则说明没有交换顺序,也就说明数组已经有序了,不需要再进行排序
    if (!flg)
{
    break;
}
}
}

冒泡排序复杂度

时间复杂度:O(n^2),j需要进行n+n-1+n-2+n-3......1次比较,等差数列,时间复杂度为O(n^2)

空间复杂度:O(1),就一个数组

稳定性:稳定,无论怎么交换顺序,相同的元素位置不会改变

小结

没想到会写这么久,画图还有逻辑梳理真的很需要时间,喜欢的家人们麻烦给我个三连(点赞关注收藏!!!!)

求求了!!

博主有不好的地方请在评论区留言或者私信,我都会虚心接受!!!


 

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

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

相关文章

2024年第十六届“华中杯”(A题)大学生数学建模挑战赛| 物理建模,多目标优化| 数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看华中杯 (A题&#xff09;&#xff01; CS团队倾…

最简单的例子说清楚量化对冲----量化中性策略 vs DMA策略

一个简单的例子 何为中性对冲&#xff0c;比如股票市场上有一个指数叫做中国指数&#xff0c;由十支股票组成。现在每一只股票买一万块&#xff0c;共十万。这样子我们是不是相当于等权的买了整个指数所包含的全部股票。现在出现一个东西叫做股指期货&#xff0c;股指期货的作…

Redis: 集群

文章目录 一、单点Redis的问题二、主从架构1、概述2、集群结构3、主从数据同步原理&#xff08;1&#xff09;全量同步&#xff08;2&#xff09;增量同步 4、总结&#xff08;1&#xff09;全量同步和增量同步的区别&#xff08;2&#xff09;什么时候执行全量同步&#xff08…

基础拓扑学习

基础拓扑 有限集、可数集和不可数集 2.1 定义 考虑两个集 A A A和 B B B&#xff0c;他们的元素可以是任何东西。假定对于 A A A的每个元素 x x x&#xff0c;按照某种方式&#xff0c;与集 B B B的一个元素联系着&#xff0c;这个元素记作 f ( x ) f\left( x \right) f(x);那…

Django框架设计原理

相信大多数的Web开发者对于MVC&#xff08;Model、View、Controller&#xff09;设计模式都不陌生&#xff0c;该设计模式已经成为Web框架中一种事实上的标准了&#xff0c;Django框架自然也是一个遵循MVC设计模式的框架。不过从严格意义上讲&#xff0c;Django框架采用了一种更…

Syncthing实时共享同步数据,可用于异地备份数据

一、Syncthing概述 Syncthing的主要功能是用来进行文件传输&#xff0c;我需要对多台不同系统的&#xff08;windows&#xff0c;linux&#xff09;服务器的数据进行备份&#xff0c;当前测试使用Syncthing来进行两台Centos7服务器数据备份&#xff0c;注意在不同服务器使用Syn…

手写商城项目学习/复习到的知识

1.在windowr创建项目可以选择自定义/vue2/vue3,但尝试在vscode不能选择. 2.vant vant是组件库,可导入结构等.vant2用于vue2,vant3,vant\4用于vue3 vant2的使用 官网: Vant 2 - 轻量、可靠的移动端组件库 (gitee.io) 全部导入:将vant所有的组件放到了所有组件内component使…

web自动化测试系列-selenium常用方法定位(五)

目录 1.selenium的定位方法 2.操作案例 3.实现代码 前面我们介绍了html页面元素主要是通过标签和属性来进行定位 &#xff0c;只要满足唯一&#xff0c;无论是标签还是属性 &#xff0c;都能进行定位 。当然 &#xff0c;我们要通过selenium来进行定位 &#xff0c;同样还是…

Python:可迭代对象与迭代器

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 根据Python官方文档&#xff0c;可迭代对象(iterable)是“一种能够逐个返回其成员项的对象”。具体来说&#xff0c;这种对象要么定义了一个返回迭代器(iterator)的魔术…

深入解析Nacos配置中心的动态配置更新技术

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在微服务架构中&#xff0c;配置管理变得尤为关键。Nacos&#xff0c;作为一个开源的、易于使用的、功能丰富的平台&#xff0c;为…

python 无处不在的二分搜索

我们知道二分查找算法。二分查找是最容易正确的算法。我提出了一些我在二分搜索中收集的有趣问题。有一些关于二分搜索的请求。我请求您遵守准则&#xff1a;“我真诚地尝试解决问题并确保不存在极端情况”。阅读完每个问题后&#xff0c;最小化浏览器并尝试解决它。 …

从计算机视觉到生命科学

人工智能技术的快速发展正在深刻影响和重塑我们的生活。作为AI领域的前沿方向,多模态大模型凭借其强大的跨域学习和推理能力,在众多行业和科学领域展现出广阔的应用前景。多模态AI指的是能够同时处理和整合文本、图像、音频、视频等不同模态数据的智能系统。这种融合不同信息源…

Java详解:GUI容器组件 | 功能组件

✎ 简介&#xff1a; Graphical User Interface&#xff08;GUI&#xff09;图形用户界面 图形界面对于用户来说在视觉上更易于接受. ✎ 关于swing: • swing是一个为java设计的GUI工具包javax.swing&#xff0c;包括了用户界面的各种组件. • swing中组件可以分为两大类&…

刷题之Leetcode19题(超级详细)

19.删除链表的倒数第N个节点 力扣题目链接(opens new window)https://leetcode.cn/problems/remove-nth-node-from-end-of-list/ 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 进阶&#xff1a;你能尝试使用一趟扫描实现吗&#x…

【C语言__函数栈帧的创建和销毁__复习篇9】

目录 前言 一、知识补充 二、分析创建和销毁的过程 三、前言问题回答 前言 本篇主要讨论以下问题&#xff1a; 1. 编译器什么时候为局部变量分配的空间 2. 为什么局部变量的值是随机的 3. 函数是怎么传参的&#xff0c;传参的顺序是怎样的 4. 形参和实参是什么关系 5. 函数…

Jmeter 性能压测-常见问题

1、怎么确定系统最大负载&#xff1f; 通过负载测试&#xff0c;不断增加用户数&#xff0c;随着用户数的增加&#xff0c;各项性能指标也会相应产生变化&#xff0c;当出现了性能拐点。 比如&#xff0c;当用户数达到某个数量级时&#xff0c;响应时间突然增长&#xff0c;那…

算法:期望场景;鲁棒优化

部分代码 for i1:T stst[D_DGk(i)*min_P_DG<P_DGk(i)<D_DGk(i)*max_P_DG]; end for i2:T indicatorD_DGk(i)-D_DGk(i-1); rangei:min(T,iT_up-1); st st[D_DGk(range)>indicator]; end for i2:T indicatorD_DGk(i-1)-D_DGk(i); rangei:min(T…

《QT实用小工具·二十九》托盘图标控件

1、概述 源码放在文章末尾 托盘图标控件 可设置托盘图标对应所属主窗体。 可设置托盘图标。 可设置提示信息。 自带右键菜单。 下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #ifndef TRAYICON_H #define TRAYICON_H/*** 托盘图标控件* 1. 可设置托盘图标…

书生·浦语大模型全链路开源体系-第5课

书生浦语大模型全链路开源体系-第5课 书生浦语大模型全链路开源体系-第5课相关资源LMDeploy基础配置LMDeploy运行环境下载internlm2-chat-1_8b模型使用Transformer来直接运行InternLM2-Chat-1.8B模型使用LMDeploy以命令行方式与InternLM2-Chat-1.8B模型对话设置KV Cache最大占用…

Spring Batch

Spring是一个开放源代码的J2EE应用程序框架&#xff0c;由Rod Johnson发起&#xff0c;是针对bean的生命周期进行管理的轻量级容器&#xff08;lightweight container&#xff09;。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题&#xff0c;提供了功能强大IOC、AOP及W…