八大排序——冒泡排序/归并排序

news2025/4/30 0:25:15

八大排序——冒泡排序/归并排序

一、冒泡排序

1.1 冒泡排序

1.2 冒泡排序优化

二、归并排序

1.1 归并排序(递归)

1.2 递归排序(非递归)


一、冒泡排序

1.1 冒泡排序

比较相邻的元素。如果第一个比第二个大,就交换它们两个。

void Bubble_Sort(int arr[], int len) // 定义冒泡排序函数,参数为数组和数组长度
{
    // 外层循环控制排序的总趟数,从0开始,到len-1结束
    for (int i = 0; i < len - 1; i++)
    {
        // 内层循环负责每一趟排序中的实际比较和交换操作
        // 从0开始,到len-i-1结束,因为每趟排序结束后,最大的元素会“冒泡”到最后,不需要再参与比较
        for (int j = 0; j + 1 < len - i; j++)
        {
            // 比较相邻的两个元素
            if (arr[j] > arr[j + 1])
            {
                // 如果左边的元素大于右边的元素,说明它们的顺序错误,需要交换
                int tmp = arr[j]; // 使用临时变量tmp来保存arr[j]的值
                arr[j] = arr[j + 1]; // 将arr[j+1]的值赋给arr[j]
                arr[j + 1] = tmp; // 将tmp的值赋给arr[j+1],完成交换
            }
        }
    }
}

1.2 冒泡排序优化

数据要是已经默认有序了,则后续的趟数就不排序了

问题:怎么得出已有数据是否有序?

解决方法:跑一趟,跑完了都没有一次数据交换发生,也就是说都是左边值小于右边值

void Bubble_Sort(int arr[], int len)
{
	bool tag = true;
	for (int i = 0; i < len - 1; i++)//控制趟数
	{
		//每一趟开始时把tag重新置位真
		tag = true;
		for (int j = 0; j + 1 < len - i; j++)//j指向比较一对数据中左边的值,右边用j+1
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j ] = arr[j+1];
				arr[j + 1] = tmp;
				tag = false;
			}
		}
		if (tag)//tag还是真,那么就默认递增有序,直接退出
		{
			return;
		}
	}
}

时间复杂度位n^2  空间复杂度1

稳定值:稳定 俩个俩个比

二、归并排序

将长度为n的待排序序列,看作n个长度为1的有序组,然后进行合并,合并成n/2个长度为2的有序组,然后接着合并,直到所有的数据都合并到同一个组为止

1.1 归并排序(递归)

#include <stdio.h> // 引入标准输入输出头文件,用于使用 printf 和 scanf 函数
#include <stdlib.h> // 引入标准库头文件,用于使用内存分配函数 malloc 和 exit 函数
#include <string.h> // 引入字符串操作头文件,用于使用 memset 函数

// 函数声明,用于在主函数之后定义,显示排序后的数组
void Show(int arr[], int len);

// 合并两个有序子数组到临时数组 brr 中,然后再复制回原数组 arr
void Merge(int arr[], int len, int left, int mid, int right, int* brr) {
    int i = left; // 初始化指针 i 指向左边子数组的起始位置
    int j = mid + 1; // 初始化指针 j 指向右边子数组的起始位置
    int k = left; // 初始化指针 k 指向临时数组 brr 的起始位置
    while (i <= mid && j <= right) { // 当两个子数组中都有元素时
        if (arr[i] <= arr[j]) { // 如果左边的元素小于等于右边的元素
            brr[k] = arr[i]; // 将左边的元素放入临时数组 brr
            i++; // 左边子数组的指针后移
            k++; // 临时数组的指针后移
        } else { // 如果左边的元素大于右边的元素
            brr[k] = arr[j]; // 将右边的元素放入临时数组 brr
            j++; // 右边子数组的指针后移
            k++; // 临时数组的指针后移
        }
    }
    while (j <= right) { // 复制右边子数组中剩余的元素
        brr[k++] = arr[j++];
    }
    while (i <= mid) { // 复制左边子数组中剩余的元素
        brr[k++] = arr[i++];
    }
    for (int i = left; i <= right; i++) { // 将合并后的有序数组复制回原数组 arr
        arr[i] = brr[i];
    }
}

