数据结构的归并排序(c语言版)

 

一.归并排序的基本概念

1.基本概念

归并排序是一种高效的排序算法,它采用了分治的思想。它的基本过程如下:

  1. 将待排序的数组分割成两个子数组,直到子数组只有一个元素为止。
  2. 然后将这些子数组两两归并,得到有序的子数组。
  3. 不断重复第二步,直到最终得到有序的整个数组。

2.核心思想

归并排序的核心是"分而治之"的思想。通过不断地将数组拆分成更小的子数组,直至子数组只有一个元素,然后再将这些有序的子数组合并起来,最终得到一个有序的数组。

与简单的冒泡排序或选择排序相比,归并排序的时间复杂度为O(nlogn),这使它能够高效地处理大规模的数据集。虽然它需要O(n)的额外空间来存储中间结果,但其优秀的时间复杂度使其成为处理大数据量排序问题的首选算法之一。

总的来说,归并排序是一种强大而高效的排序算法,它体现了分治策略在算法设计中的重要应用。如果您有任何其他问题,欢迎随时向我咨询。

3.优点

优点:

  1. 时间复杂度稳定:归并排序的时间复杂度为O(nlogn),不管输入数据的初始状态如何,时间复杂度都是稳定的。这使它能够高效处理大规模数据。

  2. 稳定排序:归并排序是一种稳定的排序算法,也就是说,当两个相等的元素出现时,它们在输出序列中的相对顺序与输入序列中的相对顺序一致。这对某些应用场景很重要。

  3. 并行计算友好:归并排序的"分而治之"特性使得它很容易并行化,在多核处理器上可以获得很好的性能提升。

4.缺点

缺点:

  1. 需要额外空间:归并排序需要额外的内存空间来存储中间结果,空间复杂度为O(n)。这可能成为一个瓶颈,尤其是在内存受限的环境中。

  2. 数据交换频繁:归并排序需要频繁地将数据从输入数组复制到临时数组,这在某些情况下可能会降低性能。

  3. 无法就地排序:归并排序无法在原数组上就地排序,需要使用额外的空间。这对于某些内存受限的场景可能是个问题。

二.归并排序的功能

归并排序的基本功能就是对一组数据进行排序。具体来说,它可以实现以下几个功能:

  1. 将无序的数组或列表排序为有序的数组或列表。归并排序可以将任意大小的输入集合有效地排序,包括大型数据集。

  2. 保持数据的相对位置关系。如果输入数据中存在相等的元素,归并排序会保留它们原有的相对顺序,这在某些应用场景中很重要。

  3. 支持并行计算。由于归并排序的"分而治之"特性,它非常适合在多核处理器上并行执行,从而获得大幅的性能提升。

  4. 可以用于外部排序。当数据量太大无法一次性装入内存时,可以采用外部排序的方式,先将数据划分成多个小块,然后使用归并排序分别对这些小块进行排序,最后合并这些有序块。

  5. 可以作为其他算法的子过程。归并排序常被用作其他算法的核心步骤,比如快速排序、外部排序等。

归并排序是一种通用且高效的排序算法,它在各种规模和类型的数据排序中都有重要应用。它的功能十分强大,能够满足绝大多数排序需求。

三.归并排序的代码实现

1.合并两个有序数组

  1. 定义三个索引变量 ijk,分别用来遍历左数组、右数组和目标数组。
  2. 使用 while 循环比较左右数组当前元素的大小,将较小的元素依次添加到目标数组中。
  3. 当左数组或右数组中还有剩余元素时,将它们依次添加到目标数组的末尾。
// 合并两个有序数组
void merge(int arr[], int left[], int left_size, int right[], int right_size, int size) {
    int i = 0, j = 0, k = 0;
    while (i < left_size && j < right_size) {
        if (left[i] <= right[j]) {
            arr[k++] = left[i++];
        } else {
            arr[k++] = right[j++];
        }
    }
    while (i < left_size) {
        arr[k++] = left[i++];
    }
    while (j < right_size) {
        arr[k++] = right[j++];
    }
}

