排序算法学习之归并排序

1.
归并排序原理
:有长度为n的子序列a[n],可以将其看做n个长度为1的子序列,将相邻子序列两两归并后子序列数量减少一半,再对子序列进行两两归并,数量又减少一般,重复直到得到一个长度为n的子序列

2. 实现归并操作的代码如下:


/*array[s…m]和array[m+1…t]均已各自有序,合并使得array[s…t]有序*/
void Merge(int s, int m, int t, int *array)
{
int temp[t-s+1];/*设临时数组存放排序后的元素*/
int i=s, j=m+1, k=0;
while(i<=m && j<=t)
{
if(array[i] < array[j])
temp[k++] = array[i++];
else
temp[k++] = array[j++];
}
while(i<=m)
temp[k++] = array[i++];
while(j<=t)
temp[k++] = array[j++];

for(i=s, k=0; i<=t && k<=t-s; i++, k++) /*将临时数组里的元素复制到原数组*/
{
array[i] = temp[k];
}

3. 递归调用代码如下:


void MSort (int s, int t, int *array)    /*递归调用*/
{
if(s == t)
return ;
int m = (s+t)/2; /*设置中间数*/
MSort(s, m, array); /*左边序列有序*/
MSort(m+1, t, array); /*右边序列有序*/
Merge(s, m, t, array); /*将左右有序序列归并*/
}
void MergeSort1(int n, int *array)
{
MSort(0, n-1, array);

4. 归并排序非递归调用的实现

由于大量引入递归造成时间和空间上性能的损耗,所以我们考虑引入迭代来代替递归,效率必然要高于递归,如下:


void MergeSort2(int n, int *array)
{
int k, i;
for (k=1; 2*k<n; k *= 2) /*设置每段待归并的有序序列的长度:1,2,4,8,16……*/
{
for (i=0; i+k-1<n; i += 2*k)/*考虑待归并的左右两段序列,[i+k-1]是左序列末尾元素下标*/
{ /*[end=i+2*k-1]是右序列末尾元素下标,end不应该超过n-1*/
int end=i+2*k-1;
if(end > n-1)
end = n-1;
Merge(i, i+k-1, end, array);
}
}
}

时间: 2024-10-19 11:00:46

排序算法学习之归并排序的相关文章

八大排序算法学习笔记:冒泡排序

冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法. 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端. 算法原理: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针对所有

排序算法学习之堆排序

一.堆与堆排序的产生及定义 在简单选择排序中,每次从n个元素中比较n-1次选取最小的元素,这很好理解,但是前面比较过的数据在之后还要重新比较,这将花费大量的运算时间.堆排序算法就很好的解决了这个问题,堆排序在每次选择到最小记录的同时会根据比较结果对其他数据进行调整,堆排序的时间复杂度为O(NlogN). 堆通常是指二叉堆,即堆是一颗完全二叉树,同时其满足一定性质:每个节点的值大于等于其左右孩子的值(大顶堆),或者每个节点的值小于等于其左右孩子的值(小顶堆).堆在本质上是一个数组,根节点即为a[0

八大排序算法学习笔记:插入排序(一)

插入排序     包括:直接插入排序,二分插入排序(又称折半插入排序),链表插入排序,希尔排序(又称缩小增量排序).属于稳定排序的一种(通俗地讲,就是两个相等的数不会交换位置) . 直接插入排序: 1.算法的伪代码(这样便于理解):     INSERTION-SORT (A, n)             A[1 . . n] for j ←2 to n do key ← A[ j] i ← j – 1 while i > 0 and A[i] > key do A[i+1] ← A[i]

八大排序算法学习笔记:插入排序(二分插入排序)

二分插入排序   也称折半插入排序, 1.基本思想:设数列[0....n]分为两部分一部分是[0...i]为有序序列,另一部分是[i+1.....n]为无序序列,从无序序列中取一个数 x ,利用二分查找算法找到 x 在有序序列中的插入位置并插入,有序序列还是有序的,接下来重复上述步骤,直到无序序列全部插入有序序列 ,这是整个序列只剩下有序序列即有序了. 2.代码:    3.复杂度: 用二分插入排序所要进行的总比较次数为O(lgn),当n较大时,比直接插入排序的最大比较次数小得多,但大于最小比较

排序算法学习之快速排序

快速排序基本思想:选取一个枢轴元素(图简单可选第一个),通过对序列一次遍历(中间涉及到数的交换),将该枢轴放置到序列合适位置,保证其左边数都比它小,右边数都比它大,然后利用递归思想对其左右两个子序列进行同样排序. 快熟排序的基本实现过程:将枢轴元素key备份,序列头尾各设置一个游标--i和j,尾部游标j先移动(如果选择的最后一个元素为枢轴则i先移),直到遇到比key小的元素,将其移到原枢轴处覆盖之,此时j处元素空着了,然后再对i进行移动,直到遇到比key大的元素,将其移到右边下表为j的空白处 v

图解排序算法(四)之归并排序

基本思想 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之). 分而治之 可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现).分阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n. 合并相邻有序子序列 再来看看治阶段

经典排序算法学习笔记之二——快速排序

一.快速排序 数据结构 不定 最差时间复杂度 O(n^2) 最优时间复杂度 O (n*log n) 平均时间复杂度 O (n*log n) 最差空间复杂度 根据实现的方式不同而不同 https://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F 1.算法思想: 从数列中挑出一个元素,称为"基准"(pivot), 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边

排序算法之二路归并排序

基本思想 首先将待排序的元素序列分成两个长度相等的子序列,为每一个子序列排序,然后再将它们合并成一个序列. 代码 private void mergeSort(int[] a, int[] b, int left, int right) { if (left < right) { int middle = (left + right) / 2; mergeSort(a, b, left, middle); mergeSort(a, b, middle + 1, right); merge(a,

常见经典排序算法学习总结,附算法原理及实现代码(插入、shell、冒泡、选择、归并、快排等)

博主在学习过程中深感基础的重要,经典排序算法是数据结构与算法学习过程中重要的一环,这里对笔试面试最常涉及到的7种排序算法(包括插入排序.希尔排序.选择排序.冒泡排序.快速排序.堆排序.归并排序)进行了详解.每一种算法都有基本介绍.算法原理分析.算法代码. 转载请注明出处:http://blog.csdn.net/lsh_2013/article/details/47280135 插入排序 1)算法简介 插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法.它的工作原理是通过