数据结构---排序(下)

news2024/11/8 2:53:54

一.快速排序补充

快速排序的分治部分还有其他方法,如挖坑法,快慢指针法。

1.挖坑法(重要)

思路:先将基准位置元素用tmp保存,假定基准位置没有值(有个坑),然后分别从前后向中间遍历,右边大于基准就减减,遇到小于基准的就放到基准值位置的坑中,左边亦然,遍历整个数组后,将基准值填入最后一个左边遍历值。

    //挖坑法
    public static int partition2(int[] array,int start,int end) {
        int pivot = array[start];
        int i = start;
        while(start < end) {
            while(start < end && array[end] >= pivot) {
                end--;
            }
            array[start] = array[end];
            while(start < end && array[start] <= pivot) {
                start++;
            }
            array[end] = array[start];
        }
        array[start] = pivot;
        return start;
    }

细节注意:填坑不是互换

2.快慢指针法

通过建立两个指针,一个满足小于基准值++,另一个在前一个指针不大于基准时++,大于后不再++;从而与前一个快指针换位。

//快慢指针法
    public static int partition3(int[] array,int start,int end) {
        int prev = start;
        int cur = start+1;
        while(cur <= end) {
           if(array[cur] < array[start] && array[cur] != array[++prev]) {
               swap(array,prev,cur);
           }
           cur++;
        }
        //把最后一个小于[prev]的值换到开头
        swap(array,prev,start);
        return prev;//start不行
    }

3.非递归法快速排序实现

思路:反复利用栈的push,pop来实现递归的效果。核心就是把分别把要排序的数据的left,right压入栈,在排序时弹出用于排序。

    public static void quickSort2(int[] array) {
        int left = 0;
        int right = array.length-1;
        int par = partition3(array,left,right);
        Stack<Integer> stack = new Stack<>();
        if(par > left+1) {
            //left+1是为了保证最少左边右一个元素
            stack.push(left);
            stack.push(par-1);
        }
        if(par < right-1) {
            //right-1是为了
            stack.push(par+1);
            stack.push(right);
        }
        while(!stack.empty()) {
            right = stack.pop();
            left = stack.pop();
            par = partition3(array,left,right);
            if(par > left+1) {
                //left+1是为了保证最少左边右一个元素
                stack.push(left);
                stack.push(par-1);
            }
            if(par < right-1) {
                //right-1是为了
                stack.push(par+1);
                stack.push(right);
            }
        }
    }
时间复杂度: O(N*logN)
空间复杂度: O(logN)
稳定性:不稳定

二.归并排序(递归)

思想:

采用分治法的一个非常典型的应用,将数组分解成若干子列,先使若干子列有序,再进行合并操作递归使整个数组有序。

 1.分解

     利用中间值mid递归分解

    public static void mergeSortFunc(int[] array,int left,int right) {
        if(left == right) {
            return;
        }
        int mid = (left + right) / 2;
        //分解
        mergeSortFunc(array,left,mid);
        mergeSortFunc(array,mid+1,right);
        
    }

最终分解结果是各子列被分解为长度不超过2的单元

2.合并

先对最终子列排序,之后沿用这个方法递归得数组。

    public static void merge(int[] array,int left,int mid,int right) {
        int s1 = left;
        int e1 = mid;
        int s2 = mid+1;
        int e2= right;
        int k = 0;
        int[] tmpArray = new int[right - left + 1];
        while(s1 <= e1 && s2 <= e2) {
            if(array[s1] <= array[s2]) {
                tmpArray[k++] = array[s1++];
            }else {
                tmpArray[k++] = array[s2++];
            }
        }
        while(s1 <= e1) {
            tmpArray[k++] = array[s1++];
        }
        while(s2 <= e2){
            tmpArray[k++] = array[s2++];
        }
        for (int i = 0; i < tmpArray.length; i++) {
            array[i + left] = tmpArray[i];
        }
    }

总代码:

    public static void mergeSort1(int[] array) {
        mergeSortFunc(array,0,array.length-1);
    }
    public static void mergeSortFunc(int[] array,int left,int right) {
        if(left == right) {
            return;
        }
        int mid = (left + right) / 2;
        //分解
        mergeSortFunc(array,left,mid);
        mergeSortFunc(array,mid+1,right);
        //合并
        merge(array,left,mid,right);
    }
    public static void merge(int[] array,int left,int mid,int right) {
        int s1 = left;
        int e1 = mid;
        int s2 = mid+1;
        int e2= right;
        int k = 0;
        int[] tmpArray = new int[right - left + 1];
        while(s1 <= e1 && s2 <= e2) {
            if(array[s1] <= array[s2]) {
                tmpArray[k++] = array[s1++];
            }else {
                tmpArray[k++] = array[s2++];
            }
        }
        while(s1 <= e1) {
            tmpArray[k++] = array[s1++];
        }
        while(s2 <= e2){
            tmpArray[k++] = array[s2++];
        }
        for (int i = 0; i < tmpArray.length; i++) {
            array[i + left] = tmpArray[i];
        }
    }
 

