排序和查找(5)-归并排序

归并排序是一个分治算法。归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。merg() 函数是用来合并两个已有序的数组.  是整个算法的关键。看下面的描述对mergeSort函数的描述:

MergeSort(arr[], l,  r)
If r > l
     1. 找到中间点,讲arr分为两部分:
             middle m = (l+r)/2
     2. 对一部分调用mergeSort :
             Call mergeSort(arr, l, m)
     3.对第二部分调用mergeSort:
             Call mergeSort(arr, m+1, r)
     4. 合并这两部分:
             Call merge(arr, l, m, r)

下图来自维基百科,显示了完整的归并排序过程。例如数组{38, 27, 43, 3, 9, 82, 10}.

下面是C程序的实现:

 1 #include<stdlib.h>
 2 #include<stdio.h>
 3
 4 /*合并arr的左右两部分: arr[l..m] 和 arr[m+1..r]  */
 5 void merge(int arr[], int l, int m, int r)
 6 {
 7     int i, j, k;
 8     int n1 = m - l + 1;
 9     int n2 =  r - m;
10
11     /* create temp arrays */
12     int L[n1], R[n2];
13
14     /* 复制数据到 L[] 和 R[] */
15     for(i = 0; i < n1; i++)
16         L[i] = arr[l + i];
17     for(j = 0; j <= n2; j++)
18         R[j] = arr[m + 1+ j];
19
20     /* 将两部分再合并到 arr[l..r]*/
21     i = 0;
22     j = 0;
23     k = l;
24     while (i < n1 && j < n2)
25     {
26         if (L[i] <= R[j])
27         {
28             arr[k] = L[i];
29             i++;
30         }
31         else
32         {
33             arr[k] = R[j];
34             j++;
35         }
36         k++;
37     }
38
39     /* 复制剩下的部分 L[] */
40     while (i < n1)
41     {
42         arr[k] = L[i];
43         i++;
44         k++;
45     }
46
47     /* 复制剩下的部分 R[] */
48     while (j < n2)
49     {
50         arr[k] = R[j];
51         j++;
52         k++;
53     }
54 }
55
56 /* 对数据arr排序,从l到r */
57 void mergeSort(int arr[], int l, int r)
58 {
59     if (l < r)
60     {
61         int m = l+(r-l)/2; //和 (l+r)/2 一样, 但是可以避免溢出在 l 和 r较大时
62         mergeSort(arr, l, m);
63         mergeSort(arr, m+1, r);
64         merge(arr, l, m, r);
65     }
66 }
67
68 void printArray(int A[], int size)
69 {
70     int i;
71     for (i=0; i < size; i++)
72         printf("%d ", A[i]);
73     printf("\n");
74 }
75
76 /*测试程序 */
77 int main()
78 {
79     int arr[] = {12, 11, 13, 5, 6, 7};
80     int arr_size = sizeof(arr)/sizeof(arr[0]);
81
82     printf("Given array is \n");
83     printArray(arr, arr_size);
84
85     mergeSort(arr, 0, arr_size - 1);
86
87     printf("\nSorted array is \n");
88     printArray(arr, arr_size);
89     return 0;
90 }

时间复杂度:O(nlogn) 空间复杂度:O(n)    稳定排序

归并排序的应用:

1) 对链表进行排序。其它排序算法如堆排序和快速排序不能对链表排序。参考:使用归并排序对链表进行排序

2) 计算一个数组中的逆序对。剑指offer(09)-数组中的逆序对[分治]

3) 外排序

时间: 2024-10-12 12:51:37

排序和查找(5)-归并排序的相关文章

所有的排序、查找算法

import javax.mail.Part; /** * 顺序查找.排序 * * @author 曾修建 * @version 创建时间:2014-7-30 下午04:15:10 */ public class SequentialSearch { public static void main(String[] args) { Integer[] a = {1,2,3,4,5,7,6,88}; //二分查找非递归 System.out.println( "二分查找非递归实现 位置 : &qu

数据结构与算法-排序与查找(java描述)

在软件开发中,有两个常见的任务,一个是某一组中查找某个特定的元素,另一个是将某一组元素按照特定的顺序排序.我们可以使用多种算法来完成这些任务,而这些算法的差异也是值得我们去仔细研究的,接下来我们探究一下这些算法. 一.查找 1.1.线性查找法 线性查找就是通过索引对数组data的每个元素进行遍历,如果发现要找的目标元素和数组data中的某个元素相同时,就返回已经查找到,当然,我们也是可以改进一下,就是直接把找到的元素返回即可. public static <T extends Comparabl

常用排序,查找,树算法集锦

本文转载至  http://blog.csdn.net/zhangkongzhongyun/article/details/8080466 分类: c语言2012-10-17 11:16 275人阅读 评论(0) 收藏 举报 算法google 前面写了好些排序,红黑树,B 树算法的文章,还剩下查找这一大块没有写,查找相关的算法代码已经实现,但是却没有写查找算法日志的闲情了,只好先在这里放出代码来,以后有空有闲情再补上吧. 算法代码 Google 仓库:点击这里 已完成算法 排序 插入排序 希尔排

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

leetcode 题解:Search in Rotated Sorted Array II (旋转已排序数组查找2)

题目: Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed? Would this affect the run-time complexity? How and why? Write a function to determine if a given target is in the array. 说明: 1)和1比只是有重复的数字,整体仍采用二分查找 2)方法二 : 实现:  

java 数组比较,元素的比较,Comparable,Comparator比较的应用实现,排序,查找示例

java 数组比较,元素的比较,自定义Comparator的实现,排序,查找示例 package org.rui.array.compar; import java.util.Arrays; import java.util.Random; import org.rui.generics.anonymity.Generator; /** * 程序设计的基本目标是"将保持不变的事物与会发生改变的事物相分离" * 而这是,不变的是通用的排序算法,变化的是各种对象相互比较的方式, * 因此,

leetcode题解:Search in Rotated Sorted Array(旋转排序数组查找)

题目: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). You are given a target value to search. If found in the array return its index, otherwise return -1. You may assume no du

插入排序、冒泡排序、选择排序、希尔排序、快速排序、归并排序、堆排序和LST基数排序——C++实现

首先是算法实现文件Sort.h,代码如下: /* * 实现了八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 * 以及快速排序.归并排序.堆排序和LST基数排序 * @author gkh178 */ #include <iostream> template<class T> void swap_value(T &a, T &b) { T temp = a; a = b; b = temp; } //插入排序:时间复杂度o(n^2) template<

链表排序,查找,洗牌,旋转

链表的排序和查找可以使用Collections类 排序,public static sort(List<E> list1)不实现Comparable的结点不能用 查找,int binarySearch(List<E> list2,T Key,CompareTo<T>) 都是第一个放链表对象,第二个放结点 结点要实现接口Comparable接口的compareTo方法作为比较标准,后面的参数可以写null (比如Sring内部已经实现了compareTo方法,就是按照字典