数据结构与算法-选择冒泡快排

news2024/9/17 7:20:21

    一:选择排序

    场景:找出一个班上身高最高的人你会怎么找?A B C D A B

选择排序的思路和插入排序非常相似,也分已排序和未排序区间。但选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾。但是不像插入排序会移动数组 选择排序会每次进行交换,如以下例子:     

4 5 6 3 2 1

第一次:    1 5 6 3 2 4

第二次:    1 2 6 3 5 4

1.时间复杂度:O(N^2)

2.空间复杂度:O(n)

3.交换次数

4.稳定性:不稳定

   二:冒泡排序

        核心思路:冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。一次冒泡会让至少一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作。

        举例说明:4 5 6 3 2 1,从小到大排序。 1 2 3 4 5 6

进行排序:什么样的情况下不做任何交换了呢,那就是所有的数都在它应该在的位置;O(n)

1.时间复杂度:O(n^2)

2.空间复杂度:O(n)

3.交换次数:挺大的

4.稳定性:稳定

package Sort2;

import java.util.Arrays;

/**
 * 冒泡排序
 */

public class BubbleSort {

	public static void main(String[] args) {

		int data[] = { 4, 5, 6, 3, 2, 1 };
		int n = data.length;

		//n-1:这里是因为判断两个数是只比较一次 例如: 1  2   比较次数只会比一次
		for (int i = 0; i < n - 1; i++) {	//排序的次数
			//优化:如果所有的数都排好了,不需要交换了,就不需要冒泡了,所以直接退出
			boolean flag = false;
			// n-1-i:要减掉i是因为每次冒泡排序都会将后面的值确定,所以i就是后面已经排好的数字,所以就不需要再比较了,所以得减掉
			for (int j = 0; j < n - 1 - i; j++) {	//具体冒泡 n - 1 - i,6,5,4,3,2,1
				if (data[j] > data[j + 1]) {
					//交换
					int temp = data[j];	//用了第三个变量,不用第三个变量
					data[j] = data[j + 1];
					data[j + 1] = temp;
					flag = true;

					//异或实现
//					data[j] = data[j] ^ data[j+1];
//					data[j+1] = data[j] ^ data[j+1];
//					data[j] = data[j] ^ data[j+1];
				}
			}
			if(!flag) break;
		}
		System.out.println(Arrays.toString(data));
	}
}
/**
 * 下面是交换的时候如果不用第三方变量存储的话如何交换
 */
// a:2 b:3
// 3 2 => a:3 b:2
// 用加减
//a = a + b => a = 3+2 =5;
//b = a - b => b = 5-3 =2;
//a = a - b => a = 5-2 =3;
   2.1 如何进行简单的优化:

                1.  在交换的时候会需要第三方变量,会占空间,所以可以用异或交换。

                2. 当排好序了就不需要继续循环了,所以加flag作为标签。

       2.2 如何实现异或交换?

        异或操作可以实现交换两个数字的值的原因是因为异或操作具有以下几个性质:

  1. 任何数和0异或的结果仍然是这个数本身:a ^ 0 = a
  2. 任何数和自身异或的结果是0:a ^ a = 0
  3. 异或操作满足交换律:a ^ b = b ^ a 利用这些性质,我们可以通过异或操作实现交换两个数字的值,具体步骤如下: 假设有两个变量a和b,它们的初始值分别为a0和b0。
  4. 第一步:通过将a与b异或,将结果保存在a中:a = a ^ b。 此时,a的值为a0 ^ b0,b的值保持不变。
  5. 第二步:再将a与b异或,将结果保存在b中:b = a ^ b。 在这一步中,我们可以将上一步得到的a的值(a0 ^ b0)再与b0异或,得到的结果就是a0,即原始的a的值。 同时,由于异或操作满足交换律,所以b = (a0 ^ b0) ^ b0 = a0 ^ (b0 ^ b0) = a0 ^ 0 = a0。 此时,a的值保持不变,b的值变为a0。
  6. 第三步:最后将a与b异或,将结果保存在a中:a = a ^ b。 在这一步中,我们将上一步得到的a的值a0 ^ b0与上一步得到的b的值(a0)异或,得到的结果就是b0。
public class SwapNumbers {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        
        System.out.println("交换前:");
        System.out.println("a = " + a);
        System.out.println("b = " + b);
        
        // 使用异或操作交换a和b的值
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        
        System.out.println("交换后:");
        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }
}

        三: 快速排序

45 28 80 90 50 16 100 10

基准数:一般就是取要排序序列的第一个。

第一次排序基准数:45

从后面往前找到比基准数小的数进行对换: 10 28 80 90 50 16 100 45

从前面往后面找比基准数大的进行对换: 10 28 45 90 50 16 100 80    

   10 28 16 90 50 45 100 80  

   10 28 16 45 50 90 100 80

以基准数分为3部分,左边的比之小,右边比之大:

