【算法导论】分治法及归并排序

原创 2014年09月18日 00:39:58

有很多算法,在结构上他们是递归的:为了解决一个已经给定的问题,算法要一次或多次的递归调用其自身来解决相关的子问题,这类算法通常采用分治策略。

分治法的基本思想:

(1).原问题==(划分)== >>若干个更小规模的子问题。

(2).要求子问题的求解方法与原问题相同。

分治法的求解步骤:

(1)分解(Divide):将当前问题划分成若干子问题

(2)解决(Conquer):递归解子问题,如果子问题足够小则直接解

(3)合并(Combine):将子问题的解合并长原问题


分治法示例,归并排序:

/*
《Introduction to Algorithms(second edition)》
 chapter2,MERGE_SORT()
date:2014-9-18
*/

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

#define MAX 50

typedef struct
{
	int arr[MAX+1];
	int length;
}SortArr;

SortArr *CreateSortArr()
{
	int i = 0;
	char buf[4*MAX] = "";
	char *ptr = NULL;
	SortArr *sortArr = (SortArr *)malloc(sizeof(SortArr));
	memset(sortArr, 0, sizeof(SortArr));

	printf("请输入待排序数据,以逗号分隔,以分号结束\n"
		"例:23,12,65,36,35;\n"
		"input:");
	scanf("%s", buf);

	ptr = buf;
	sortArr->arr[i] = 0;	//arr[0]不存值用作哨兵单元
	i = 1;
	while(*ptr != ';')
	{
		sortArr->arr[i] = atoi(ptr);
		i++;

		ptr = strstr(ptr, ",");
		if(!ptr)
		{
			break;
		}
		ptr++;
	}
	sortArr->length = (i - 1);

	return sortArr;
}

int merge(int arr[], int p, int q, int r)
{
    int i = 0;
    int j = 0;
    int k = 0;
    int n1 = 0;
    int n2 = 0;
    int *leftArr = NULL;
    int *rightArr = NULL;

    n1 = q - p + 1;
    n2 = r - q;

    //为了和arr[]下标保持一致,leftArr[0]和rightArr[0]不用
    leftArr = (int *)malloc((n1 + 2) * sizeof(int));
    rightArr = (int *)malloc((n2 + 2) * sizeof(int));

    for(i = 1; i <= n1; i++)
    {
        leftArr[i] = arr[p+i-1];
    }
    for(j = 0; j <= n2; j++)
    {
        rightArr[j] = arr[q+j];
    }

    i = 1;
    j = 1;

    //将最后一个数设置为哨兵
    leftArr[n1+1] = INT_MAX;
    rightArr[n2+1] = INT_MAX;

    for(k = p; k <= r; k++)
    {
        if(leftArr[i] <= rightArr[j])
        {
            arr[k] = leftArr[i];
            i++;
        }
        else
        {
            arr[k] = rightArr[j];
            j++;
        }
    }

    free(leftArr);
    free(rightArr);
    return 0;
}

int mergeSort(int arr[], int p, int r)
{
    int q = 0;

    if(p < r)
    {
        q = (p + r) / 2;
        mergeSort(arr, p, q);
        mergeSort(arr, (q+1), r);
        merge(arr, p, q, r);
    }

    return 0;
}

int MergingSortRecursion(SortArr *sortArr)
{
    mergeSort(sortArr, 1, sortArr->length);
    return 0;
}

int PrintArray(SortArr sortArr)
{
	int i = 0;

	for(i = 1; i <= sortArr.length; i++)
	{
		printf("%d,", sortArr.arr[i]);
	}
	printf("\b;\n");

	return 0;
}

int main()
{
	SortArr *sortArr = NULL;
	sortArr = CreateSortArr();

	printf("\nBefore Sort:\t");
	PrintArray(*sortArr);

	MergingSortRecursion(sortArr);

	printf("Sorted Array:\t");
	PrintArray(*sortArr);

	free(sortArr);

	return 0;
}
时间复杂度分析:

在merge()函数中,第70行~77行的的for()循环所需要的时间O(n1+n2)=O(n),第86行~98行的for循环共有n轮迭代,其中每一轮迭代所需的时间都是常量,所以merge()函数的时间复杂度为O(n)。

《算法导论》读书笔记(二)——分治法

设计算法 插入排序使用了增量法,即先排j-1个,然后排j个,下面学习一种新的方法:分治法。 分治法 分治法的思想:大事化小,分而治之。把规模较大的问题分解为几个规模较小的类似子问题,递归的求解子问题,...
  • vinson0526
  • vinson0526
  • 2013年09月02日 22:15
  • 907

算法导论:归并排序java实现

这是归并排序的部分代码,个人认为归并排序作为算法课的前导算法算是一个比较难的问题因为他涉及到了我们都比较恐惧的递归运算。说到递归我们都是非常头疼的,但是递归较其他用迭代来实现的算法又算是理解起来比较简...
  • xidian_db
  • xidian_db
  • 2015年03月30日 16:33
  • 389

算法导论学习:归并排序法的实现

上回学习了最简单也是最直接的插入排序。插入排序在小数据量时是很高效的,但是遇到大数据时,便显得无力了,今天来介绍归并排序,在大数据排序时,时间短,但同时它的空间使用率就显得高了。 第二章...
  • qq_17256847
  • qq_17256847
  • 2016年04月14日 16:13
  • 297

归并排序与分治算法详解

每日一算法,今天我们来谈谈分治算法,再结合算法看看归并排序的实现。同时进一步探讨一下如果从分治算法的结构算出算法的时间复杂度,这点尤为重要。...
  • freestyle4568
  • freestyle4568
  • 2015年12月04日 16:00
  • 1816

MIT算法导论学习笔记-Lecture3:分治法

第三讲 分治法(Devide and Conquer)
  • ai552368625
  • ai552368625
  • 2014年07月25日 09:01
  • 1944

【算法导论】归并排序

归并排序算法分析,欢迎拍砖!
  • cyp331203
  • cyp331203
  • 2014年12月02日 21:42
  • 1040

老生常谈——分治法与归并排序

首先来决一个基本的问题:如何合并两个有序序列?
  • dd864140130
  • dd864140130
  • 2016年03月11日 23:18
  • 1159

算法导论——归并排序

算法的设计有很多思想,之前的插入排序使用的是增量的方法,即在排好的子数组A中,将元素A[j]插入,形成新的子数组A。 这次将实现另一种排序——归并排序,归并排序采用了“分治法”(divide-and-...
  • Anger_Coder
  • Anger_Coder
  • 2013年09月30日 11:16
  • 2552

分治法-----归并排序(C语言描述)

归并排序的基本思想: 将两个及其以上的有序表合并为一张有序表,把待排序序列通过分治法分为若干个有序子序列,然后每两个子序列合并为一个子序列,经过多次合并后整合为一张有序表。 排序过程如图:...
  • LCYong_
  • LCYong_
  • 2016年11月25日 15:16
  • 1756

分治法之归并排序(优化版)

#include #define THRESHOLD 28 void ModMerge(int Array[],int TempArray[],int left,int right,int mi...
  • niushitang
  • niushitang
  • 2013年03月02日 11:34
  • 2029
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【算法导论】分治法及归并排序
举报原因:
原因补充:

(最多只允许输入30个字)