归并排序

来源:互联网 发布:北京大学网络教学平台 编辑:程序博客网 时间:2024/05/16 18:02

首先先讲讲分治思想。分治即将原问题分解为几个规模较小但类似于原问题的子问题,递归求解这些子问题,然后再合并这些子问题的解来建立问题的解。(《算法导论》中的原话)

知道了分治,那么该如何实现呢。根据上面的描述,我们要解决的几个主要的问题是:

1.如何分解原问题

2.如何进行递归求解。因为递归都要有个尽头,所以这里我们还要定义一个最小的子问题

3.如何合并那些已经解决了的子问题。


代码:

MergeSort.h

#pragma onceclass MergeSort{private:int* data;// 数据int length;// 数据个数public:MergeSort(int* &d, int size) : data(d), length(size) {}~MergeSort(void){if(data != nullptr){delete data;data = nullptr;}}void output() const;void sort();void swap(int i, int j);private:void mergeSort(int p, int q);void merge(int p, int q, int r);};

MergeSort.cpp

#include "MergeSort.h"#include <iostream>void MergeSort::output() const{int i = 0;while(i < length){std::cout<<data[i]<<" ";i++;}std::cout<<"\n";}void MergeSort::sort(){mergeSort(0, length);}/** 分解原问题,将数组分为左部分和右部分。那么我们要分割的最小情况是,左边为* 只有一个元素的数组,右边也是只有一个元素的数组。* @param p 为左边的起始索引,包含p* @param r 为右边的终止索引,不包含r*/void MergeSort::mergeSort(int p, int r){if(r - p >= 2){std::cout<<p<<":"<<r<<std::endl;int q = (p + r) / 2;  // 取中点mergeSort(p, q);      // 对左边进行递归mergeSort(q, r);  // 对右边进行递归merge(p, q, r);       // 合并左右两边,则p,r之间的元素已排序好}}/** 写代码的时候在意细节也许是好事。比如,我在写的时候喜欢带入数字计算q-p是不是* 就算出正确的数组元素个数。但是这样即使自己带入的数字能计算出正确的结果,这也* 只是让自己暂时安心。* 当疑惑时,应该先明确自己定的每个参数表达的意义,然后再去验证,这样作可以加深* 自己对代码的理解。事倍功半。*/void MergeSort::merge(int p, int q, int r){int n1 = q - p;  // 左边数组元素的个数int n2 = r - q;  // 右边数组元素的个数int* lArr = new int[n1 + 1]; // +1个元素是为了在数组的末尾增加一个哨兵int* rArr = new int[n2 + 1];for(int i = 0; i < n1; i++){lArr[i] = data[p + i];}for(int j = 0; j < n2; j++){rArr[j] = data[q + j];}lArr[n1] = RAND_MAX;  // 哨兵来了rArr[n2] = RAND_MAX;int lIndex = 0, rIndex = 0;for(int k = p; k < r; k++){if(lArr[lIndex] <= rArr[rIndex])  // 有了哨兵,比较的时候就不用担心数组越界{                                 // 同时简化了代码data[k] = lArr[lIndex];lIndex++;}else{data[k] = rArr[rIndex];rIndex++;}}}// 数值交换方法,只对整型数据有效void MergeSort::swap(int i, int j){data[i] ^= data[j];data[j] ^= data[i];data[i] ^= data[j];}

Main.cpp

#include <iostream>#include <time.h>#include "MergeSort.h"// 获取[1,500]范围内的随机数int proRandNum() {return rand() % 500 + 1;}int main(){using namespace std;srand((unsigned)time(NULL)); // 设置随机数种子int size = 20;int *data = new int[size];for(int i = 0; i < size; i++){data[i] = proRandNum();}MergeSort* sort = new MergeSort(data, size);cout<<"before sorted:\n";sort->output();cout<<"after sorted:\n";sort->sort();sort->output();system("pause");return 0;}


0 0
原创粉丝点击