{10 28 16} 45 {50 90 100 80}

到此第一次以45位基准数的排序完成。

1.时间复杂度:nlogn 最坏的情况就是O(n^2)

2.空间复杂度:O(n)

3.稳定性:不稳定

4.快排和归并的对比:

(1)归并排序的处理过程是由下到上的,先处理子问题,然后再合并。

(2)快排其实就是从上到下,先分区,在处理子问题,不用合并。 其优化就是优化基准数,提供一个取三个数中间的思路.

package Sort2;

public class QuiklySort {

	public static void qSort(int data[], int left, int right) {

		int base = data[left]; // 就是我们的基准数,取序列的第一个,不能用data[0]
		int ll = left; // 表示的是从左边找的位置
		int rr = right; // 表示从右边开始找的位置
		while (ll < rr) {
			// 从后面往前找比基准数小的数
			while (ll < rr && data[rr] >= base) {
				rr--;
			}
			//这里有个小技巧,如果ll < rr为true,说明 data[rr] >= base = false,就找到比基准数小的,就要交换
			if (ll < rr) { // 表示是找到有比之大的
				int temp = data[rr];
				data[rr] = data[ll];
				data[ll] = temp;
				ll++;
			}
			// 从前面往后找比基准数大的数
			while (ll < rr && data[ll] <= base) {
				ll++;
			}
			if (ll < rr) {
				int temp = data[rr];
				data[rr] = data[ll];
				data[ll] = temp;
				rr--;
			}
		}
		// 肯定是递归 分成了三部分,左右继续快排,注意要加条件不然递归就栈溢出了
		//ll:循环终止时为基准数在最中间,然后将ll左右两部分继续递归
		if (left < ll)
			qSort(data, left, ll - 1);
		if (ll < right)
			qSort(data, ll + 1, right);

	}
}

        各种排序比较:

这么多种排序算法我们究竟应该怎么选择呢?

1.分析场景:稳定还是不稳定

2.数据量:数据量小的时候选什么?比如就50个数,优先选插入(5000*5000=25000000)

3.分析空间: 综上所述,没有一个固定的排序算法,都是要根据情况分析的。但是如果你不会分析的情况下 选择归并或者快排。

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

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

相关文章

浅谈硬件连通性测试方法有哪些

硬件连通性测试是一种用于验证硬件设备之间连接的稳定性和可靠性的测试过程。那么&#xff0c;硬件连通性测试方法有哪些呢?下面&#xff0c;就来看看具体介绍吧! 1、电气测试&#xff1a;电气测试用于检查硬件设备之间的电源和信号连接。这包括使用万用表或示波器测量电压、电…

Java开发之Redis(面试篇 持续更新)

文章目录 前言一、redis使用场景1. 知识分布2. 缓存穿透① 问题引入② 举例说明③ 解决方案④ 实战面试 3. 缓存击穿① 问题引入② 举例说明③ 解决方案④ 实战面试 4. 缓存雪崩① 问题引入② 举例说明③ 解决方案④ 实战面试 5. 缓存-双写一致性① 问题引入② 举例说明③ 解决…

面试设计模式-责任链模式

一 责任链模式 1.1 概述 在进行请假申请&#xff0c;财务报销申请&#xff0c;需要走部门领导审批&#xff0c;技术总监审批&#xff0c;大领导审批等判断环节。存在请求方和接收方耦合性太强&#xff0c;代码会比较臃肿&#xff0c;不利于扩展和维护。 1.2 责任链模式 针对…

uboot命令解析流程

uboot命令解析: (1)bootdelay没有打断,跑的是autoboot_command abortboot —>run_command_list (bootcmd) (2)否则走的cli_loop cli_loop –>cli_simple_loop ----> cli_readline —>run_command_repeatable -----> &#xff08;解析命令 匹配命令 运行命令 ) …

lv3 嵌入式开发-8 linux shell脚本函数

目录 1 函数的定义 2 函数的调用 3 变量的作用域 4 练习 1 函数的定义 基本语法&#xff1a; function name() {statements[return value] }function是 Shell 中的关键字&#xff0c;专门用来定义函数&#xff1b; name是函数名&#xff1b; statements是函数要执行…

java八股文面试[数据库]——自适应哈希索引

自适应Hash索引&#xff08;Adatptive Hash Index&#xff0c;内部简称AHI&#xff09;是InnoDB的三大特性之一&#xff0c;还有两个是 Buffer Pool简称BP、双写缓冲区&#xff08;Doublewrite Buffer&#xff09;。 1、自适应即我们不需要自己处理&#xff0c;当InnoDB引擎根…

FOXBORO FBM232 P0926GW 自动化控制模块

Foxboro FBM232 P0926GW 是 Foxboro&#xff08;福克斯博罗&#xff09;自动化控制系统的一部分&#xff0c;通常用于监测和控制工业过程。以下是关于这种类型的自动化控制模块可能具有的一些常见功能&#xff1a; 数字输入通道&#xff1a; FBM232 P0926GW 控制模块通常具有多…

