4.8 合并排序法

4-8 MergeSort.c

 1 #include <stdio.h>
 2 #include "4-1 CreateData.c"    //生成随机数的函数
 3 #define ARRAYLEN 10    //需要排序的数据元素数量
 4 void MergeStep(int a[],int r[],int s,int m,int n) //相邻有序段合并
 5 {
 6     int i,j,k;
 7     k=s;
 8     i=s;
 9     j=m+1;
10     while(i<=m && j<=n) //当两个有序表都未结束时,循环比较
11     {
12         if(a[i]<=a[j]) //当较小的元素复制到R中
13             r[k++]=a[i++];
14         else
15             r[k++]=a[j++];
16     }
17     while(i<=m) //将未合并的部分复制到R中
18         r[k++]=a[i++];
19     while(j<=n)
20         r[k++]=a[j++]; //将未合并的部分复制到R中
21 }
22 void MergePass(int a[],int r[],int n,int len) //完成一遍合并的函数
23 {
24     int s,e;
25     s=0;
26     while(s+len<n) //至少有两个有序段
27     {
28         e=s+2*len-1;
29         if(e>=n) //最后一段可能少于len个结点
30             e=n-1;
31         MergeStep(a,r,s,s+len-1,e); //相邻有序段合并
32         s=e+1; //下一对有序段中左段的开始下标
33     }
34     if(s<n) //还剩一个有序段,将其从A中复制到R中
35         for(;s<n;s++)
36             r[s]=a[s];
37 }
38 void MergeSort(int a[],int n)
39 {
40     int *p;
41     int len=1;     //有序序列的长度
42     int f=0;    //变量f作标志
43     if(!(p=(int *)malloc(sizeof(int)*n)))    //分配内存空间,保存临时数据
44     {
45         printf("分配临时内存失败!\n");
46         exit(0);
47     }
48     while(len<n)
49     {
50         if(f)   //交替地在A和P之间来回合并
51             MergePass(p,a,n,len);    //调用MergePass,对p合并到a
52         else
53             MergePass(a,p,n,len);    //调用MergePass,对a合并到p
54         len*=2;    //增加有序序列长度
55         f=1-f; //使f值在0和1之间切换
56     }
57     if(f)    //若进行了排序
58         for(f=0;f<n;f++)    //将数组p中的数据复制到数组a
59             a[f]=p[f];
60     free(p); //释放分配的内存
61 }
62
63 int main()
64 {
65     int i,a[ARRAYLEN];    //定义数组
66     for(i=0;i<ARRAYLEN;i++)    //清空数组
67         a[i]=0;
68     if(!CreateData(a,ARRAYLEN,1,100))    //判断生成随机数是否成功
69     {
70         printf("生成随机数不成功!\n");
71         getch();
72         return 1;
73     }
74     printf("原数据:");     //输出生成的随机数
75     for(i=0;i<ARRAYLEN;i++)
76         printf("%d ",a[i]);
77     printf("\n");
78     MergeSort(a,ARRAYLEN);    //调用合并排序函数
79     printf("排序后:");
80     for(i=0;i<ARRAYLEN;i++)    //输出排序后的结果
81         printf("%d ",a[i]);
82     printf("\n");
83     getch();
84     return 0;
85 }
时间: 2024-10-26 15:17:06

4.8 合并排序法的相关文章

【合并排序法】

/* 合并排序法 */ #include <stdio.h> #include <stdlib.h> #include <time.h> #define MAX1 10 #define MAX2 10 #define SWAP(x,y) {int t; t = x; x = y; y = t;} int partition(int[], int, int); void quicksort(int[], int, int); void mergesort(int[], i

合并排序法

