当前位置: 首页 > news >正文

归并排序(自然分组)

上两次总结了归并排序递归和非递归的算法,说实话,也仅仅是理解了,自己手敲代码还是敲不出来。这次总结归并排序在自然分组的情况下的算法。

算法思想:遍历把一个无序的集合,把局部有序的元素划分为一组,两两进行合并,一次合并完毕,再次进行自然分组,然后再两两合并,直到最后一次合并后只剩下一个分组,至此,这个无序的集合就成为有序的集合了。

若数组a中元素为{4,8,3,7,1,5,6,2},则自然排好序的子数组段有{4,8},{3,7},{1,5,6},{2},经一次合并后得到2个合并后的子数组段{3,4,7,8}和{1,2,5,6},继续合并相邻排好序的子数组段,直至整个数组已排好序,最终结果{1,2,3,4,5,6,7,8}

代码实现:

#include <stdio.h>

#define N 8

int fenzu(int a[N], int b[N]) {  //自然分组,记录每个分组的起始位置的下标。
    int temp=a[0];
    int j=0;
    int i;
    b[j++]=0;                    //第一个分组一定是从0号下标开始。
    for(i = 1; i < N;i++) {
        if(temp <= a[i]) {
            temp = a[i];
        } else {
            b[j++] = i;
            temp = a[i];
        }
    }
    b[j++] = N;  //把数组的最后一个元素下标的下一个位置存下来,方便后面的判断结束条件。
    return j;
}

void merge(int a[N], int left, int mid, int right) {
    int i=left,j=mid+1,k=left;
    int t;
    int d[N];
    while(i <= mid && j <= right) {
        if(a[i] < a[j]){
            d[k++] = a[i++];
        } else {
            d[k++] = a[j++];
        }
    }
    if(i!=mid+1){            //说明左边的元素还有,直接加在临时数组d中。
        for(t=i;t<=mid;t++){
            d[k++]=a[t];
        }
    }
    if(j != right+1) {
        for(t = j; t <= right; t++){  //说明右边的元素还有,直接加在临时数组d中。
            d[k++] = a[t];
        }
    }
    for(i = left; i <= right; i++){   //把此次进行合并后的元素拷贝到原数组
        a[i] = d[i];				  //没有参与合并的数组元素不变.为了进行下一次自然分组。 
    }
}

void mergeSort(int a[N], int b[N]) {
    int length=fenzu(a,b);
    int i;
    while(length != 2) {
        for(i = 0; i < length-2; i += 2){    //这里的i < length-2,因为下一行有b[i+2],不然数组会越界.
            merge(a, b[i], b[i+1]-1, b[i+2]-1);
        }
        length=fenzu(a, b);    //一次合并完成,重新进行自然分组.
    }
}

void print(int n, int a[]) {
	int i;
	for(i = 0; i < n; i++) {
		i != n-1 ? printf("%d,", a[i]) : printf("%d", a[i]);
	}
	printf("\n");
} 

int main() {
    int a[N] = {4,8,3,7,1,5,6,2};
    int b[N];
    
    print(N, a);
    mergeSort(a, b);
    print(N, a);
    
    return 0;
}

在随机情况下,自然归并排序分的组数是与普通归并排序是无限趋近相等的。

结论:所以自然分组的归并排序的时间复杂度同样为O(nlogn)。

         然而,若已知待排序数列相对有序的情况,则自然归并排序算法是优于普通归并排序算法的。


相关文章:

  • STM32概述
  • 软件工程学科的诞生
  • 软件开发过程模型综述
  • 算法设计题--数组元素换位
  • 数组换位问题-比较容易理解的解法
  • C语言形参与实参的复习
  • MySQL入门学习总结
  • 计算机存储体系简介
  • Linux基本命令个人总结
  • Makefile的简单写法总结
  • 不带头节点链表--用面向对象的思想实现
  • 经典算法--约瑟夫环问题的三种解法
  • 堆栈的实现与应用--工具
  • 剧院票务管理系统
  • C语言实现贪吃蛇(洗牌算法 循环数组 二维坐标与一维坐标的转化)
  • 【面试系列】之二:关于js原型
  • ES6简单总结(搭配简单的讲解和小案例)
  • Github访问慢解决办法
  • HTTP中GET与POST的区别 99%的错误认识
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • JSDuck 与 AngularJS 融合技巧
  • React的组件模式
  • Redux 中间件分析
  • springMvc学习笔记(2)
  • 深度解析利用ES6进行Promise封装总结
  • 我建了一个叫Hello World的项目
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 怎么将电脑中的声音录制成WAV格式
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • #Linux(帮助手册)
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (二)PySpark3:SparkSQL编程
  • (二十三)Flask之高频面试点
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (附源码)计算机毕业设计大学生兼职系统
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (译)2019年前端性能优化清单 — 下篇
  • ***检测工具之RKHunter AIDE
  • **PHP二维数组遍历时同时赋值
  • .FileZilla的使用和主动模式被动模式介绍
  • .Net Redis的秒杀Dome和异步执行
  • .Net Web窗口页属性
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .net程序集学习心得
  • .NET单元测试
  • .NET中统一的存储过程调用方法(收藏)
  • [ JavaScript ] JSON方法
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [20190401]关于semtimedop函数调用.txt
  • [ASP]青辰网络考试管理系统NES X3.5
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用
  • [BZOJ3223]文艺平衡树