hdu--3743--归并排序<自顶向下&&自底向上>2种写法

有些人说 归并排序的递归版本实用性差 可读性强

非递归版本恰好相反

我觉得 也没那么明显差距吧....

其实非递归版本也不难理解的

假如 我们需要进行排序的数组的长度为 len 每次的子排序数组区间为size

那么我们首先将它拆成  len个size为1的小区间 然后2个相邻的进行合并merge排序 这时候 你需要判断一下 能否恰好一一合并 因为是奇数就不行了

这样 我们进行了第一趟归并 然后size*2 然后将size为2的2个相邻区间进行合并 继续判断..

一直到size>len 结束循环

...

传送----这篇写的不错

然后这题 我分别拿 递归的归并     非递归的归并进行了测试 没什么区别

其中 对于归并中的辅助数组我们可以选择直接开好足够大的静态数组 或者选择 new[right-left+1]来开  当然 我们也知道new的话会比较耗时 但同时也节省了内存

************************

差点忘记说这题了 毫无特色=-= 或许是因为我做了上一题的原因 只要你能读懂英文...#24 就是完全一样的啊...

 1 #include <iostream>
 2 using namespace std;
 3
 4 typedef long long LL;
 5 LL sum;
 6 const int size = 1000010;
 7 int arr[size];
 8 int temp[size];
 9
10 void merge_sort( int l , int r )
11 {
12     int p , q , mid , i;
13     if( r-l > 1 )
14     {
15         p = l;
16         mid = l + (r-l)/2;
17         q = mid;
18         i = l;
19         merge_sort( l , mid );
20         merge_sort( mid , r );
21         while( p<mid || q<r )
22         {
23             if( q>=r || ( p<mid && arr[p]<=arr[q]) )
24             {
25                 temp[i++] = arr[p++];
26             }
27             else
28             {
29                 temp[i++] = arr[q++];
30                 sum += mid-p;
31             }
32         }
33         for( i = l ; i < r ; i++ )
34             arr[i] = temp[i];
35     }
36 }
37
38 int main()
39 {
40     cin.sync_with_stdio(false);
41     int n;
42     while( cin >> n )
43     {
44         sum = 0;
45         for( int i = 0 ; i<n ; i++ )
46             cin >> arr[i];
47         merge_sort( 0 , n );
48         cout << sum << endl;
49     }
50     return 0;
51 }

 1 #include <iostream>
 2 using namespace std;
 3
 4 typedef long long LL;
 5 LL sum;
 6 const int size = 1000010;
 7 int arr[size];
 8 int temp[size];
 9
10 void merge( int left , int mid , int right )
11 {
12     int p , q , i;
13     p = i = left , q = mid+1;
14     while( p<=mid || q<=right )
15     {
16         if( q>right || ( p<=mid && arr[p]<=arr[q] ) )
17         {
18             temp[i++] = arr[p++];
19         }
20         else
21         {
22             temp[i++] = arr[q++];
23             sum += mid-p+1;
24         }
25     }
26     for( i = left ; i<=right ; i++ )
27     {
28         arr[i] = temp[i];
29     }
30 }
31
32 void merge_sort( int n )
33 {
34     int left , mid , right , len;
35     len = 1;
36     while( len <= n-1 )
37     {
38         left = 0;
39         while( left+len <= n-1 )
40         {
41             mid = left + len - 1;
42             right = mid + len;
43             if( right>n-1 )
44                 right = n-1;
45             merge( left , mid , right );
46             left = right + 1;
47         }
48         len *= 2;
49     }
50 }
51
52 int main()
53 {
54     cin.sync_with_stdio(false);
55     int n;
56     while( cin >> n )
57     {
58         sum = 0;
59         for( int i = 0 ; i<n ; i++ )
60         {
61             cin >> arr[i];
62         }
63         merge_sort( n );
64         cout << sum << endl;
65     }
66     return 0;
67 }

 1 #include <iostream>
 2 using namespace std;
 3
 4 typedef long long LL;
 5 LL sum;
 6 const int size = 1000010;
 7 int arr[size];
 8
 9 void merge( int left , int mid , int right )
