算法(三):归并排序

归并排序同为分治法,但是与快速排序不同

快速排序更偏向于分,在分的递归过程中的两侧数据交换

而归并排序更偏向于合并,在两半部分合并的递归中的按顺序排序

代码:

[email protected]:/mnt/shared/appbox/mgsort# cat mgsort.c
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

static int compare_int(const void *int1, const void *int2)
{
        if(*(const int *)int1 == *(const int *)int2)
                return 0;

        return *(const int *)int1 > *(const int *)int2 ? 1 : -1;
}

static int merge(void *data, int esize, int i, int j, int k, int (*compare)(const void *key1, const void *key2))
{
        char *a = data;
        char *m;
        int ipos, jpos, mpos;

        ipos = i;
        jpos = j + 1;
        mpos = 0;

        if((m = (char *)malloc(esize * ((k-i)+1))) == NULL)
                return -1;

        while(ipos <= j || jpos <= k)
        {
                if(ipos > j)// left no more elements to merge
                {
                        while(jpos <= k)//merge right
                        {
                                memcpy(&m[mpos * esize], &a[jpos * esize], esize);
                                jpos++;
                                mpos++;
                        }
                        continue;
                }
                else if(jpos > k)//right no more elements to merge
                {
                        while(ipos <= j)// merge left
                        {
                                memcpy(&m[mpos * esize], &a[ipos * esize], esize);
                                ipos++;
                                mpos++;
                        }
                        continue;
                }

                //both left and right need merge
                if(compare(&a[ipos * esize], &a[jpos * esize]) < 0)
                {
                                memcpy(&m[mpos * esize], &a[ipos * esize], esize);
                                ipos++;
                                mpos++;
                }
                else
                {
                                memcpy(&m[mpos * esize], &a[jpos * esize], esize);
                                jpos++;
                                mpos++;
                }
        }

        memcpy(&a[i * esize], m, esize * ((k-i)+1));
        free(m);

        return 0;
}

int mgsort(void *data, int size, int esize, int i, int k , int (*compare)(const void *key1, const void *key2))
{
        int j;

        if(i < k)
        {
                j = (int)(((i + k -1))/2);

                if(mgsort(data, size, esize, i, j, compare) < 0)
                        return -1;

                if(mgsort(data, size, esize, j+1, k, compare) < 0)
                        return -1;

                if(merge(data, esize, i, j, k, compare)< 0)
                        return -1;
        }
        return 0;
}

int main(int argc, char *argv[])
{
        int ret;
        int i, j, k;
        i = 11;
        j = 12;
        int array[10]= {1,4,7,2,5,8,3,6,9,10};

        printf("\n******************compare_init test**********************\n");
        printf("compare_int(&i, &j)=%d\n", compare_int(&i, &j));
        printf("compare_int(&j, &i)=%d\n", compare_int(&j, &i));
        printf("compare_int(&i, &i)=%d\n", compare_int(&i, &i));
        printf("\n******************partition    test**********************\n");

        mgsort(array, 10, sizeof(int), 0, 9, compare_int);

        for(i=0; i<10; i++)
                printf("%d ", array[i]);
        printf("\n");

        return 0;
}

运行结果:

[email protected]:/mnt/shared/appbox/mgsort# ./mgsort 

******************compare_init test**********************
compare_int(&i, &j)=-1
compare_int(&j, &i)=1
compare_int(&i, &i)=0

******************partition    test**********************
1 2 3 4 5 6 7 8 9 10
[email protected]:/mnt/shared/appbox/mgsort# 
时间: 2024-08-24 15:09:20

算法(三):归并排序的相关文章

排序算法之归并排序(Mergesort)解析

一.归并排序的优缺点(pros and cons) 耗费心思来理解它,总要有个理由吧: 归并排序的效率达到了巅峰:时间复杂度为O(nlogn),这是基于比较的排序算法所能达到的最高境界 归并排序是一种稳定的算法(即在排序过程中大小相同的元素能够保持排序前的顺序,3212升序排序结果是1223,排序前后两个2的顺序不变),这一点在某些场景下至关重要 归并排序是最常用的外部排序方法(当待排序的记录放在外存上,内存装不下全部数据时,归并排序仍然适用,当然归并排序同样适用于内部排序...) 缺点: 归并

算法-4.归并排序(自顶向下)