2、在Windows 10中安装和配置 PostgreSQL 15.4

一、PostgreSQL 安装前简介 PostgreSQL&#xff08;通常简称为PG SQL&#xff09;是一个强大、开源的关系型数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;它具有广泛的功能和可扩展性&#xff0c;被广泛用于企业和开发项目中,PostgreSQL 具有如下一些关键特点&…

VUE3+TS项目无法找到模块“../version/version.js”的声明文件

问题描述 在导入 ../version/version.js 文件时&#xff0c;提示无法找到模块 解决方法 将version.js改为version.ts可以正常导入 注意&#xff0c;因为version.js是我自己写的模块&#xff0c;我可以直接该没有关系&#xff0c;但是如果是引入的其他的第三方包&#xff0c…

Windows系统的桌面显示信息工具___BGInfo使用

一、BGInfo简介 BGInfo(桌面显示信息工具)是微软开发的用于在Windows系统中实现将Windows系统信息【如:当前用户名、CPU、操作系统版本、IP地址、硬盘等】或自定的内容显示在桌面壁纸上的操作工具,用户可以根据自己的需要定制属于自己的桌面内容(特别是对应企业来说通过域…

原理之Thread与Runnable的关系

原理之Thread与Runnable的关系 附录 课程 附录 1.Thread和Runnable的关系

深入实现 MyBatis 底层机制的任务阶段4 - 开发 Mapper 接口和 Mapper.xml

&#x1f600;前言 在我们的自定义 MyBatis 底层机制实现过程中&#xff0c;我们已经深入研究了多个任务阶段&#xff0c;包括配置文件的读取、数据库连接的建立、执行器的编写&#xff0c;以及 SqlSession 的封装。每个任务阶段都为我们揭示了 MyBatis 内部工作原理的一部分&a…

机器学习算法基础--批量随机梯度下降法回归法

目录 1.算法流程简介 2.算法核心代码 3.算法效果展示 1.算法流程简介 """ 本节算法是梯度下降方法的小批量随机梯度下降法,算法的思路是从数中随机取出n个数据进行数梯度下降,再进行相应的迭代, 最后能够获得一个效果不错的回归方程/最优解. 算法的公式就不…

lv3 嵌入式开发-9 linux TFTP服务器搭建及使用

目录 1 TFTP服务器的介绍 2 TFTP文件传输的特点 3 TFTP服务器的适用场景 4 配置介绍 4.1 配置步骤 4.2 使用 5 常见错误 1 TFTP服务器的介绍 TFTP&#xff08;Trivial File Transfer Protocol&#xff09;即简单文件传输协议 是TCP/IP协议族中的一个用来在客户机与服务器…

9.3.3网络原理(网络层IP)

一.报文: 1.4位版本号:IPv4和IPv6(其它可能是实验室版本). 2.4位首部长度:和TCP一样,可变长,带选项,单位是4字节. 3.8位服务类型 4.16位总长度:IP报头 IP载荷 传输层是不知道载荷长度的,需要网络层来计算. IP报文 - IP报头 IP载荷 TCP报文 TCP载荷 IP载荷(TCP报文) …

解决方案|电子签加速证券业“数字革命”

电子签在各行各业中的快速普及已成为近年来的新趋势。与此同时&#xff0c;电子签也在证券行业中掀起一场数字化转型的新“革命”。 2020年10月&#xff0c; 中基协《私募投资基金电子合同业务管理办法&#xff08;试行&#xff09;&#xff08;征求意见稿&#xff09;》明确了…

《代码随想录》刷题笔记——链表篇【java实现】

链表节点定义 public class ListNode {// 结点的值int val;// 下一个结点ListNode next;// 节点的构造函数(无参)public ListNode() {}// 节点的构造函数(有一个参数)public ListNode(int val) {this.val val;}// 节点的构造函数(有两个参数)public ListNode(int val, ListNo…

【80天学习完《深入理解计算机系统》】第十四天 复习第三章

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

层次分析法(matlab实现)

1.层次分析法&#xff08;AHP&#xff09; 在决策理论中&#xff0c;层次分析法是一种以数学和心理学为基础&#xff0c;组织和分析复杂决策的结构化技术&#xff0c;它代表了一种量化决策标准权重的准确方法&#xff0c;通过成对比较&#xff0c;利用个别专家的经验来估计因素…

MySQL5.7慢查询实践

总结 获取慢查询SQL 已经执行完的SQL&#xff0c;检查慢查询日志&#xff0c;日志中有执行慢的SQL正在执行中的SQL&#xff0c;show proccesslist;&#xff0c;结果中有执行慢的SQL 慢查询日志关键参数 名称解释Query_time查询消耗时间Time慢查询发生时间 分析慢查询SQL e…