10 {
11     int p , q , i;
12     p = left , q = mid+1;
13     int* temp = new int[right-left+1];
14     i = 0;
15     while( p<=mid || q<=right )
16     {
17         if( q>right || ( p<=mid && arr[p]<=arr[q] ) )
18         {
19             temp[i++] = arr[p++];
20         }
21         else
22         {
23             temp[i++] = arr[q++];
24             sum += mid-p+1;
25         }
26     }
27     for( int k = 0 , i = left ; i<=right ; i++ , k++ )
28     {
29         arr[i] = temp[k];
30     }
31     delete []temp;
32 }
33
34 void merge_sort( int n )
35 {
36     int left , mid , right , len;
37     len = 1;
38     while( len <= n-1 )
39     {
40         left = 0;
41         while( left+len <= n-1 )
42         {
43             mid = left + len - 1;
44             right = mid + len;
45             if( right>n-1 )
46                 right = n-1;
47             merge( left , mid , right );
48             left = right + 1;
49         }
50         len *= 2;
51     }
52 }
53
54 int main()
55 {
56     cin.sync_with_stdio(false);
57     int n;
58     while( cin >> n )
59     {
60         sum = 0;
61         for( int i = 0 ; i<n ; i++ )
62         {
63             cin >> arr[i];
64         }
65         merge_sort( n );
66         cout << sum << endl;
67     }
68     return 0;
69 }

today:

  寒门出贵子,

  白屋出公卿。

  将相本无种,

  男儿当自强。

时间: 2024-11-05 07:18:15

hdu--3743--归并排序<自顶向下&&自底向上>2种写法的相关文章

自顶向下归并排序和自底向上的归并排序

欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. 归并排序算法的使用情景 归并排序算法和快速排序算法是java.util.Arrays中使用的排序算.对于一般的基本数据类型,Arrays.sort函数使用双轴快速排序算法,而对于对象类型使用归并排序(准确的说使用的是TimSort排序算法,它是归并排序的优化版本).这样做的原因有两点,第一个原因,归并排序是稳定的,而快速排序不是稳定的.第二个原因,对于基本数据类型,排序的稳定性意义

HDU Today(三种写法)(最短路)

Description 经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强.这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市?浦镇陶姚村买了个房子,开始安度晚年了. 这样住了一段时间,徐总对当地的交通还是不太了解.有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格). 徐总经常会问蹩脚的英文问路:"Can you h

hdu 4920 快速矩阵相乘 以后得换一种写法了

[题意]:求两个矩阵相乘的结果 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 #define mod 3 6 7 int a[808][802],b[808][802]; 8 int c[808][808],n; 9 10 void mul() 11 { 12 for(int i=0; i<n; i++) 13 for(int j=0; j&

一维数组的三种写法

/** *一维 数组的几种写法 * 记住:①数组的左边不能有数字 *   ②数组的右边既然初始化了数组,那么就要赋值 */ //一维数组的标准格式 String[] arr1 = new String[]{"bo","li","jian"}; //上面的简写格式 String[] arr2 = {"bo","li","jian"}; //初始化容量 String[] arr3 = new

Android点击事件的四种写法

Android点击事件的四种写法 一.Android点击事件的四种写法 1.点击事件的第一种写法 .  写一个内部类.实现点击事件的接口 bt.setOnClickListener(new MyButtonListener()); 2.点击事件的第二种写法,匿名内部类 bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { callPhone(); } }); 3.点击事件的第三种

for循环的两种写法

教程 (https://tour.golang.org/methods/21) 里的 for 是这样写的: 其中 for 语句可以改写如下: for n, err := r.Read(b); err != io.EOF; n, err = r.Read(b) { fmt.Printf("n = %v err = %v b = %v\n", n, err, b) fmt.Printf("b[:n] = %q\n", b[:n]) } (当然,golang 里的 for

全面理解Javascript闭包和闭包的几种写法及用途

一.什么是闭包和闭包的几种写法和用法                                                       1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点: 1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态. 2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区. 简单的说,Javascript允许使用内部函数---即函数定义和函数表

Android Listener侦听的N种写法

Android中,View的Listener方法,在是否使用匿名类匿名对象时,有各种不同的写法. OnClickListener和其他Listener方法一样,都是View类的接口,重载实现后就能使用,其接口定义如下: [java] view plaincopyprint? public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was cli

CSU - 1356 Catch(dfs染色两种写法,和hdu4751比较)

Description A thief is running away! We can consider the city where he locates as an undirected graph in which nodes stand for crosses and edges stand for streets. The crosses are labeled from 0 to N–1. The tricky thief starts his escaping from cross