手撕code(1)—— 排序算法

news2024/11/16 13:42:41

文章目录

  • 前言
  • 1 冒泡排序
  • 2 选择排序
  • 3 插入排序
  • 4 快速排序
  • 5 归并排序
  • 6 堆排序
  • 7 希尔排序


前言

算法动画

时间复杂度分析
在这里插入图片描述

从小到大排序

1 冒泡排序

在这里插入图片描述

被动的将最大值送到最右边

1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

原地修改数组:

void bubbleSort(vector<int>& nums) {

	int len = nums.size();
	for (int i = 0; i < len - 1; ++i) {    // 外层只需n-1
		for (int j = 0; j < len - 1 - i; ++j) {
			if (nums[j] > nums[j + 1])    // 最大的放在数组最右
                swap(nums[j], nums[j + 1]);
		}
	}
}

优化:算是一种剪枝
假如从开始的第一对到结尾的最后一对,相邻的元素之间都没有发生交换的操作,这意味着右边的元素总是大于等于左边的元素,此时的数组已经是有序的了,我们无需再对剩余的元素重复比较下去了。

void bubbleSort2(vector<int>& nums) {

	int len = nums.size();
	bool flag = false;
	for (int i = 0; i < len - 1; ++i) {
		flag = false;
		for (int j = 0; j < len - 1 - i; ++j) {
			if (nums[j] > nums[j + 1]) { 
				flag = true;
				swap(nums[j], nums[j + 1]); 
			}
		}
		if (!flag)//说明没有交换,则表明[0,len-i-1]已经是有序的了
			break;
	}
}

2 选择排序

在这里插入图片描述
主动将最小值送到最左边

void selectSort(vector<int>& nums) {
	int len = nums.size();
	int minIndex = 0;
	for (int i = 0; i < len; ++i) {
		minIndex = i;
		for (int j = i + 1; j < len; ++j) {
			if (nums[j] < nums[minIndex]) minIndex = j;
		}
		swap(nums[i], nums[minIndex]);
	}
}

3 插入排序

在这里插入图片描述
与选择排序思路一致,从左到右排序

void insertionSort(vector<int>& nums) {
    int len = nums.size();

    for (int i = 1; i < len; ++i) {
        int n = i;
        while(n > 0){
            if(nums[n-1] > nums[n])
                swap(nums[n], nums[n-1]);
            else
                break;   // 左边的数组都是有序的了
            n--;
        }
    }
}

4 快速排序

时间复杂度O(N*log(N))

nums = [15,19,2,18,24,4,20]
选择一个区间,将最左边的元素15作为中间点元素,然后将数组分成两个区间:
小于等于15的元素放其左侧,大于15的元素放其右侧
[2, 4],[15],[19, 18, 24, 20]

然后将这两个区间[2, 4][19, 18, 24, 20]按照相同的步骤(选最左侧元素。。。)

退出条件:
如果区间长度为1,直接归位

双指针递归法

1、输入输出
void quickSort(vector<int>& nums, int left, int right)

2、退出条件
if(left > right) return;

3、单层逻辑
首先存储这个区间的leftright指针,找到最左边元素nums[left]

int front = left;
int last = right;
int key = nums[left];

然后根据key值放元素。
首先,从后往前走,选比key小的移到前面

// 直到选出一个不符合要求的
while (front < last && nums[last] > key)
	last--;
if (front < last)
	nums[front] = nums[last];
	front++;

然后,从前往后走, 将比比key大的移到后面

// 直到选出一个不符合要求的
while (front < last && nums[first] <= key)
	front++;
if (front < last)
	nums[last] = nums[first];
	last--;

最后,循环这两步

while(front < last){
	从后往前走
	从前往后走
}
nums[last] = key;

放完元素后进行递归,以key值的索引为两个区间的分界线

quickSort(nums, left, last - 1);
quickSort(nums, last + 1, right);

在这里插入图片描述
在这里插入图片描述
整合代码

// front 和 last 代表区间
void quickSort(vector<int>& nums, int front, int last) {
    if(front >= last) return;

    int left = front;
    int right = last;
    int key = nums[front];

    while(left != right){
        while(left != right && nums[right] > key) right--;
        if(left != right){
            nums[left] = nums[right];
            left++;
        }
        while(left != right && nums[left] < key) left++;
        if(left != right){
            nums[right] = nums[left];
            right--;
        }
    }
    nums[left] = key;

    quickSort(nums, front, right - 1);
    quickSort(nums, right + 1, last);
}

