经典算法学习——归并排序

归并排序算法采用的是分治算法,即把两个或两个以上的有序表合并成一个新的有序表的过程。首先把待排序的序列分成若干个子序列,每个子序列都是有序的,然后把有序子序列合并成整体有序序列,这个过程也称为2路归并。实现代码已经上传至: https://github.com/chenyufeng1991/MergeSort  。

基本思想如下:将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。

综上可知,归并排序其实要做两件事情:

(1)“分解”——将序列每次折半划分;

(2)“合并”——将划分后的序列段两两合并后排序;

那么如何进行合并呢?

在每次合并过程中,都是对两个有序的序列段进行合并,然后排序。这两个有序序列段分别为R[low,mid],R[mid+1,high]。先将它们合并到一个局部的暂存数组R2中,合并完成后再将R2复制到R中。R[low,mid]称为第一段,R[mid+1,high]称为第二段,每次从两个段中取出一个记录进行关键字的比较,将较小者放入R2中。最后将各段中余下的部分直接复制到R2中。经过这样,R2已经是一个有序的序列,再将其复制回R中,一次合并排序就完成了。代码如下:

//
//  main.c
//  MergeSort
//
//  Created by chenyufeng on 16/2/16.
//  Copyright © 2016年 chenyufengweb. All rights reserved.
//

#include <stdio.h>

void MergeSort(int *a,int begin,int end,int *temp);
void MergeArray(int *a,int begin,int mid,int end,int *temp);

int main(int argc, const char * argv[]) {

    int num[] = {2,5,9,3,6,1,0,7,4,8};
    int temp[10];
    MergeSort(num,0,9,temp);
    for(int i = 0;i < 10;i++){
        printf("%d ",num[i]);
    }
    printf("\n");
    return 0;
}

//将有二个有序子数组a[begin...mid]和a[mid+1...end]合并;
void MergeArray(int *a,int begin,int mid,int end,int *temp){

    int i = begin,j = mid + 1;
    int m = mid,n = end;
    int k = 0;

    //开始合并两个数组;
    while(i <= m && j <= n){
        if(a[i] <= a[j]){
            temp[k++] = a[i++];
        }else{
            temp[k++] = a[j++];
        }
    }

    while(i <= m){
        temp[k++] = a[i++];
    }

    while(j <= n){
        temp[k++] = a[j++];
    }

    //把temp数组中的结果装回a数组
    for(i = 0;i < k;i++){
        a[begin + i] = temp[i];
    }
}

void MergeSort(int *a,int begin,int end,int *temp){
    if(begin < end){

        int mid = (begin + end) / 2;
        /**
         *  分别递归进行排序,也称为2-路归并;
         */
        MergeSort(a,begin,mid,temp);   //左边有序
        MergeSort(a,mid + 1,end,temp);   //右边有序
        MergeArray(a,begin,mid,end,temp); //将左右两边有序的数组合并
    }
}

本文参考:http://www.cnblogs.com/jingmoxukong/p/4308823.html

http://blog.csdn.net/chenhuajie123/article/details/9296359

时间: 2024-10-05 05:07:12

经典算法学习——归并排序的相关文章

经典算法学习——非循环双向链表实现冒泡排序(不带头结点)

我在前面两篇博客<经典算法学习--单链表(不带头结点)实现冒泡排序><经典算法学习--单链表实现冒泡排序(带头结点)>中详细描述了分别使用带头结点和不带头结点的单链表实现了冒泡排序,让我们对单链表和冒泡排序有了理性的认识.今天我们将会来使用不带头结点的非循环双向链表来实现冒泡排序,在处理过程中,这种冒泡比前面两种更为简单高效.代码上传至 https://github.com/chenyufeng1991/DoubleLinkedList_BubbleSort . 核心代码如下: /

经典算法学习——链表实现冒泡排序

我在之前一篇博客<经典算法学习--冒泡排序>中简单实现了使用数组进行冒泡排序.这篇博客我们将来实现使用链表如何排序,其实整体的思路是一样的.示例代码上传至: https://github.com/chenyufeng1991/BubbleSortLinkedList . 算法描述如下: (1)比较相邻的前后两个数据,如果前面数据大于后面的数据,就将两个数据交换: (2)这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就到了最后一个位置,也就是下标为N-1的位置(沉到了水底).