2.递归实现

  1. 首先,它检查数组大小是否小于等于 1,如果是,则直接返回,因为单个元素已经是有序的了。

  2. 接下来,它将数组分为两个子数组:左子数组 left 和右子数组 right。计算中点 mid 作为分割点,将原数组 arr 分为左右两部分。

  3. 然后,它将原数组 arr 的元素复制到左右两个临时数组 left 和 right 中。

  4. 递归地对左右两个子数组分别调用 merge_sort 函数,对它们进行排序。

  5. 最后,它调用 merge 函数,将已经排序的左右子数组合并回原数组 arr

// 递归实现归并排序
void merge_sort(int arr[], int size) {
if (size <= 1) {
return;
}
int mid = size / 2;
int left[mid];
int right[size - mid];
for (int i = 0; i < mid; i++) {
left[i] = arr[i];
}
for (int i = mid; i < size; i++) {
right[i - mid] = arr[i];
}
merge_sort(left, mid);
merge_sort(right, size - mid);
merge(arr, left, mid, right, size - mid);
}

3.非递归实现

  1. 首先,它申请了一个临时数组 temp,用来存储合并后的有序子数组。这是非递归实现所需要的额外空间。

  2. 然后,它使用一个外层循环来控制子数组的宽度 width。初始值为 1,每次翻倍,直到 width 大于等于数组大小 size

  3. 内层循环遍历数组,每次处理长度为 2 * width 的两个相邻子数组。

  4. 对于每个子数组对,它计算左子数组的长度 left_size 为 width,右子数组的长度 right_size 可能会小于 width (当剩余元素不足 width 时)。

  5. 然后调用 merge 函数,将左右两个有序子数组合并为一个有序子数组,存储在原数组 arr 中。

  6. 最后,释放临时数组 temp 占用的动态内存。

// 非递归实现归并排序
void iterative_merge_sort(int arr[], int size) {
    int *temp = (int *)malloc(size * sizeof(int));
    if (!temp) {
        printf("Memory allocation failed.\n");
        return;
    }

    for (int width = 1; width < size; width *= 2) {
        for (int i = 0; i < size; i += 2 * width) {
            int left_size = width;
            int right_size = (i + 2 * width < size) ? width : size - i - width;
            merge(arr + i, arr + i, left_size, arr + i + width, right_size, size);
        }
    }

    free(temp);
}

四.归并排序的源代码

1.递归

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

// 合并两个有序数组
void merge(int arr[], int left[], int left_size, int right[], int right_size) {
    int i = 0, j = 0, k = 0;
    while (i < left_size && j < right_size) {
        if (left[i] <= right[j]) {
            arr[k++] = left[i++];
        } else {
            arr[k++] = right[j++];
        }
    }
    while (i < left_size) {
        arr[k++] = left[i++];
    }
    while (j < right_size) {
        arr[k++] = right[j++];
    }
}

// 递归实现归并排序
void merge_sort(int arr[], int size) {
    if (size <= 1) {
        return;
    }
    int mid = size / 2;
    int left[mid];
    int right[size - mid];
    for (int i = 0; i < mid; i++) {
        left[i] = arr[i];
    }
    for (int i = mid; i < size; i++) {
        right[i - mid] = arr[i];
    }
    merge_sort(left, mid);
    merge_sort(right, size - mid);
    merge(arr, left, mid, right, size - mid);
}

