Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Двумерный массив. Совпадение строки и столбца, и сумма строки с отрицательным элементом 
V
    Опции темы
voral
Дата 30.6.2011, 22:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Не совсем правильное сравнение. Тут основное время занимает заполнение массива. Вот я почистил код. Каждый вариант запускается по три раза:
Код

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 15000
#define NN 3

int A[SIZE][SIZE];
void sum(int i)
{
    int j, result=0, fexists=0;
    for (j=0;j<SIZE;++j)
    {
        result+=A[i][j];
        if ((fexists==0)&&(A[i][j]<0)) fexists=1;
    }
}
void sum2(int i)
{
    int j, result=0, fexists=0;
    for (j=0;j<SIZE;++j)
    {
        result+=A[i][j];
        if (A[i][j]<0) fexists=1;
    }
}

int main()
{
    static int min = -1;
    static int max = 9;
    int i,j, fok;
    for (i=0;i<SIZE;++i)
        for (j=0;j<SIZE;++j)
            A[i][j]=min + rand()%(max-min+1);
    printf("Go\n");
    long c ;
    for (j=0;j<NN;++j)
    {
        c=clock();
        for (i=0;i<SIZE;++i)
            sum(i);
        c=clock()-c;
        printf("%ld\n",c);
    }
    for (j=0;j<NN;++j)
    {
        c=clock();
        for (i=0;i<SIZE;++i)
            sum2(i);
        c=clock()-c;
        printf("%ld\n",c );
    }
    
}

В результате у меня получися следующий вывод:
Код

Go
1630000
1630000
2930000
4120000
4120000
4130000

PM MAIL WWW   Вверх
Dov
Дата 1.7.2011, 00:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


аСинизатор
***


Профиль
Группа: Завсегдатай
Сообщений: 1721
Регистрация: 10.5.2003
Где: Эрец-Исраэль

Репутация: 11
Всего: 88



Цитата(voral @  30.6.2011,  22:34 Найти цитируемый пост)
В результате у меня получися следующий вывод:

А если как-то так попробовать?
Код
void sum(int i)
{
    int    j, result = 0;

    for(j = 0; j < SIZE; j++)
    {
        result += A[i][j];

        if(A[i][j] < 0)
            for(++j; j < SIZE; ++j)
                result += A[i][j];
    }
}



Это сообщение отредактировал(а) Dov - 1.7.2011, 00:10


--------------------
Тут вечности запах томительный,
И свежие фрукты дешевые, 
А климат у нас – изумительный, 
И только соседи – #уевые. 
                           Игорь Губерман.
PM   Вверх
voral
Дата 1.7.2011, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Да это будет быстрее. 

Это сообщение отредактировал(а) voral - 1.7.2011, 00:38
PM MAIL WWW   Вверх
newbieone
Дата 1.7.2011, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.3.2010

Репутация: 1
Всего: 1



Окей, практика показала увеличение производительности. А теперь теоретически это как-то можно объяснить? Я вот на прошлой странице пытался провести сравнение сложности алгоритмов "на бумажке" по количеству машинных операций, но, видимо, оно чего-то (многого) не учитывает.

Это сообщение отредактировал(а) newbieone - 1.7.2011, 09:47
PM MAIL   Вверх
voral
Дата 1.7.2011, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Цитата(newbieone @  1.7.2011,  09:45 Найти цитируемый пост)
Окей, практика показала увеличение производительности. А теперь теоретически это как-то можно объяснить? Я вот на прошлой странице пытался провести сравнение сложности алгоритмов "на бумажке" по количеству машинных операций, но, видимо, оно чего-то (многого) не учитывает.

Это о последнем алгоритме?
Там все просто. 
Сначала бежим по каждому элементу сторки, прибавляем его у сумме и сравниваем.
Как только нашли первый отрицательный элемент, нас уже не интересует есть ли еще отрицательные, по этому мы уходим в продолжение цикла где нет проверок на отрицательность, т.е. избавляемся от лишнй операции на каждую итерацию. (в предыдущем "быстром" варианте мы все равно проверяли флаг на равенство 1 или 0)
PM MAIL WWW   Вверх
newbieone
Дата 1.7.2011, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.3.2010

Репутация: 1
Всего: 1



voral, я имел ввиду математическое пояснение в терминах теории сложности вычислений (сложности алгоритмов).
Цитата
о последнем алгоритме?

Вашего первоначального и того, что предложил borisbn.

Это сообщение отредактировал(а) newbieone - 1.7.2011, 10:26
PM MAIL   Вверх
voral
Дата 1.7.2011, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Цитата(newbieone @ 30.6.2011,  19:26)
Теперь здесь:
Код