Javascript经典算法学习1:产生随机数组的辅助类

辅助类 在几个经典排序算法学习部分,为方便统一测试不同算法,新建了一个辅助类,主要功能为:产生指定长度的随机数组,提供打印输出数组,交换两个元素等功能,代码如下: function ArraySortUtility(numOfElements) { this.dataArr = []; this.pos = 0; this.numOfElements = numOfElements; this.insert = insert; this.toString = toString; this.cle

经典算法学习之分治法(以排列、组合程序为例)

分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归的求解这些子问题,然后再合并这些子问题的解来建立原问题的解. 分治法在每层递归是遵循的三个步骤: (1)分解原问题为若干个子问题,这些子问题是原问题的规模较小的实例. (2)解决这些子问题,队规的求解各个子问题,当子问题规模足够小的时候,直接求解. (3)合并这些子问题的解构成原问题的解. 显然归并排序是一个非常经典规矩的分治法的例子,鉴于之前已经写过一篇关于归并排序的博文,这里不在使用归并排序作为例子. 注意分治法的每一层递归

经典算法之归并排序——python和JS实现

前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:韩忠康 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http://t.cn/A6Zvjdun 算法 归并排序(merge-sort),典型的分治策略(divide and conquer).核心思路是将整体序列一分为二形成两个子序列,分别对子序列排序,再将两个有序子序列合并成一个有序序列. 思路如图: 整体过程分为拆分和合并两大阶段. 拆分,核

经典算法学习——第一个只出现一次的字符

这同样是剑指Offer中的很经典的一道面试题.题目描述为:在字符串中找出第一个只出现一次的字符.如输入"abaccdeff",则输出'b'.  一开始大家就会想到最简单的方法就是每访问到一个字符的时候,与后面的每一个字符去进行比较,若没有发现相同的元素,那么该元素就是第一个只出现一次的字符.这样的复杂度为O(n^2).   显然这样的效率不高. 这道题的大方向就是一题查找算法,常见的查找算法为顺序查找,二分查找,哈希查找.比较适合这道题的是哈希查找.首先我们可以建立一个256长度的数组

经典算法学习——打印两个链表的第一个公共节点

求链表的公共节点是一道很经典的算法题,并不是很难.我们需要知道的是,一旦两个链表有一个公共节点的话,那么这两个链表的形状就是一个"Y"型.也就是说,自公共节点之后的所有节点都是一样的.如下: 其实只要看了这幅图,实现就很简单了.首先我们分别遍历两个链表,分别得出他们的长度L1,L2.然后在查找公共节点时,先在长的那个链表中走|L1-L2|步,然后两个链表同时向后进行同步遍历,每走一步时,就判断后面那个节点是否相同.若相同,则找到该第一个公共节点.完整代码上传至 https://gith

经典算法学习——冒泡排序

冒泡排序是我们学习的第一种排序算法.应该也算是最简单.最经常使用的排序算法了. 无论怎么说.学会它是必定的. 今天我们就用C语言来实现该算法. 演示样例代码已经上传至:https://github.com/chenyufeng1991/BubbleSort 算法描写叙述例如以下: (1)比較相邻的前后两个数据.假设前面数据大于后面的数据,就将两个数据交换: (2)这样对数组的第0个数据到N-1个数据进行一次遍历后.最大的一个数据就到了最后一个位置,也就是下标为N-1的位置(沉到了水底). (3)

Java基础知识强化56:经典算法之归并排序(MergeSort)

1. 归并排序的原理: 原理,把原始数组分成若干子数组,对每一个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组 举例: 无序数组[6 2 4 1 5 9]   先看一下每个步骤下的状态,完了再看合并细节 第一步: [6 2 4 1 5 9]原始状态 第二步: [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍 第三步: [1 2 4 6] [5 9]继续两组两组合并 第四步: [1 2 4 5 6 9]合并完毕,排序完毕        输