// 递归地将数组分成两半,并对每一半进行排序,然后合并
void Divide(int arr[], int len, int left, int right, int* brr) {
    if (left < right) { // 如果左边界小于右边界,则继续递归
        int mid = (left + right) / 2; // 计算中间索引
        Divide(arr, len, left, mid, brr); // 对左半部分递归调用 Divide 函数
        Divide(arr, len, mid + 1, right, brr); // 对右半部分递归调用 Divide 函数
        Merge(arr, len, left, mid, right, brr); // 合并两个有序子数组
    }
}

// 归并排序的入口函数
void Merge_Sort(int arr[], int len) {
    int* brr = (int*)malloc(len * sizeof(int)); // 动态分配一个临时数组 brr,用于合并时存放数据
    if (brr == NULL) { // 如果内存分配失败
        fprintf(stderr, "Memory allocation failed\n"); // 打印错误信息到标准错误输出
        exit(EXIT_FAILURE); // 退出程序
    }
    Divide(arr, len, 0, len - 1, brr); // 从数组的起始索引到结束索引进行递归排序
    free(brr); // 释放临时数组 brr 的内存
}

// 显示数组内容的函数
void Show(int arr[], int len) {
    for (int i = 0; i < len; i++) { // 遍历数组
        printf("%d ", arr[i]); // 打印数组的每个元素
    }
    printf("\n"); // 打印换行符
}

int main() {
    int arr[] = {122, 222, 11, 357, 333, 12, 111, 789, 654, 356}; // 初始化一个待排序的数组
    int len = sizeof(arr) / sizeof(arr[0]); // 计算数组的长度
    Merge_Sort(arr, len); // 调用归并排序函数对数组进行排序
    Show(arr, len); // 显示排序后的数组
    return 0; // 程序正常结束,返回 0
}

1.2 递归排序(非递归)

#include <stdio.h>
#include <stdlib.h>

// 函数声明,用于显示排序后的数组
void Show(int arr[], int len);

// 合并两个有序子数组到临时数组brr中,然后再复制回原数组arr
void Merge(int arr[], int len, int left, int mid, int right, int* brr)
{
    int i = left;
    int j = mid + 1;
    int k = left;
    while (i <= mid && j <= right)
    {
        if (arr[i] <= arr[j])
        {
            brr[k] = arr[i];
            i++;
            k++;
        }
        else
        {
            brr[k] = arr[j];
            j++;
            k++;
        }
    }
    while (j <= right)
    {
        brr[k++] = arr[j++];
    }
    while (i <= mid)
    {
        brr[k++] = arr[i++];
    }
    for (int i = left; i <= right; i++)
    {
        arr[i] = brr[i];
    }
}

// 非递归的分治函数
//gap是当前子数组的长度
void Merge_No_Recursion(int arr[], int len, int gap, int* brr)
{
    int left1 = 0;
    int right1 = left1 + gap - 1;
    int left2 = right1 + 1;
    int right2 = left2 + gap - 1 < len ? left2 + gap - 1 : len - 1;
    int k = 0;

    while (left2 < len)
    {
        int i = left1;
        int j = left2;

        while (i <= right1 && j <= right2)
        {
            if (arr[i] <= arr[j])
            {
                brr[k] = arr[i];
                i++;
                k++;
            }
            else
            {
                brr[k] = arr[j];
                j++;
                k++;
            }
        }
        while (j <= right2)
        {
            brr[k++] = arr[j++];
        }
        while (i <= right1)
        {
            brr[k++] = arr[i++];
        }

        left1 = right2 + 1;
        right1 = left1 + gap - 1;
        left2 = right1 + 1;
        right2 = left2 + gap - 1 < len ? left2 + gap - 1 : len - 1;
    }

    while (left1 < len)
    {
        brr[k++] = arr[left1++];
    }

    for (int i = 0; i < len; i++)
    {
        arr[i] = brr[i];
    }
}