时间复杂度:O(n*logN)

空间复杂度:O(n)

 稳定性:稳定性

三.归并排序(非递归)

思路:手动分组,利用for循环将数组分解成若干子列,在分解过程中排好序,再循环回原数组。

分解:

    public static void mergeSort2(int[] array) {
        int gap = 1;
        while(gap < array.length) {
            for (int i = 0; i < array.length; i+=2*gap) {
                int left = i;
                int mid = left + gap - 1;
                int right = mid + gap;
                if(mid >= array.length) {
                    mid = array.length-1;
                }
                if(right >= array.length) {
                    right = array.length-1;
                }
            }
            gap *= 2;
        }
    }

注意:mid,right可能会越界。

合并:因为分解是从最小子列开始,所以可以在每次循环中排序合并。

    public static void mergeSort2(int[] array) {
        int gap = 1;
        while(gap < array.length) {
            for (int i = 0; i < array.length; i+=2*gap) {
                int left = i;
                int mid = left + gap - 1;
                int right = mid + gap;
                if(mid >= array.length) {
                    mid = array.length-1;
                }
                if(right >= array.length) {
                    right = array.length-1;
                }
                merge(array,left,mid,right);
            }
            gap *= 2;
        }
    }

四.计数排序(了解)

将要统计元素大小作为数组下标,通过统计要排序的元素的个数,然后按顺序打印统计数组元素遍的数组下标,完成排序。

    public static void countSort(int[] array) {
        int min = array[0];
        int max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(array[i] < min) {
                min = array[i];
            }
            if(array[i] > max) {
                max = array[i];
            }
        }
        int len = max - min + 1;
        int[] tmpArray = new int[len];
        //制作计数数组
        for (int i = 0; i < array.length; i++) {
            tmpArray[array[i] - min]++;
        }
        //完成排序
        int Index = 0;
        for (int i = 0; i < len; i++) {
            while(tmpArray[i] != 0) {
                array[Index++] = i + min;
                tmpArray[i]--;
            }
        }
    }

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

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

相关文章

第100+31步 ChatGPT学习:概率校准 Quantile Calibration

基于Python 3.9版本演示 一、写在前面 最近看了一篇在Lancet子刊《eClinicalMedicine》上发表的机器学习分类的文章&#xff1a;《Development of a novel dementia risk prediction model in the general population: A large, longitudinal, population-based machine-learn…

这款神器,运维绝杀 !!!

项目简介 CrowdSec 是一款开源的、基于社区协作的网络安全防护工具&#xff0c;它通过分析和共享IP信誉数据来对抗恶意行为。该软件不仅支持IPv6&#xff0c;而且相较于传统的Python实现&#xff0c;其采用Go语言编写&#xff0c;运行速度提升了60倍。CrowdSec 利用Grok模式解析…

Unreal5从入门到精通之如何在指定的显示器上运行UE程序

前言 我们有一个设备,是一个带双显示器的机柜,主显示器是一个小竖屏,可以触屏操作,大显示器是一个普通的横屏显示器。我们用这个机柜的原因就是可以摆脱鼠标和键盘,直接使用触屏操作,又可以在大屏观看,非常适合用于教学。 然后我们为这款机柜做了很多个VR项目,包括Uni…

R7:糖尿病预测模型优化探索

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、实验目的&#xff1a; 探索本案例是否还有进一步优化的空间 二、实验环境&#xff1a; 语言环境&#xff1a;python 3.8编译器&#xff1a;Jupyter notebo…

Django 框架:全方位技术分析

Django 框架:全方位技术分析 介绍 Django 是一个高级 Python Web 框架,鼓励快速开发和遵循设计的最佳实践。由经验丰富的开发人员打造,开源并可扩展,Django 旨在让构建 Web 应用更快、更轻松。 历史背景 Django 始于 2003 年,最初是 Lawrence Journal-World 报社的一个内…

如何用 ChatPaper.ai 打造完美的 AI 课堂笔记系统

作为学生&#xff0c;我们都遇到过这样的困扰&#xff1a;上课时记笔记太投入就听不进讲解&#xff0c;专注听讲又担心错过重要知识点。有了AI助手&#xff0c;这个问题就可以优雅地解决了。今天跟大家分享如何用ChatPaper.ai构建个人的智能课堂笔记系统。 为什么需要AI辅助记笔…

《手写Spring渐进式源码实践》实践笔记(第十六章 三级缓存解决循环依赖)

文章目录 第十六章 通过三级缓存解决循环依赖背景技术背景Spring循环依赖循环依赖类型三级缓存解决循环依赖 业务背景 目标设计一级缓存实现方案设计思路代码实现测试结果 三级缓存实现方案 实现代码结构类图实现步骤 测试事先准备属性配置文件测试用例测试结果&#xff1a; 总…

Java8新特性/java

