三分归并排序

一直以来做题目用的都是sort函数,突然要自己写归并算法确实挺头痛的。

尤其是一开始连归并排序是什么都搞不懂,最后看了半天书终于明白二分归并,那么三分的也就呼之欲出了

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5
  6 #define N 100005
  7 int a[N],b[N],c[N];
  8
  9 //这个函数不断用来找三段区域中的最小值的那个点,以便用来将找到的点存入b数组中
 10 int minn(int i,int j,int l)
 11 {
 12     if(a[i]<a[j]&&a[i]<a[l])
 13         return 1;
 14     else if(a[j]<a[i]&&a[j]<a[l])
 15         return 2;
 16     else
 17         return 3;
 18 }
 19 //每次合并三个区域后,一个区域率先完成,那接下来两个区域继续合并就用下面这个函数
 20 void mergeTwoArray(int st1,int la1 , int st2, int la2 ,int k,int *a,int *b)
 21 {
 22     int i = st1,j=st2;
 23     while(i<=la1&&j<=la2){
 24         if(a[i]<a[j])
 25             b[k++] = a[i++];
 26
 27         else
 28             b[k++] = a[j++];
 29     }
 30     if(i<=la1)
 31         while(i<=la1)
 32             b[k++] = a[i++];
 33     if(j<=la2)
 34         while(j<=la2)
 35             b[k++] = a[j++];
 36 }
 37 //合并三段区域的过程
 38 void mov(int x,int m,int n,int y,int *a,int *b)
 39 {
 40     int i=x,j=m+1,l=n+1,k=x;
 41     while(i<=m&&j<=n&&l<=y){
 42         int t = minn(i,j,l);
 43         if(t == 1)
 44             b[k++] = a[i++];
 45
 46         else if(t == 2)
 47             b[k++] = a[j++];
 48
 49         else
 50             b[k++] = a[l++];
 51     }
 52
 53     if(i>m)
 54         mergeTwoArray(j,n,l,y,k,a,b);//说明左侧区域元素用尽,带入参数继续合并其他两个区域,后面else if中的语句也是同一个意思
 55     else if(j>n)
 56         mergeTwoArray(i,m,l,y,k,a,b);
 57     else
 58         mergeTwoArray(i,m,j,n,k,a,b);
 59 }
 60
 61 void cpy(int x,int y,int *a,int *b)
 62 {
 63     for(int i=x;i<=y;i++)
 64         a[i] = b[i];
 65 }
 66
 67 //总的归并过程
 68 void mergeSort(int x,int y,int *a)
 69 {
 70     if(x>=y)
 71         return;
 72     int thi1 = (y-x)/3+x;
 73     int thi2 = y-(y-x)/3;
 74     mergeSort(x,thi1,a);//合并最左边
 75     mergeSort(thi1+1,thi2,a);//合并中间区域
 76     mergeSort(thi2+1,y,a);//合并右侧区域
 77
 78     //将分割的三块区域不断找到最小值后从a数组移入b数组
 79     mov(x,thi1,thi2,y,a,b);
 80     //将b数组的元素重新移回a数组
 81     cpy(x,y,a,b);
 82 }
 83
 84 int main()
 85 {
 86     int T;
 87     printf("输入测试样例数: ");
 88     scanf("%d",&T);
 89     while(T--){
 90         int n;
 91         printf("输入元素的个数: ");
 92         scanf("%d",&n);
 93         printf("依次输入所有的元素:");
 94         for(int i=0;i<n;i++){
 95             scanf("%d",a+i);
 96         }
 97         mergeSort(0,n-1,a);
 98         printf("输出三分排序后的结果:\n");
 99         for(int i=0;i<n;i++){
100             printf("%d ",a[i]);
101         }
102         puts("");
103     }
104     return 0;
105 }
时间: 2024-10-10 21:25:47

三分归并排序的相关文章

排序(6)---------归并排序(C语言实现)

归并排序: 归并操作,也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作.归并排序算法依赖归并操作. 归并操作的过程如下: (1) 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 (2) 设定两个指针,最初位置分别为两个已经排序序列的起始位置 (3) 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 (4) 重复步骤3直到某一指针到达序列尾 (5) 将另一序列剩下的所有元素直接复制(抄)到合并序列尾 简单的说,就是将一个序列不断的进行

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

codeforces 414C C. Mashmokh and Reverse Operation(归并排序求逆序对)

题目链接: C. Mashmokh and Reverse Operation time limit per test 4 seconds memory limit per test 512 megabytes input standard input output standard output Mashmokh's boss, Bimokh, didn't like Mashmokh. So he fired him. Mashmokh decided to go to university

归并排序(Merge Sort)

更详细的请看这篇博文:http://www.cnblogs.com/jingmoxukong/p/4308823.html 我只做个人学习和补充 基于分治法的排序,比较简单.个人感觉其核心是数组左右拆分之后类似队列的比较.类似两两合并之类的算法都可以参考 分为3个步骤,拆开为树结构遍历->向上合并 特别做了一张gif来更好的理解归并排序 左边集合比较通过就左边索引前进,右边集合比较通过则右边索引前进 比较结果放入结果数组中 最后如果多出一个就把这一个直接加入结果数组 为了易于学习,代码直接使用了

两路归并排序

链表两路归并 #include<iostream> #include<assert.h> using namespace std; struct node { int val; node * next; node(int v) { val=v; next=NULL; } }; node * merge(node* list1 , node * list2) { assert(list1!=NULL&&list2!=NULL);//括号中是希望出现的正确的情况  no

算法基础:分治模式,归并排序ΘΘΘΘΘΘ知识小结

1.分治模式在每层递归时都有三个步骤:分解,解决,合并 2.归并排序算法完全遵循分治模式: 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列 解决:使用归并排序递归的排序两个子序列 合并:合并两个已排序的子序列以产生已排序的答案 3.分析分治算法所需要的时间计算: 假设T(n)是规模为n的一个问题的运行时间,若问题足够小,如对某个常量c,n≦c,则直接求解需要常量时将,我们将其写作Θ(1).假设吧原问题分解成a个子问题,每个子问题的规模是原问题的1/b(对归并排序,a和b都为2,然

归并排序

基本思想: 1)首先需要一个临时空间temp用来存放合并后的元素,长度为排列好的元素总个数. 2)取两个指针,分别为左右部分数组的头元素. 3)比较指针指向元素,将较小(较大)的那个放入temp(注意相等时不做元素位置交换),并将两指针向后移动一个step. 4)循环步骤3直到其中一段数组没有剩余元素(其中一段被遍历完). 5)将还有元素剩余的另外一半数组元素直接放入temp尾部 代码实现: public static void merge(int[] list, int left, int m

基本排序算法(冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 希尔排序)

冒泡排序 public static void bubbleSort(int[] arr){ int lgn = arr.length; for (int i = 0; i < lgn - 1; i++) { for (int j = 0; j < lgn - 1 - i; j++) { if(arr[j] > arr[j + 1]){ int temp = arr[j + 1]; arr[j + 1] = arr[j]; arr[j] = temp; } } } } 选择排序 publ

利用Python实现归并排序

利用python进行归并排序,摘抄自http://blog.csdn.net/minxihou/article/details/51821052 "代码真的不是一气呵成的,而且也不是想当然写出来的.可能需要反复断点中断来查看是否有逻辑错误.在理解了问题的基础下我们需要先把大体的代码框架最好先写出来,特别是主要的逻辑判断语句.但是不需要太care我循环体或者判断里面语句怎么实现,当你把这一步做到的时候能避免很多不必要的错误发生." 1 import random 2 3 def Conf