if (A[i][j]<0) fexists=1;

В худшем случае, когда все элементы отрицательны, имеем N присваиваний и N сравнений. 2N операций (ну или 3N, при тех же условиях, что и выше). Всё, конечно, поменяется, если вы скажете, что операция присваивания требует больше ресурсов, чем операция сравнения, но намного ли? Надо еще учесть, что далеко не всегда будет худший вариант, возможно, только один из элементов будет отрицательным, тогда будем иметь всего N+1 (2N+1) операций против 2N+1 (или 3N+1 соответственно).

а вы про этот пост где N расписывали smile
Ну тогда както так:
В худшем случае (кагда нет отрицательных числ)
мы имеем N сравнений и ни одногоприсваивания
В лучшем случае когда первый элемент в строке отрицателен имеем 1 сравнени и так же ни одного присваивания.

Итак имеем от 1 до N (в зависимости от позиции отрицательного числа) операций против от N до 2N

Добавлено через 4 минуты и 35 секунд
А вообще. Если целью поставить быстродействие и если позволяет процедура заполнения матрицы. Добавить еще один одномерный массив. При вводе нового элемента матрицы анализировать существование отрицательного значения и заносить номер строки в массив. Хотя в этом случае (такой ввод) моно собственну и суму здесь же считать. Но это уже теряем гибкость.
PM MAIL WWW   Вверх
newbieone
Дата 1.7.2011, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.3.2010

Репутация: 1
Всего: 1



voral, не могу с вами согласиться. У вас же там в условном операторе два условия через &&, сравнений соответственно будет в два раза больше, плюс вы забываете о сравнениях (о первом из них, второе из-за short-circuiting не будет вычисляться) уже после присваивания...
Если пытаться анализировать этим способом, имеем практически одинаковые результаты: N+2 до 2N против N+1 до 2N.
Код
if ( fexists == 0 && A[ i ][ j ] < 0 ) fexists = 1;

Если первый элемент отрицательней, проведется 2 сравнения, 1 присваивание, и после этого еще N-1 сравнений (т.к. fexists станет равным единице, то первое сравнение даст false и дальше выражение вычисляться не будет). В сумме N+1 сравнений и 1 присваивание, т.е. N+2 операций.
Если все положительные, то fexists всегда остается равным нулю и имеем 2N сравнений.
Код
if (A[i][j]<0) fexists=1;

Здесь если существует единственный отрицательный элемент, N сравнений и 1 присваивание, т.е. N+1 операция.
Если все отрицательные, N сравнений и N присваиваний, т.е. 2N операций.

Другое дело, что способ, судя по практическим результатам, не совсем верен. Практика с теорией расходятся...

Это сообщение отредактировал(а) newbieone - 1.7.2011, 13:50
PM MAIL   Вверх
voral
Дата 1.7.2011, 17:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Цитата(newbieone @  1.7.2011,  13:47 Найти цитируемый пост)
voral, не могу с вами согласиться. У вас же там в условном операторе два условия через &&, сравнений соответственно будет в два раза больше, плюс вы забываете о сравнениях (о первом из них, второе из-за short-circuiting не будет вычисляться) 

видимо мы о разном. Я разложил именно поселедний самый шустрый вариант.
Этот же случай 
Код

if ( fexists == 0 && A[ i ][ j ] < 0 ) fexists = 1;

я понимаю так. 
Самое плохое когда нет отрицательных
два сравнения, сложение энд т.е. 3N - операций 
Самое хорошее когда первое отрицательное
первая итерация  два сравнения, сложение энд и присваивание 4 операции
остальные итерации одно сравнение
т.е. (N-1)+4
Т.е получаем от N+3 до 3N  против N+1 до 2N, (кстати операция операции рознь и && совсем не одно и то же что сравнение)

К тому же. У нас диапазон чисел от -1 до 9. При размере матрицы 15000 шанс что в строке не будет отрицательных чисел очень мал. Т.е. скорее всего исходный случай с одним сравнением будет стремиться именно к 2N, В то время как где два сравнения врят ли дотянет до 3N...
Думаю если уменьшить размер, или увеличить диапазон чисел.... ТО может быть преимущество перейдет.

Это конечно все просто рассуждения можно попробовать посмотреть на практике. Дизасемблировать оба варианта, чтоб посмотреть как это выглядит на асме; и сделать с промежуточным выводом значений... smile
PM MAIL WWW   Вверх
newbieone
Дата 1.7.2011, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.3.2010