// 归并排序的非递归版本
void Merge_Sort_No_Recursion(int arr[], int len)
{
    int* brr = (int*)malloc(len * sizeof(int));
    if (brr == NULL)
        exit(EXIT_FAILURE);

    for (int gap = 1; gap < len; gap *= 2 )
    {
        Merge_No_Recursion(arr, len, gap, brr);
    }
    free(brr);
}

// 显示数组的函数
void Show(int arr[], int len) {
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[] = { 120000, 230000, -100, 195, 71, 89, 42, 8, 902, 894, 194, 80, 194, 128, 90, 18, 490, 18, 409, 180, 95, 12, 489, 404 };
    int len = sizeof(arr) / sizeof(arr[0]);
    Merge_Sort_No_Recursion(arr, len);
    Show(arr, len);
    return 0;
}

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

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

相关文章

银发科技:AI健康小屋如何破解老龄化困局

随着全球人口老龄化程度的不断加深&#xff0c;如何保障老年人的健康、提升他们的生活质量&#xff0c;成为了社会各界关注的焦点。 在这场应对老龄化挑战的战役中&#xff0c;智绅科技顺势而生&#xff0c;七彩喜智慧养老系统构筑居家养老安全网。 而AI健康小屋作为一项创新…

命令行指引的尝试

效果 步骤 首先初始化一个空的项目&#xff0c;然后安装一些依赖 npm init -y npm install inquirer execa chalk ora至于这些依赖是干嘛的&#xff0c;如下图所示&#xff1a; 然后再 package.json 中补充一个 bin 然后再根目录下新建一个 index.js , 其中的内容如下 #!/…

【Dify系列教程重置精品版】第1课 相关概念介绍

文章目录 一、Dify是什么二、Dify有什么用三、如何玩转Dify?从螺丝刀到机甲战士的进阶指南官方网站:https://dify.ai github地址:https://github.com/langgenius/dify 一、Dify是什么 Dify(D​​efine + ​​I​​mplement + ​​F​​or ​​Y​​ou)。这是一款开源的大…

leetcode0106. 从中序与后序遍历序列构造二叉树-medium

1 题目&#xff1a;从中序与后序遍历序列构造二叉树 官方标定难度&#xff1a;中 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入…

Spring Boot默认缓存管理

Spring框架支持透明地向应用程序添加缓存&#xff0c;以及对缓存进行管理&#xff0c;其管理缓存的核心是将缓存应用于操作数据的方法&#xff0c;从而减少操作数据的执行次数&#xff0c;同时不会对程序本身造成任何干扰。Spring Boot继承了Spring框架的缓存管理功能&#xff…

XYNU2024信安杯-REVERSE(复现)

前言 记录记录 1.Can_you_find_me? 签到题&#xff0c;秒了 2.ea_re 快速定位 int __cdecl main_0(int argc, const char **argv, const char **envp) {int v4; // [esp0h] [ebp-1A0h]const char **v5; // [esp4h] [ebp-19Ch]const char **v6; // [esp8h] [ebp-198h]char v7;…

MySQL的MVCC【学习笔记】

MVCC 事务的隔离级别分为四种&#xff0c;其中Read Committed和Repeatable Read隔离级别&#xff0c;部分实现就是通过MVCC&#xff08;Multi-Version Concurrency Control&#xff0c;多版本并发控制&#xff09; 版本链 版本链是通过undo日志实现的&#xff0c; 事务每次修改…

达梦数据库压力测试报错超出全局hash join空间,适当增加HJ_BUF_GLOBAL_SIZE解决

1.名词解释&#xff1a;达梦数据库中的HJ_BUF_GLOBAL_SIZE是所有哈希连接操作可用的最大哈希缓冲区大小&#xff0c;单位为兆字节&#xff08;MB&#xff09; 2.达梦压测报错&#xff1a; 3.找到达梦数据库安装文件 4.压力测试脚本 import http.client import multiprocessi…

Oracle--SQL性能优化与提升策略

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、导致性能问题的内在原因 系统性能问题的底层原因主要有三个方面&#xff1a; CPU占用率过高导致资源争用和等待内存使用率过高导致内存不足并需…

