归并排序(C/C++)
2015-08-22 14:45
471 查看
归并排序
算法原理
归并算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。(百度百科)本文主要实现二路归并。
实质上归并排序就是一个 (不断划分子序列)– (子序列长度为1时停止递归) – (合并子序列) 的过程。
那么如何合并有序子序列?长度为1的子序列当然是有序的。对于长度大于一的序列的合并,我们引用算法导论的扑克的例子,桌上有两堆从小的在上,大的在下的扑克牌,我们要把它们合并为有序的一堆,只需每次把两堆牌顶中小的那张拿下来放在新堆中即可。
复杂度
时间复杂度 O(nlogn)空间复杂度 O(n)
IO复杂度 (2nlogn)
算法实现
#include <iostream> #include <cstdio> #include <cstdlib> #define LEN 11 using namespace std; void printarray(int *data,int size) //打印序列 { for(int i = 0; i < size ;++i) { cout << data[i] << " " ; } cout << endl; } void merge(int *data,int start,int mid,int end) //排序子序列 { int ptr = 0; int origin_mid = mid; int origin_start = start; //记录原来的界限 int buffer[end-origin_start+1]; int lenth = end - start +1; /* cout << "start:" << start << " mid:"<<mid << " end:" << end <<endl; cout << "Data: "; printarray(data,11);*/ while(start <= origin_mid || mid <= end) //当start指针和mid指针均没有越界时,即为两个子序列都不是空序列时循环 { if ((data[start] < data[mid+1] || mid >= end ) && start <= origin_mid) //把前半子序列数据压入缓冲区的情况有 1.前半段头数据较大 2.后半子序列为空 (保证前段不为空) { buffer[ptr] = data[start]; start++; //压入缓冲区,前半段指针后移 ptr++; }else{ buffer[ptr] = data[mid+1]; mid++; ptr++; } } /* cout << "Buffer: "; printarray(buffer,lenth);*/ for(int i = origin_start; i <= end ;++i) { data[i] = buffer[i-origin_start]; //用缓冲区数据代替没有排序的序列 } /* cout <<"merged data:"; printarray(data,11); cout << "----------" << endl;*/ } void mergesort(int *data,int start,int end) //归并 { int mid = (start + end )/2; //分治的分界 if(start < end) { mergesort(data,start,mid); //分治 mergesort(data,mid+1,end); //分治 merge(data,start,mid,end); //归并 } } int main(int argc, char const *argv[]) { int data []= {1,5,7,10,2,3,4,8,12,4,13}; mergesort(data,0,LEN-1); printarray(data,LEN); return 0; }
简洁一点的Merge写法:
void Merge(int data[],int start,int mid,int end) { int i = start; int j = mid+1; int k = start; int merged_data[LEN]; while(i <= mid && j <= end)//均不为空堆 { if(data[i]<=data[j]) merged_data[k++]=data[i++]; else merged_data[k++]=data[j++]; } while(i <= mid) //后半段为空堆 merged_data[k++]=data[i++]; while(j <= end) //前半段为空堆 merged_data[k++]=data[j++]; for(int l=0 ; l<8 ; l++) //记录数组 data[l]=merged_data[l]; }
相关文章推荐
- C++实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序等
- Java实现八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序等
- Java排序算法总结之归并排序
- C++归并排序算法实例
- Javascript排序算法之合并排序(归并排序)的2个例子
- 归并排序的递归实现与非递归实现代码
- java二路归并排序示例分享
- java实现归并排序算法
- 归并排序的实现代码与思路
- leetcode 虐我篇之(二) Two Sum
- In-place Merge Sort 原地并归排序
- 使用Java完成《算法导论》习题2.3-2
- 插入排序移动次数
- 归并排序 with Python
- 归并排序-逆序对的求解
- 排序算法的复杂度和稳定性
- 用python实现归并排序
- (转)排序算法的稳定与不稳定
- 自学笔记之归并排序
- java实现排序算法