Репутация: 1
Всего: 1



Хехе, ну вот, а говорили на предыдущей странице, что
Цитата
Тут все бесспорно.

smile
PM MAIL   Вверх
voral
Дата 1.7.2011, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Вот еще небольшой тестик
Код

#include <stdio.h>
int main()
{
    int size=15000, count=15000;
    int min=-1, max = 9;
    int i,j,k;
    int stat_max=0,stat_average=0,stat_count=0;
    

    srand(time(NULL));
    for (i=0;i<count;++i)
        for (j=0;j<size;++j)
        {
            k=rand()%(max-min+1)+min;
            if (k<0)
            {
                if (stat_max<j) stat_max=j;
                stat_average+=j;
                ++stat_count;
                break;
            }
        }
        printf("Negative exists in %d from %d    Max=%d Average=%d\n",stat_count,count,stat_max,stat_average/count);

}

Результат:
Код

Negative exists in 15000 from 15000    Max=100 Average=10


Добавлено через 2 минуты и 54 секунды
При размере строки 11 все равно неплохой результат:
Цитата

Negative exists in 9834 from 15000    Max=10 Average=4


PM MAIL WWW   Вверх
Kruger2
Дата 11.7.2011, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



Через несколько глав снова вернулся к этому заданию, но уже в более продвинутом виде. 
Теперь необходимо решить туже задачу, с динамическим выделением памяти.

Тут я взял за основу код уважаемого voral, т.к. удобнее дописать функциюsmile

вот основа:


Код

#include <stdio.h>
#include <stdlib.h>
#define SIZE 8
int A[SIZE][SIZE]= {
                           { 2, 2, 2, 2, 2, 2, 2, 2 },
                           { 2, 2, 2, 6, 0, -8, 3, 5 },
                           { 2, 2, 1, 8, 1, 4, 9, 3 },
                           { 2, 2, 8, 5, 2, 0, 0, 6 },
                           { 2, 2, 1, 3, 9, 3, 9, 1 },
                           { 2, 2, 4, 9, 1, -6, 4, 9 },
                           { 2, 2, 9, 0, 9, 4, 8, 8 },
                           { 2, 2, 3, 2, 8, 2, 8, 0 }
                           };;
                               
void compareLine(int i)
{
    int j;
    for (j=0;j<SIZE;++j)
        if (A[i][j]!=A[j][i])
            return;
    printf("K=%d\n",i+1);
}
void sum(int i)
{
    int j, result=0, fexists=0;
    for (j=0;j<SIZE;++j)
    {
        result+=A[i][j];
        if (A[i][j]<0) fexists=1;
    }
    if (fexists==1) printf("sum line %d: %d\n",i+1,result);
}
int main()
{
    int i;
    for (i=0;i<SIZE;++i)
    {
        compareLine(i);
        sum(i);
    }

system("pause");
return 0;
}



Вот что я добавил: 


Код

#include <stdio.h>
#include <stdlib.h>
#define SIZE 8
int A[SIZE][SIZE]= {
                           { 2, 2, 2, 2, 2, 2, 2, 2 },
                           { 2, 2, 2, 6, 0, -8, 3, 5 },
                           { 2, 2, 1, 8, 1, 4, 9, 3 },
                           { 2, 2, 8, 5, 2, 0, 0, 6 },
                           { 2, 2, 1, 3, 9, 3, 9, 1 },
                           { 2, 2, 4, 9, 1, -6, 4, 9 },
                           { 2, 2, 9, 0, 9, 4, 8, 8 },
                           { 2, 2, 3, 2, 8, 2, 8, 0 }
                           };;
                           
void malloc (int** Array)
{
    
    Array = (int **)malloc(SIZE*sizeof(int* ));
         if(!Array) 
     {
       printf("Memory not allocated. \n");
      return;
     }
     int i;
     for (i=0; i< SIZE; i++)
     {
       Array[i]= (int *) malloc(SIZE*sizeof (int ));
       if (!Array[i])
       {
         printf("Memory not allocated2 \n");
         return;
       }
     }
}

void freememory(int** Array)
{
       int i;
       for(i=0; i<SIZE; i++)
       {
         free (Array[i]);
       }
       free(Array);
}
     
void compareLine(int i)
{
    int j;
    for (j=0;j<SIZE;++j)
        if (A[i][j]!=A[j][i])
            return;
    printf("K=%d\n",i+1);
}
void sum(int i)
{
    int j, result=0, fexists=0;
    for (j=0;j<SIZE;++j)
    {
        result+=A[i][j];
        if (A[i][j]<0) fexists=1;
    }
    if (fexists==1) printf("sum line %d: %d\n",i+1,result);
}
int main()
{
    int i;
    for (i=0;i<SIZE;++i)
    {
        compareLine(i);
        sum(i);
    }

system("pause");
return 0;
}