public class Merge { //递归分成小部分 public void merge_sort(int[] arrays,int start,int end){ if(start<end){ int m=(start+end)/2; merge_sort(arrays,start,m); merge_sort(arrays,m+1,end); combin_arrays(arrays,start,m,end); } } //合并数组 public void combin_arrays

算法之合并排序

上篇文章讲到插入排序算法,是一个标准的增量方法:在排好的子数组后,将元素插入,形成新的数组.今天要介绍的是一种新方法:分治法. 分治法,将原问题划分成n个规模较小而结构与原问题相似的子问题:递归地解决这些子问题,然后再合并其结果,就能得到原问题的解.在每一层递归上都会有三个步骤: 分解:将原问题分解成一系列子问题: 解决:递归地解决各子问题,若子问题足够小,则直接求解: 合并:将子问题的结果合并成原问题的解. 合并排序算法完全依照了上述模式,直观的操作如下: 分解:将n个元素分成各含n/2个元素

递归与分治-合并排序、快速排序以及循环赛问题

合并排序 合并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的.然后再把有序子序列合并为整体有序序列. 递归方法: 基本思想是:将待排序元素分成大小一致相同的2个子集和,分别对两个子集和进行排序,最终将排好序的子集合并成所需要的排好序的集合 package com.gqx.arithmetic.Recursion; public class Recursion_Merge2 { private static void mergeSort(

Atitit.现实生活中最好使用的排序方法-----ati排序法总结

1. 现在的问题 1 2. 排序的类别::插入排序//交换排序//选择排序(每次最小/大排在相应的位置  )//归并排序//基数排序 1 3. 选择排序法  (垃圾...不好使用) 2 4. 堆排序-(雅十垃圾...不好用) 2 5. 希尔排序法 (雅十垃圾...不好用) 3 6. 冒泡排序法 (雅十垃圾...不好用) 3 7. 快速排序法 (雅十垃圾...不好用) 3 8. 归并排序法 (雅十垃圾...不好用) 3 9. 插入排序法 ( 勉强能使用,要是加个2分寻找走ok兰..) 3 10. 

单链表合并排序实现

原题是要实现两个已排序的单链表合并后还是已排序,但我在网上查了很多都无法直接实现.对于初学者给个算法是没多大用的,下面给出完整代码.主要思路就是先接尾再排序.而一般书是直接开始分情况if...else if...else嵌套排序.比较复杂. /*关键:两个有序单链表的合并:其实本程序可以实现任意两个单链表的合并排序,思想就是 *1.建两个链表2.合并两个链表3.对合并后的链表排序4.打印 *关键函数:linkDList 直接连接两个链表;selectsort 单链表的选择排序*/ #define

算法之合并排序(mergeSort)

合并排序算法在结构上是递归的,采用分治策略:就是将原有的问题划分为 n 个规模较小但结构与原问题相似的子问题,递归地解决这些子问题,然后合并其结果,就得到原问题的解. 合并排序的模式一般如下: 1.分解:将 n 个元素分解为各含 n/2 个元素的两个序列: 2.解决:用分治排序法对两个子序列递归地排序: 3.合并:合并两个已排好序的子序列得到排序结果. 在对子序列递归的过程中,当子序列元素数为1时,递归结束. 合并排序算法的时间复杂度为O(nlgn) 1 void merge(int* a, i

合并排序和快速排序

/* 合并排序 O(n*lgn) */ #include <iostream> using namespace std; #define MAXN 100 int a[MAXN]; void Merge(int a[MAXN],int left,int mid,int right) { int i,j,k; int n1=mid-left+1; int n2=right-mid; int L[MAXN],R[MAXN]; for(i=1;i<=n1;i++) L[i]=a[left+i-

ACM ICPC 2011–2012, NEERC, Northern Subregional Contest J. John’s Inversions(合并排序求逆序数对数)

题目链接:http://codeforces.com/gym/100609/attachments 题目大意:有n张牌,每张牌有红色和蓝色两面,两面分别写了一些数字,同种颜色的任意两个数字若排在前面的数字比排在后面的数字大就叫做一对逆序数.求怎样排序得到的逆序数对最少. 解题思路:其中一种颜色的数字是顺序且这种颜色数字相同时对应的另一种颜色的数字是顺序时得到的逆序数对数最少.难点在于求逆序数对数.因为数量很大O(n^2)复杂度不能满足,这里根据合并排序的原理求解每个数字前面有多少个比它大的数字,