经典算法之归并排序的C实现方法

以前写过归并排序的算法,但是时间过了好久,忘记怎么写的了,(也是醉了)。正好复习算法的时候遇到这个问题,就重新写了一下,把遇到的一些问题顺便记录一下。

核心就是用两个子数组记录分割后的两个数组中的变量, 然后依次比较大小即可。

这里有个细节需要注意一下,

arr_temp1[mid + 1 - low] = INT_MAX;

这段代码,用来设置一个哨兵, 用这种方法可以避免判断数组是否为空了

具体的算法的伪代码可以参考《算法导论》 Chapter 2 算法基础, P17

源代码如下:

// =====================【归并排序 】==================
// @ author         :           zhyh2010
// @ date           :           20150606
// @ version        :           1.0
// @ description    :
// =====================【归并排序】==================

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

#define NUM 20
int arr[NUM] = { 0 };
int arr_temp1[NUM] = { 0 };
int arr_temp2[NUM] = { 0 };

void init()
{
    time_t tm;
    time(&tm);
    srand((unsigned int)tm);

    int max_item = 100;
    for (int i = 0; i != NUM; i++)
        arr[i] = rand() % max_item;
}

void display(int * arr)
{
    for (int i = 0; i != NUM; i++)
        printf("%-10d", arr[i]);
    printf("\n");
}

void merge(int low, int mid, int high)
{
    for (int ii = 0; ii != mid + 1 - low; ii++)
    {
        arr_temp1[ii] = arr[low + ii];
    }
    arr_temp1[mid + 1 - low] = INT_MAX;

    for (int ii = 0; ii != high - mid; ii++)
    {
        arr_temp2[ii] = arr[mid + 1 + ii];
    }
    arr_temp2[high - mid] = INT_MAX;

    int i = 0;
    int j = 0;
    for (int k = low; k != high + 1; k++)
    {
        if (arr_temp1[i] < arr_temp2[j])
            arr[k] = arr_temp1[i++];
        else
            arr[k] = arr_temp2[j++];
    }
}

void mergeSort(int low, int high)
{
    if (low >= high)
        return;

    int mid = (low + high) / 2;
    mergeSort(low, mid);
    mergeSort(mid + 1, high);
    merge(low, mid, high);
}

void main()
{
    init();
    printf("归并排序前\n");
    display(arr);

    mergeSort(0, NUM - 1);
    printf("归并排序后\n");
    display(arr);
}
时间: 2024-10-11 22:42:59

经典算法之归并排序的C实现方法的相关文章

经典算法之快速排序的C实现方法

这里所实现的快速排序是参考<算法导论>上的伪代码,虽然之前对着伪代码敲过一遍,可是现在抛开伪代码,自己敲还是有些费劲.<-_->!! 特别需要注意的是算法导论中的快排方法,和课上讲的不太一样,课上讲的主要是利用首尾两个下标来实现, 而算法导论中,主要是 从前到后,依次判断,将小于privot 的值全部移到 i 的前面去.这里 i 是指 小于 privot值的下标上界. 源代码如下: // =====================[快速排序]================== /

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

归并排序算法采用的是分治算法,即把两个或两个以上的有序表合并成一个新的有序表的过程.首先把待排序的序列分成若干个子序列,每个子序列都是有序的,然后把有序子序列合并成整体有序序列,这个过程也称为2路归并.实现代码已经上传至: https://github.com/chenyufeng1991/MergeSort  . 基本思想如下:将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表:将这些有序序列再次归并,得到n/4个长度为4的有序序

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]合并完毕,排序完毕        输

【经典算法】归并排序

归并排序是以O(NlogN)最坏情形运行时间运行,而所使用的比较次数几乎是最优的.它是递归算法的一个很好的实例. 归并排序的也遵循分治的思想.直观上其操作如下: 分解:分解待排序的n个元素的序列成各具n/2个元素的子序列. 解决:使用归并排序递归地排序两个子序列. 合并:合并两个已排序的子序列以产生已排序的答案. 当待排的序列长度为1时,递归“开始回升”,在这种情况下不要做任何工作,因为长度为1的每个序列都已排好序. 归并排序算法的关键操作是“合并步骤”中两个已排序序列的合并.我们通过调用一个辅

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

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

白话经典算法系列之五 归并排序的实现(转)

归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 首先考虑下如何将将二个有序数列合并.这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数.然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可. //将有序数组a[]和b[]合并到c[]中 void MemeryArray(int a[], int n, int b[], int m, int c[]) { int

[经典算法题]寻找数组中第K大的数的方法总结

[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据中查找到第k个大的值. 名称是:设计一组N个数,确定其中第k个最大值,这是一个选择问题,当然,解决这个问题的方法很多,本人在网上搜索了一番,查找到以下的方式,决定很好,推荐给大家. 所谓"第(前)k大数问题"指的是在长度为n(n>=k)的乱序数组中S找出从大到小顺序的第(前)k个数的问题.

白话经典算法系列之九 从归并排序到数列的逆序数对(微软笔试题)

首先来看看原题 微软2010年笔试题 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序数对.一个排列中逆序的总数就称为这个排列的逆序数.如{2,4,3,1}中,2和1,4和3,4和1,3和1是逆序数对,因此整个数组的逆序数对个数为4,现在给定一数组,要求统计出该数组的逆序数对个数. 计算数列的逆序数对个数最简单的方便就最从前向后依次统计每个数字与它后面的数字是否能组成逆序数对.代码如下: #include <stdio.h> int main()

经典白话算法之归并排序

void Merge(int A[],int p,int q,int r){ int i,j,k; //计算子数组A[p..q]的元素个数 int n1 = q - p + 1; //计算子数组A[q+1..r]元素个数 int n2 = r - q; //创建子数组L,R int* L = (int*)malloc(sizeof(int)*(n1+1)); int* R = (int*)malloc(sizeof(int)*(n2+1)); //将子数组A[p..q]赋值到L数组 for(i