5 归并排序

在这里插入图片描述
申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

设定两个指针,最初位置分别为两个已经排序序列的起始位置;

比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

重复步骤 3 直到某一指针达到序列尾;

将另一序列剩下的所有元素直接复制到合并序列尾。

6 堆排序

在这里插入图片描述

7 希尔排序

在这里插入图片描述

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

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

相关文章

Vite+Vue+iClient for Leaflet引入并实现MapV/Eharts第三方可视化库示例

作者&#xff1a;gaogy 文章目录 背景一、使用Vite构建Vue3JavaScript项目二、搭建iClient for Leaflet开发环境三、第三方可视化库Echarts的使用四、第三方可视化库MapV的使用五、其他地图库 背景 最近很多小伙伴咨询关于基于Vue3框架搭建iClent开发环境并使用Echarts与MapV等…

OPEN AI角色插件通道开放接入支持各种细分领域对话场景模型一键接入AI 智能

相信还是有很多伙伴不了解OPEN AI平台 &#xff0c;这里在细说一下 大家知道ChatGPT, 或者百度文心一言 阿里通意千问 包括各种其他的AI 聊天或者画图&#xff0c;等应用层出不穷。 但是我们要自己实现自己 语言大模型&#xff0c;或者说是人工智能应用能不能。 有实力当然可…

C++小项目之文本编辑器mynote(1.0.0版本)

2023年5月19日&#xff0c;周五晚上&#xff1a; 今天晚上突然想写一个运行在命令行上的文本编辑器&#xff0c;因为平时写文本时老是要创建新的文本文件&#xff0c;觉得太麻烦了。捣鼓了一个晚上&#xff0c;才选出一个我觉得比较满意的。我把这个程序添加到了系统环境变量中…

C语言指针学习笔记

1-二维数组指针 int a[3][4]a代表二维数组首元素的地址&#xff0c;此首元素不是一个简单的整形元素&#xff0c;而是由4个整形元素组成的一维数组&#xff0c;因此a代表的是首行&#xff08;序号为0的行&#xff09;的起始地址。a1代表序号为1的行的起始地址。a指向a[0], …

一个月50场面试,跑的慢就抢在别人前面!

300万字&#xff01;全网最全大数据学习面试社区等你来&#xff01; 今天的主人公也是一个应届生新人拿到满意offer的案例。 下面是一些聊天记录和面经&#xff0c;这名同学做的非常好的一个点&#xff0c;他把个人项目中的所用到的技术栈和项目具体的业务流程图以及用到的技术…

2年再见面

我和张哥是在两年前吃过饭&#xff0c;那时候我是在大学城上班。 两年前&#xff0c;张哥在微信上跟我说话&#xff0c;说要来深圳找我&#xff0c;问我什么时间方便&#xff0c;请我吃个便饭。两年前&#xff0c;公众号还比较火热。有挺多人找我做事情&#xff0c;找我做事情之…

桥梁安全监测,智能化桥梁结构健康监测方案

桥梁是现代城市交通网络中不可或缺的组成部分&#xff0c;但由于长期受到自然环境和人为因素的影响&#xff0c;桥梁的安全问题一直备受关注。传统的桥梁检测方式主要是靠人力进行巡查&#xff0c;这种方式效率低下、成本高&#xff0c;而且难以全面掌握桥梁结构的真实情况。随…

回顾 | Let's Learn .NET-通过 Semantic Kernel .NET SDK 管理你的 OpenAI 项目

点击蓝字 关注我们 编辑&#xff1a;Alan Wang 排版&#xff1a;Rani Sun Lets Learn .NET 系列 “Lets Learn .NET” 是面向全球的 .NET 初学者学习系列&#xff0c;旨在通过不同语言&#xff0c;帮助不同地区的开发者掌握最新的 .NET 开发知识与技能。 在 ChatGPT 与 OpenAI…

从零玩转设计模式之简单工厂设计模式-jiandangonchangmoshi

title: 从零玩转设计模式之简单工厂设计模式 date: 2022-12-08 11:31:19.472 updated: 2022-12-11 23:03:34.805 url: https://www.yby6.com/archives/jiandangonchangmoshi categories: - 设计模式 tags: - 设计模式 简单工厂模式是一种创建型设计模式&#xff0c;用于创建单…

Docker安装MinIO教程