1.lambda表达式 区别于js的箭头函数&#xff0c;python、cpp的lambda表达式&#xff0c;java8的lambda是一个匿名函数&#xff0c;java8运行把函数作为参数传递进方法中。 语法格式 (parameters) -> expression 或 (parameters...) ->{ statements; }实战 替代匿名内部类…

ubuntu双屏只显示一个屏幕另一个黑屏

简洁的结论&#xff1a; 系统环境 ubuntu22.04 nvidia-535解决方案 删除/etc/X11/xorg.conf 文件 记录一下折腾大半天的问题。 ubuntu系统是22.04,之前使用的时候更新驱动导致桌面崩溃&#xff0c;重新安装桌面安装不上&#xff0c;请IT帮忙&#xff0c;IT一番操作过后也表示…

Oracle OCP认证考试考点详解082系列15

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 71. 第71题&#xff1a; 题目 解析及答案&#xff1a; 对于数据库&#xff0c;使用数据库配置助手&#xff08;DBCA&#xff09;可以执行…

为什么说SQLynx是链接国产数据库的最佳选择?

第一是因为SQLynx提供了广泛的国产数据库支持&#xff0c;除了市面上的主流数据库MYSQL、Oracle、PostgreSQL 、SQL Server、SQLite、MongoDB外、还支持达梦人大金仓等国产数据源&#xff01; 近几年随着国产数据库市场的不断发展和成熟&#xff0c;越来越多的企业和机构开始选…

一个基于强大的 PostgreSQL 数据库构建的无代码数据库平台,快速构建应用程序,而无需编写一行代码(带私活源码)

随着企业和个人开发需求的不断增加&#xff0c;无代码平台成为了现代开发的重要组成部分&#xff0c;帮助那些没有技术背景的用户也能轻松创建和管理数据库应用程序。今天&#xff0c;我将向大家推荐一个非常出色的开源项目——Teable&#xff0c;它不仅支持无代码开发&#xf…

软件开发项目管理:实现目标的实用指南

由于软件项目多数是复杂且难以预测的&#xff0c;对软件开发生命周期的深入了解、合适的框架以及强大的工作管理平台是必不可少的。项目管理系统在软件开发中通常以监督为首要任务&#xff0c;但优秀的项目计划、管理框架和软件工具可以使整个团队受益。 软件开发项目管理的主要…

计算网络信号

题目描述&#xff1a; 网络信号经过传递会逐层衰减&#xff0c;且遇到阻隔物无法直接穿透&#xff0c;在此情况下需要计算某个位置的网络信号值。注意&#xff1a;网络信号可以绕过阻隔物 array[m][n]的二维数组代表网格地图&#xff0c; array[i][j]0代表i行j列是空旷位置&…

ESP8266 自定义固件烧录-Tcpsocket固件

一、固件介绍 固件为自定义开发的一个适配物联网项目的开源固件&#xff0c;支持网页配网、支持网页tcpsocket服务器配置、支持串口波特率设置。 方便、快捷、稳定&#xff01; 二、烧录说明 固件及工具打包下载地址&#xff1a; https://download.csdn.net/download/flyai…

数据结构与算法——Java实现 52.力扣98题——验证二叉搜索树

我将一直向前&#xff0c;带着你给我的淤青 —— 24.11.5 98. 验证二叉搜索树 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的…

[mysql]DDL,DML综合案例,

综合案例 题目如下 目录 综合案例 ​编辑 ​编辑 # 1、创#1建数据库test01_library # 2、创建表 books&#xff0c;表结构如下&#xff1a; # 3、向books表中插入记录库存 # 4、将小说类型(novel)的书的价格都增加5。 # 5、将名称为EmmaT的书的价格改为40&#xff0c;并将…

书生实战营第四期-基础岛第三关-浦语提示词工程实践

一、基础任务 任务要求&#xff1a;利用对提示词的精确设计&#xff0c;引导语言模型正确回答出“strawberry”中有几个字母“r”。 1.提示词设计 你是字符计数专家&#xff0c;能够准确回答关于文本中特定字符数量的问题。 - 技能&#xff1a; - &#x1f4ca; 分析文本&…

国药准字生发产品有哪些?这几款不错

头秃不知道怎么选的朋友们看这&#xff0c;基本上市面上火的育发精华我都用了个遍了&#xff0c;陆陆续续也花了有大几w了&#xff0c;都是真金白银总结出来的&#xff0c;所以必须要给掉发人分享一些真正好用的育发产品&#xff0c;大家可以根据自己实际情况来选择。 1. 露卡菲…

构建基于 DCGM-Exporter, Node exporter,PROMETHEUS 和 GRAFANA 构建算力监控系统

目录 引言工具作用概述DCGM-ExporterNode exporterPROMETHEUSGRAFANA小结 部署单容器DCGM-ExporterNode exporterPROMETHEUSGRAFANANode exporterDCGM-Exporter 多容器Node exporterDCGM-ExporterDocker Compose 参考 引言 本文的是适用对象&#xff0c;是希望通过完全基于Doc…