1.基本思想 将两个有序的数组归并成一个更大的有序数组,很快人们就根据这个操作发明了一种简单的递归排序算法:归并排序.要将一个数组排序,可以先(递归地)将它分成两半分别排序,然后将结果归并起来.你将会看到,归并排序最吸引人的性质是它能够保证将任意长度为N的数组排序所需时间和NlogN成正比:它的主要缺点则是它所需的额外空间和N成正比.简单的归并排序如下图所示: 原地归并的抽象方法: 实现归并的一种直截了当的办法是将两个不同的有序数组归并到第三个数组中,实现的方法很简单,创建一个适当大小的数组然后

十大基础实用算法之归并排序和二分查找

归并排序 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 算法步骤: 1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置 3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 4. 重复步骤3直到某一指针达到序列尾 5. 将另一序列剩下的所有元素直接复制到合并序列尾 用分治策略解决问题分为三步:分解

Java常见排序算法之归并排序

在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let‘s go~~~ 1.排序算法的基本概念的讲解 时间复杂度:需要排序的的关键字的比较次数和相应的移动的次数. 空间复杂度:分析需要多少辅助的内存. 稳定性:如果记录两个关键字的A和B它们的值相等,经过排序后它们相对的位置没有发生交换,那么我们称这个排序算法是稳定的. 否则我们称这个排序算法是不稳定的

搞定面试算法系列 —— 分治算法三步走

主要思想 分治算法,即分而治之:把一个复杂问题分成两个或更多的相同或相似子问题,直到最后子问题可以简单地直接求解,最后将子问题的解合并为原问题的解. 归并排序就是一个典型的分治算法. 三步走 和把大象塞进冰箱一样,分治算法只要遵循三个步骤即可:分解 -> 解决 -> 合并. 分解:分解原问题为结构相同的子问题(即寻找子问题) 解决:当分解到容易求解的边界后,进行递归求解 合并:将子问题的解合并成原问题的解 这么一说似乎还是有点抽象?那我们通过经典的排序算法归并排序来体验一下分治算法的核心思想.

算法:归并排序

算法:归并排序 写在前面 归并排序算法是基于一个简单的归并操作:合并两个有序数组来形成一个更大的有序数组. 提炼归并的思想,归并排序就是将一个无序数组先划分成两个部分(递归地),对其分别排序,然后再进行合并. 归并排序无论输入情况,时间复杂度为N*LogN,主要的缺点是使用了一个额外的大小为N的空间. 简单的归并操作: 首先我们思考一下,如何将两个有序数组合并成一个有序数组? 我们应该想到新建一个的新数组re,然后分别从两个数组的左边开始,依次比较两个数组中的元素,将数较小的元素先排入新数组中.

Dijkstra算法(三)之 Java详解

前面分别通过C和C++实现了迪杰斯特拉算法,本文介绍迪杰斯特拉算法的Java实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法图解 3. 迪杰斯特拉算法的代码说明 4. 迪杰斯特拉算法的源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 迪杰斯特拉算法介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想

经典白话算法之归并排序

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

算法题——归并排序的原地实现

普通的归并排序,需要一个额外的数组来保存每次merge的结果:如果要求不使用额外空间,那么每次merge的时候需要做一些处理. 思路: 合并left[] 和 right[]时,假如right[0]应该放入left[3],那么:①可以用一个var来保存right[0],然后将left[3]之后的元素右移一次,再将var值放入left[3]:②也可以交换right[0]和left[3]的值,然后left[0]在新的位置向后遍历,找到合适的位置,再把前面的移位.    寻找合适位置的过程是一次插入排序

排序算法系列——归并排序

记录学习点滴,菜鸟成长记 归并排序的英文叫做Merge-Sort,要想明白归并排序算法,还要从“递归”的概念谈起. 1.递归 一般来讲,人在做决策行事的时候是往往是从已知出发,比如,我又要举个不恰当的例子了→_→: 看到漂亮姑娘→喜欢人家→追→女朋友→老婆 但是人家施瓦辛格不是这么想的,人家从小就立志当总统: 要当总统←先当州长←竞选州长要有钱←那得找个有钱妹子←妹子都喜欢明星←身材好能当明星←健身 递归,就像一个人对自己的发展有清晰的规划和坚定的信心一样,他知道每一步会有怎么样的结果,他需要仅