本章教程&#xff0c;主要介绍一下&#xff0c;如何在Linux用Docker安装MinIO。 MinIO是一个高性能、分布式对象存储系统&#xff0c;支持S3 API&#xff0c;适用于云原生环境。MinIO可以在标准硬件上运行&#xff0c;并且具有低延迟、高吞吐量、高可用性和可扩展性等优势。Min…

C语言两百行代码实现简易扫雷

文章目录 前言一.代码实现二.设计思路main()函数搭建框架reset ( )函数dis_play( )函数setmine( )函数player_move( )函数 前言 扫雷应该是我们接触到的第一个电脑游戏&#xff0c;用c语言实现扫雷对初学者来说是一个不错的锻炼 编写扫雷只需要用到数组、函数和生成随机数的知…

Java文件与IO流

首先我们要清楚什么是流&#xff0c;正如其名&#xff0c;很形象&#xff0c;流就是像水一样的东西&#xff0c;具有方向性&#xff0c;在java中 &#xff0c;流大概就是类 接下来&#xff0c;我们要对输入输出流有一个基本认识&#xff0c;什么是输入输出流呢&#xff1f; 输入…

漏斗分析、 python学习路径地图、数据科学技能书知识地图、数据安全治理解决方案、AIGC发展研究、经营的本质…| 本周精华...

▲点击上方卡片关注我&#xff0c;回复“8”&#xff0c;加入数据分析领地&#xff0c;一起学习数据分析&#xff0c;持续更新数据分析学习路径相关资料~&#xff08;精彩数据观点、学习资料、数据课程分享、读书会、分享会等你一起来乘风破浪~&#xff09;回复“小飞象”&…

【计算机组成原理】(四)原码补码的加减乘除

各种码的作用&#xff1a; 模运算的性质&#xff1a; -3&#xff08;-1&#xff09;*129 90*129 211*129 332*129 -15&#xff08;-2&#xff09;*129 我们发现等号右边都是9&#xff0c;相当于等号的左边的数除去12的余数都是9 那我们就说这几个等好左边的数&#xff0…

从零玩转设计模式之原型模式-yuanxingmoshi

title: 从零玩转设计模式之原型模式 date: 2022-12-11 20:05:35.488 updated: 2022-12-23 15:35:44.159 url: https://www.yby6.com/archives/yuanxingmoshi categories: - 设计模式 tags: - 设计模式 - 原型模式 什么是原型模式设计模式? 原型模式是一种软件设计模式&#…

【Rust 日报】2023-05-19 Bevy主分支添加了对WebGPU的支持

cascade-protocol Rust实现的 Cascade information reconciliation protocol for Quantum Key Distribution (QKD) 量子键分布&#xff1f;好像是密码学相关的。 隔行如隔山&#xff0c;小编也不懂这个具体是干啥的。感兴趣的同学可以前去研究。 https://github.com/gftea/casc…

SSR 应用与原 CSR 应用变更同步问题实践

在上一篇介绍《天猫汽车商详页的SSR改造实践》一文中提到过&#xff0c;为免影响线上应用&#xff0c;我们的一体化应用&#xff08;后面简称称 SSR 应用&#xff09;是在原 CSR 项目基础上另起的应用仓库。 背景 当商详业务有新需求迭代&#xff0c;CSR 仓库发生了变化&#x…

Java基础学习(18)反射、动态代理

Java基础学习 一、反射1.1 什么是反射1.2 获取class对象 二、综合练习2.1 保存信息2.2 文件的动态创建 三、动态代理3.1 什么是动态代理3.2 创建代理 一、反射 1.1 什么是反射 反射允许对封装类的字段&#xff0c;方法和构造函数的信息进行编程访问 个人理解&#xff1a; 就是…

【JVM】5. 本地方法接口和本地方法栈

文章目录 5.1. 什么是本地方法&#xff1f;5.2. 为什么使用Native Method&#xff1f;5.3. 本地方法栈 5.1. 什么是本地方法&#xff1f; 简单地讲&#xff0c;一个Native Method是一个Java调用非Java代码的接囗。一个Native Method是这样一个Java方法&#xff1a;该方法的实现…

【007】C++数据类型之原码、补码、反码

C数据类型之原码、补码、反码 引言一、原码、补码、反码的概述二、为什么要使用补码&#xff1f;三、对数据的存四、对数据的取总结 引言 &#x1f4a1; 作者简介&#xff1a;专注于C/C高性能程序设计和开发&#xff0c;理论与代码实践结合&#xff0c;让世界没有难学的技术。包…