六个能够白嫖学习资料的网站

一、咖喱君的资源库 地址&#xff1a;https://flowus.cn/galijun/share/de0f6d2f-df17-4075-86ed-ebead0394a77 这是一个学习资料/学习网站分享平台&#xff0c;包含了英语、法语、德语、韩语、日语、泰语等几十种外国语言的学习资料及平台&#xff0c;这个网站的优势就是外语…

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤

以下是在 IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤&#xff1a; 步骤 1&#xff1a;创建 Maven Web 项目 新建项目 File -> New -> Project → 选择 Maven → 勾选 Create from archetype → 选择 maven-archetype-webapp。输入 GroupId&#xff08;如 com.examp…

手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段

手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段 --本地AI电话机器人 前言 书接上一篇&#xff0c;《手机打电话通话时如何向对方播放录制的IVR引导词声音》中介绍了【蓝牙电话SDK示例App】可以实现手机app在电话通话过程中插播预先录制的开场白等语音片段的功能。…

SpringCloud——负载均衡

一.负载均衡 1.问题提出 上一篇文章写了服务注册和服务发现的相关内容。这里再提出一个新问题&#xff0c;如果我给一个服务开了多个端口&#xff0c;这几个端口都可以访问服务。 例如&#xff0c;在上一篇文章的基础上&#xff0c;我又新开了9091和9092端口&#xff0c;现在…

string的基本使用

string的模拟实现 string的基本用法string的遍历&#xff08;三种方式&#xff09;&#xff1a;关于auto&#xff08;自动推导&#xff09;:范围for: 迭代器普通迭代器(可读可改&#xff09;const迭代器&#xff08;可读不可改&#xff09; string细小知识点string的常见接口引…

深入解析Mlivus Cloud核心架构:rootcoord组件的最佳实践与调优指南

作为大禹智库的向量数据库高级研究员,同时也是《向量数据库指南》的作者,我在过去30年的向量数据库和AI应用实战中见证了这项技术的演进与革新。今天,我将以专业视角为您深入剖析Mlivus Cloud的核心组件之一——rootcoord,这个组件在系统架构中扮演着至关重要的角色。如果您…

Python常用的第三方模块之【pymysql库】操作数据库

pymysql是在Python3.x版本中用于连接MySQL服务器的一个实现库&#xff0c;Python2中则是使用musqldb。 PyMySQL 是一个纯 Python 实现的 MySQL 客户端库&#xff0c;它允许我们直接在 Python 中执行 SQL 语句并与 MySQL 数据库进行交互。下面我们将详细介绍如何使用 PyMySQL 进…

【Python数据分析】Pandas模块之pd.concat 函数

💭 写在前面:合并多个数据框,收集各种数据,并将其合并为一个数据框进行分析。本章我们介绍 Pandas 库中数据框合并的函数 —— concat。 0x00 引入:数据框的合并操作 合并多个数据框:收集各种数据,并将其合并为一个数据框进行分析。 下面介绍一些常用的 Pandas 库中数…

C# 综合示例 库存管理系统7 主界面(FormMain)

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 图99A-22 主界面窗口设计 主界面是多文档界面容器,需要将窗体属性IsMdiContainer设置为True。关于多文档界面编程请参看教程第7.12节《多文档界面》。 主界面并不提…

系统思考:看清问题背后的结构

组织的挑战&#xff0c;往往不是因为不努力&#xff0c;而是“看不清” 结束了为期两天系统思考课程的第一天&#xff0c;被学员的全情投入深深打动。我们用系统结构图&#xff0c;一步步揭示那些表面看起来“习以为常”的问题&#xff1a; 什么原因跨部门协作总是磕磕绊绊&am…

Langchain_Agent+数据库

本处使用Agent数据库&#xff0c;可以直接执行SQL语句。可以多次循环查询问题 前文通过chain去联系数据库并进行操作&#xff1b; 通过链的不断内嵌组合&#xff0c;生成SQL在执行SQL再返回。 初始化 import os from operator import itemgetterimport bs4 from langchain.ch…