Значит функция maloc вроде бы написана без синтаксических ошибок, ибо компилятор не матерится. Однако как проверить правильно ли выделяется память я не знаю, поэтому прошу провеhить код функции maloc

Далее, то что код функции freememory должен находится не тут я понимаю (ибо выделил память и тут же аннулировал), но где она должна находиться? После main? прямо перед main? Будьте добры, подскажите.
PM MAIL   Вверх
voral
Дата 11.7.2011, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Цитата(Kruger2 @  11.7.2011,  12:42 Найти цитируемый пост)
Далее, то что код функции freememory должен находится не тут я понимаю (ибо выделил память и тут же аннулировал), но где она должна находиться? После main? прямо перед main? Будьте добры, подскажите. 

При выделении памяти ты заносишь адрес в переменную. Переменная имеет свою область видимости. А также, если она не глобальная, может пропасть при выходе из функции в которой существует.

Ты сделал свои обертки для malloc и free.  Желательно их вызывать (для одной области) в  рамках однной функции - в которой живет переменная хранящая адрес.

Однако, могут быть ситуации когда ты передаешь адрес в другую функцию/поток, а из той в которой создал уходишь... Тогда уже там надо позаботиться об освобождении.
Например
Код

myType* getNewObject()
{
  myType* Result= (myType*)malloc(sizeof(myType));
  return Result;
}

Переменная Result будет уничтожена. Но память останется выделенной.....
PM MAIL WWW   Вверх
Kruger2
Дата 11.7.2011, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



Т.е. мне надо вызвать функцию малок внутри каждой из моих двух функций или вызвать её в мейне перед выполнением двух других функций?

Добавлено @ 14:40
и получается освобождать память тоже не надо, т.к. нет глобальных переменных ?

Это сообщение отредактировал(а) Kruger2 - 11.7.2011, 14:40
PM MAIL   Вверх
Kruger2
Дата 11.7.2011, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 9.1.2011

Репутация: нет
Всего: нет



Код

#include <stdio.h>
#include <stdlib.h>
#define SIZE 8
int A[SIZE][SIZE]= {
                           { 2, 2, 2, 2, 2, 2, 2, 2 },
                           { 2, 2, 2, 6, 0, -8, 3, 5 },
                           { 2, 2, 1, 8, 1, 4, 9, 3 },
                           { 2, 2, 8, 5, 2, 0, 0, 6 },
                           { 2, 2, 1, 3, 9, 3, 9, 1 },
                           { 2, 2, 4, 9, 1, -6, 4, 9 },
                           { 2, 2, 9, 0, 9, 4, 8, 8 },
                           { 2, 2, 3, 2, 8, 2, 8, 0 }
                           };;
                           
void inMemory (int** Array)
{
    
    Array = (int **)malloc(SIZE*sizeof(int* ));
         if(!Array) 
     {
       printf("Memory not allocated. \n");
      return;
     }
     int i;
     for (i=0; i< SIZE; i++)
     {
       Array[i]= (int *) malloc(SIZE*sizeof (int ));
       if (!Array[i])
       {
         printf("Memory not allocated2 \n");
         return;
       }
     }
}

void freeMemory(int** Array)
{
     
       int i;
       for(i=0; i<SIZE; i++)
       {
         free (Array[i]);
       }
       free(Array);
}
     
void compareLine(int i)
{
    int j, b,c;
      void inMemory(int** b);
    for (j=0;j<SIZE;++j)
        if (A[i][j]!=A[j][i])
            return;
    printf("K=%d\n",i+1);
      void freeMemory(int** c);
}
void sum(int i)
{
    int j, result=0, fexists=0, b, c;
      void inMemory(int** b);
    for (j=0;j<SIZE;++j)
    {
        result+=A[i][j];
        if (A[i][j]<0) fexists=1;
    }
    if (fexists==1) printf("sum line %d: %d\n",i+1,result);
      void freeMemory(int** c);
}
int main()
{
    int i;
    for (i=0;i<SIZE;++i)
    {
        compareLine(i);
        sum(i);
    }

system("pause");
return 0;
}



Вызываю внутри каждой функции сначала inmemory, затем freememory (решил переименовать малок в инмемори, что бы внести ясность)

Это сообщение отредактировал(а) Kruger2 - 11.7.2011, 14:53
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0877 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.