int main() {
    int arr[] = {5, 2, 4, 6, 1, 3, 2, 6};
    int size = sizeof(arr) / sizeof(arr[0]);
    merge_sort(arr, size);
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

2.非递归

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

// 合并两个有序数组
void merge(int arr[], int left[], int left_size, int right[], int right_size, int size) {
    int i = 0, j = 0, k = 0;
    while (i < left_size && j < right_size) {
        if (left[i] <= right[j]) {
            arr[k++] = left[i++];
        } else {
            arr[k++] = right[j++];
        }
    }
    while (i < left_size) {
        arr[k++] = left[i++];
    }
    while (j < right_size) {
        arr[k++] = right[j++];
    }
}

// 非递归实现归并排序
void iterative_merge_sort(int arr[], int size) {
    int *temp = (int *)malloc(size * sizeof(int));
    if (!temp) {
        printf("Memory allocation failed.\n");
        return;
    }

    for (int width = 1; width < size; width *= 2) {
        for (int i = 0; i < size; i += 2 * width) {
            int left_size = width;
            int right_size = (i + 2 * width < size) ? width : size - i - width;
            merge(arr + i, arr + i, left_size, arr + i + width, right_size, size);
        }
    }

    free(temp);
}

int main() {
    int arr[] = {5, 2, 4, 6, 1, 3, 2, 6};
    int size = sizeof(arr) / sizeof(arr[0]);
    iterative_merge_sort(arr, size);
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于MetaGPT构建LLM 订阅 Agent

前言 在上一篇文章中&#xff0c;我们学习了如何利用MetaGPT框架构建单智能体和多智能体&#xff0c;并通过一个技术文档撰写Agent和课后作业较为完整的理解一个Agent的需求分析和开发流程&#xff1b;但是技术要和应用结合才能得到更广泛的推广&#xff1b;在本文中&#xff0…

常用的图算法工具库总结【单机版】

常用的图算法工具库总结【单机版】 在当今数据驱动的世界中&#xff0c;图论和图算法在多个领域扮演着越来越重要的角色。从社交网络分析到网络安全&#xff0c;从生物信息学到交通网络优化&#xff0c;图结构数据的管理和分析需求催生了一系列强大的图算法工具库。这些库提供…

Autodesk 3ds Max软件下载安装;3ds Max功能强大的三维建模、渲染软件安装包获取

3ds Max&#xff0c;无论是初学者还是资深设计师&#xff0c;都能通过3ds Max在数字世界中实现自己的创意&#xff0c;打造出令人惊叹的三维作品。 在3ds Max中&#xff0c;灯光系统是至关重要的一环。它提供了光度学灯光和标准灯光两种主要类型&#xff0c;用于照亮和增强场景…

[QT] MAC使用Qt Creator运行程序如何仅运行一个进程?

大家刚开始使用QtCreator会发现每次run程序&#xff0c;都会出现一个程序进程&#xff0c;使得调试操作增加。如下&#xff0c;每次run都会出现一个demo14的进程。 如何每次run后&#xff0c;就关闭上一次的进程&#xff0c;而重新拉起新进程呢&#xff1f; 看这里 这是默认…

25考研|脱产考研「二战」究竟值不值得?

多所高校举办座谈会劝阻脱产考研「二战」&#xff0c;这背后反映了学校对于学生未来发展的深思熟虑和对学生职业规划的关心。学校此举可能基于以下几方面的考量&#xff1a; 首先&#xff0c;脱产考研「二战」意味着学生需要再次投入大量的时间和精力准备研究生入学考试。这不…

线上政务大厅如何通过智能化服务和透明流程改变政务办理模式?

一、线上政务大厅方便快捷办理业务 1、多功能集成的一站式服务 线上政务大厅集成了多种政府服务功能&#xff0c;用户只需一个账号就能访问多个服务平台&#xff0c;办理各类政务业务。包括&#xff1a; &#xff08;1&#xff09;身份认证&#xff1a;用户可以通过线上政务大厅…

NXP i.MX8系列平台开发讲解 - 3.14 Linux 之Power Supply子系统(一)

专栏文章目录传送门&#xff1a;返回专栏目录 Hi, 我是你们的老朋友&#xff0c;主要专注于嵌入式软件开发&#xff0c;有兴趣不要忘记点击关注【码思途远】 目录 1. Power Supply子系统介绍 2. Power Supply子系统框架 3. Power Supply代码分析 本章节主要介绍Linux 下的P…

Java数据结构-哈希表

目录 1. 概念2. 哈希冲突2.1 冲突的避免2.1.1 设计合理的哈希函数2.1.2 降低负载因子 2.2 冲突的解决-闭散列2.3 冲突的解决-开散列 3. 哈希桶的实现 1. 概念 哈希表&#xff08;Hash table&#xff0c;也叫散列表&#xff09;&#xff0c;是根据关键码值(Key)而直接进行访问的…

派派派森03

1.JSON数据 Python数据和Json数据的相互转化 # 导入json模块 import json#准备符合json格式要求的python数据 data [{"name": "老王", "age": 16}, {"name": "张三", "age": 20}]# 通过json.dump(data)方法把pyt…

令人惊叹的小程序 UI 风格

令人惊叹的小程序 UI 风格

【信号与系统】Z变换

Z 变换 连续时间傅立叶变换&#xff08;CTFT&#xff09;的推广是拉普拉斯变换。 离散时间傅立叶变换&#xff08;DTFT&#xff09;的推广是Z 变换。 公式 X [ z ] ∑ n − ∞ ∞ x [ n ] z − n x [ n ] 1 2 π j ∮ X ( z ) z n − 1 d z , \begin{aligned} X[z] &…

反激变压器的设计要点

反激电源的设计最关键的就是在于开关电源的变压器&#xff0c;我们对于反激电源变压器的设计计算的最终目的是为了得到一下几点&#xff1a; 1 原边和副边的电流波形 2 原边和副边的电压波形或幅值 3 磁通密度状况 &#xff08;我们选择的磁芯是不是饱和了&#xff0c;是不是…

vuInhub靶场实战系列--bulldog-1

免责声明 本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关。 目录 免责声明前言一、环境配置1.1 靶场信息1.2 靶场配置 二、信息收集2.1 主机发现2.1.1 netdiscover2.1.2 nmap主机扫描2.1.3 arp-scan主机扫描 2.2 端口扫描…

智慧城市的规划与实施:科技引领城市运行效率新飞跃

随着信息技术的飞速发展&#xff0c;智慧城市的构想正逐步成为现实。作为地理信息与遥感领域的研究者&#xff0c;我深知在这一转型过程中&#xff0c;技术的创新与应用是提升城市运行效率的关键。本文旨在探讨如何利用地理信息系统&#xff08;GIS&#xff09;、遥感技术、大数…

hcia datacom学习(11):vlan基础配置

1.vlan作用 &#xff08;1&#xff09;限制广播域&#xff1a;广播被限制在vlan内&#xff0c;不会在vlan间转发 &#xff08;2&#xff09;提高安全性&#xff1a;不同vlan的报文在传输时是相互隔离的 &#xff08;3&#xff09;灵活构建&#xff1a;交换机可以把不同终端分…

外资企业使用卓豪Zoho CRM优势有哪些?

外资企业在中国市场的竞争愈发激烈&#xff0c;为了在众多本土与国际对手中脱颖而出&#xff0c;高效管理客户关系、提升销售业绩、并实现市场精准定位成为了企业不可或缺的竞争力。在这场数字化转型的浪潮中&#xff0c;卓豪Zoho CRM以其卓越的性能和全面的功能&#xff0c;成…

《精品生活》万方普刊投稿发表简介

《精品生活》杂志是由国家新闻出版总署批准&#xff0c;南方出版传媒股份有限公司主管&#xff0c;广东大沿海出版工贸有限公司主办&#xff0c;广东精品生活杂志社出版的综合性文化期刊。主要栏目&#xff1a;教学研究、艺术教育、文化广角、民族文化、理论前沿、综合论坛。 刊…

现代园区管理工具:“园区运营管理平台”全景解析!

当下&#xff0c;我国各地区产业园区、工业园区、经济开发区、科技园区、商务园区如雨后春笋般迅速崛起&#xff0c;成为推动区域经济增长、促进产业升级的重要载体。然而&#xff0c;如何高效、智能地管理这些园区&#xff0c;提高这些园区的运营效率、服务质量和综合竞争力&a…

如何稳定高效地进行 TiDB 数据导入导出?

对于在数据库行业中摸爬滚打多年的老鸟 DBA 来说&#xff0c;TiDB 可是一点也不陌生&#xff0c;作为 PingCAP 公司自主研发的真开源分布式数据库&#xff0c;其先进的设计理念以及丰富的生态工具&#xff0c;可算得上是业界自主创新和性能领先的代名词。 TiDB 是谁&#xff1…

低温测控芯片迎来突破性进展!

为支持大规模超导量子计算机的开发&#xff0c;日本最大的公共研究机构之一国家先进工业科学与技术研究所 (AIST) 的研究人员与横滨国立大学、东北大学&#xff08;日本国立大学之一&#xff09;和NEC公司合作&#xff0c;提出并成功演示了一种可在低温下控制许多量子比特的超导…