Vestail
@Vestail
Software Engineer

Количество обращений к массиву в восходящей сортировки слиянием?

В книге "Алгоритмы на java" написано, что нисходящая(рекурсивная) и восходящая(итеративная) сортировки слиянием выполняет максимум 6N*lg(N) (логарифм двоичный) обращений к массиву. В одном из упражнений предлагается проверить это нарисовав график зависимости количества обращений к массиву от N . С нисходящей сортировкой все хорошо, но вот восходящая дает странные результаты.
Вот график для N = 1..512. Красная линия это 6N*lg(N), а черная фактические обращения к массиву.
4dtbV0f.png
Как видно в некоторых местах черная линия внезапно возрастает. Я заметил что это часто происходит при N = 2^x + 1.
Не понимаю в чем проблема, вот мой код(реализация самой сортировки полностью из книги):

public class MergeBUCount {

    private static Integer count; // переменная для счета обращений к массиву

    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
        for (int k = lo; k <= hi; k++) {
            aux[k] = a[k]; 
            count += 2; //по два обращения к массиву
        }
        int i = lo, j = mid+1;
        for (int k = lo; k <= hi; k++) {
            if      (i > mid)              {a[k] = aux[j++]; count += 2;} 
            else if (j > hi)               {a[k] = aux[i++]; count += 2;}
            else if (less(aux[j], aux[i])) {a[k] = aux[j++]; count += 4;}//обращения при сравнении + копировании
            else                           {a[k] = aux[i++]; count += 4;}
        }

    }
    public static void sort(Comparable[] a, int size) {
        int N = size;
        Comparable[] aux = new Comparable[N];
        for (int n = 1; n < N; n = n+n) {
            for (int i = 0; i < N-n; i += n+n) {
                int lo = i;
                int m  = i+n-1;
                int hi = Math.min(i+n+n-1, N-1);
                merge(a, aux, lo, m, hi);
            }
        }
    }

	public static void main(String[] args) {
                 Integer[] a = new Integer[N];
		//инициализация и тд...

		for (int i = 1; i <= N; i++) {
			StdRandom.shuffle(a); //перемешиваем массив
			count = 0;
			sort(a, i);

			double limit =  6 * i * (Math.log(i) / Math.log(2)); //граничное значение

			StdDraw.setPenColor(StdDraw.BLACK);
			StdDraw.point(i, count); //фактическая точка

			StdDraw.setPenColor(StdDraw.RED);
			StdDraw.point(i, limit); //граничная точка
		}
	}
  • Вопрос задан
  • 332 просмотра
Пригласить эксперта
Ответы на вопрос 1
angrySCV
@angrySCV
machine learning, programming, startuping
ну а в чём проблема то?
у график составлен для общего случая, по факту понятно он будет отличаться.
у вас в коде есть разные ветвления кода, которые дают разное количество обращений.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы