View difference between Paste ID: hN2SnEfP and
SHOW: | | - or go back to the newest paste.
1-
1+
import java.io.IOException;
2
import java.util.Arrays;
3
import java.util.Random;
4
 
5
public class Main {
6
 
7
 
8
    // сляние двух групп елементов одинокового размера
9
    void mergegroup(int a[], int n, int st1, int st2, int st3) {
10
      swapgroup(a, n, st1, st3);
11
                int take1 = 0;
12
                int take2 = 0;
13
                for (int i = 0; i < 2 * n; i++) {
14
                        if ((take2 == n) || ((take1 < n) && (a[take1 + st3] < a[take2 + st2]))) {
15
                                int t = a[st1 + i];
16
                                a[st1 + i] = a[take1 + st3];
17
                                a[take1 + st3] = t;
18
                                take1++;
19
                        } else {
20
                                int t = a[st1 + i];
21
                                a[st1 + i] = a[take2 + st2];
22
                                a[take2 + st2] = t;
23
                                take2++;
24
                        }
25
                }
26
        }
27
 
28
 
29
        // сортировка выбором
30
        void slowsort(int a[], int st, int en) {
31
                for (int i = st; i < en; i++)
32
                        for (int j = i + 1; j < en; j++) {
33
                                if (a[i] > a[j]) {
34
                                        int k = a[i];
35
                                        a[i] = a[j];
36
                                        a[j] = k;
37
                                }
38
                        }
39
        }
40
 
41
 
42
        // обмен местами двух групп елементов одинакового размера    
43
        void swapgroup(int a[], int n, int st1, int st2) {
44
                for (int i = 0; i < n; i++) {
45
                        int k = a[st1 + i];
46
                        a[st1 + i] = a[st2 + i];
47
                        a[st2 + i] = k;
48
                }
49
        }
50
 
51
 
52
        //слияние
53
        void merge(int[] a, int n) {
54
                if (n <= 16) {
55
                        slowsort(a, 0, n);
56
                        return;
57
                }
58
                
59
                // разрез на группы длиной корень из n
60
                int sizegroup = (int) Math.sqrt(n);
61
                int remainder = n % sizegroup;
62
                int numofgrp = n / sizegroup - 1;
63
                
64
                // поиск конца первого массива
65
                int posgap = 0;
66
                while ((posgap < sizegroup * numofgrp) && (a[posgap] <= a[posgap + 1]))
67
                        posgap++;
68
                        
69
                // обмен группы содержащей конец первого массива  с последней и обьединение с остатком
70
                swapgroup(a, sizegroup, numofgrp * sizegroup, posgap - posgap
71
                                % sizegroup);
72
                remainder += sizegroup;
73
                
74
                // сортировка групп по первому елементу(в случае равенства по последнему)
75
                for (int i = 0; i < numofgrp - 1; i++) {
76
                        int minnum = i;
77
                        for (int j = i + 1; j < numofgrp; j++)
78
                                if ((a[j * sizegroup] < a[minnum * sizegroup])
79
                                        || ((a[j * sizegroup] == a[minnum * sizegroup]) 
80
                                        && (a[(j + 1) * sizegroup - 1] < a[(minnum + 1) *sizegroup-1])))
81
                                      minnum = j;
82
                        swapgroup(a, sizegroup, i * sizegroup, minnum * sizegroup);
83
                }
84
                
85
                // поочередное слияние групп
86
                for (int i = 0; i < numofgrp - 1; i++) {
87
                        mergegroup(a, sizegroup, i * sizegroup, (i + 1) * sizegroup,
88
                                        numofgrp * sizegroup);
89
                }
90
                
91
                // сортировка конца массива
92
                slowsort(a, n - 2 * remainder, n);
93
                
94
                // поочередное слияние групп в обратную сторону 
95
                for (int i = n - 2 * remainder; i >= remainder; i -= remainder)
96
                        mergegroup(a, remainder, i - remainder, i, n - remainder);
97
                        
98
                // сортировка начала и конца массива
99
                slowsort(a, 0, 2 * remainder);
100
                slowsort(a, n - remainder, n);
101
        }
102
 
103
        // сортировка
104
        void sort(int[] a) {
105
                int n = a.length;
106
                for (int stp2 = 1; stp2 <= n; stp2 *= 2)
107
                        for (int i = 0; i < n; i += stp2) {
108
                                int size = Math.min(n, i + stp2) - i;  
109
                                swapgroup(a, size, 0, i);      // для удобства реализации перемещаем  
110
                                merge(a, size);                // требуемый кусок масcива в начало
111
                                swapgroup(a, size, 0, i);      // там его сортируем и возвращаем обратно
112
                        }
113
                if (n > 16)
114
                        merge(a, n);
115
 
116
        }
117
 
118
 
119
        void testsort() throws IOException {
120
                int n = 100000;
121
                int[] a = new int[n];
122
                Random st = new Random();
123
                for (int i = 0; i < n; i++)
124
                        a[i] = st.nextInt();
125
                int[] b = a.clone();
126
                Arrays.sort(b);
127
                sort(a);
128
                for (int i = 0; i < n; i++)
129
                        if (a[i] != b[i])
130
                                throw new AssertionError();
131
        };
132
 
133
 
134
        void run() throws IOException {
135
                for (int i = 0; i < 10; i++) {
136
                        testsort();
137
                }
138
        }
139
 
140
 
141
        public static void main(String[] args) throws IOException {
142
                new Main().run();
143
        }
144
}