Дружественные и inline функции



Дружественные функции имеют доступ к закрытым и защищённым полям класса. К примеру, создадим класс точки и пусть у неё будет скрыта координата z.

class point {

           double z;

public:

           double x,y;

           point () {

                           x=0; y=0; z=0;

           }

};

Пусть у нас снаружи будет функция, которая выводит точку:

void dim3print(point c) {

           cout << "(" << c.x << "," << c.y << "," <<c.z << ")" << endl;

}

Но работать эта функция не будет, т.к. она использует скрытую координату z- её можно использовать только внутри класса. Чтобы всё-таки это работало, нужно внутри класса объявить эту функцию в виде прототипа как дружескую:

friend void dim3print(point);

Тогда всё будет работать. Вот пример полной программы:

#include <iostream>

#include <cmath>

using namespace std;

class point {

           double z;

public:

           double x,y;

           point () { x=0; y=0; z=0; }

           friend void dim3print(point);

};

void dim3print(point c) {

           cout << "(" << c.x << "," << c.y << "," <<c.z << ")" << endl;

}

int main() {

           setlocale(0,"");

           point x; x.x=2; x.y=3; dim3print(x);

           system("pause");

}

Помимо дружеских функций есть также inline функции. Или также они называются встроенными функциями. Чтобы сделать функцию встроенной, нужно перед её объявлением просто написать inline:

inline double cube (double x) { return x*x*x; }

И дальше работать с ней как с обычной функцией.

В чём же смысл этого? Встроенные функции позволяют увеличить скорость программы, но ценой занимаемого места. Если функция объявлена как встроенная, то компилятор на место вызовов функций вместо ссылок на функцию будет вставлять сам код функции, за счёт чего программа работает быстрее. Но при этом программа будет более громоздкой- и если проект большой, функций много и все они большие и встроенные и вызываются очень много раз- это наоборот может пойти в минус, поэтому лучше использовать встраивание для небольших функций (как в примере выше), которые вызываются много раз.

 

Другие алгоритмы сортировки массивов

Мы рассмотрели 2 алгоритма сортировки- простой интуитивный и быстрый рекурсивный (quick sort). Простой интуитивный называется сортировкой выбором или selection sort. Но есть и много других алгоритмов сортировки, самые типовые и рассматриваемые из них я тут приведу. Можно делать сразу с шаблонами типов переменных, но для простоты понимания мы рассмотрим массивы с целыми числами. Потом, при желании, можно добавить шаблоны.

Сортировка пузырьком ( bubble sort)

Сортировка пузырьком является первой сортировкой, которую вообще изучают, она является простой и медленной. Рассмотрим на примере сортировки массива по возрастанию. Исходный массив: 4 3 5 2

Проверяем: 4>3 ? нет, тогда меняем местами. 3 4 5 2.

Дальше: 5 > 4 ? да, тогда оставляем.

И так далее. Когда прошли весь массив, начинаем заново. Процесс продолжается до тех пор, пока весь массив будет не отсортирован:

(4) (3) (5) (2) // исходный

(3) (4) (5) (2)

(3) (4) (5) (2)

(3) (4) (2) (5) -> в начало массива

(3) (4) (2) (5)

(3) (2) (4) (5)

(3) (2) (4) (5) -> в начало

(2) (3) (4) (5)

(2) (3) (4) (5)

(2) (3) (4) (5) -> массив отсортирован, поэтому выходим из цикла

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

Ниже код алгоритма пузырьковой сортировки:

void bubblesort (int mass[], int size) {

           int buf; // буферная переменная для перемены мест

           bool per_is_going= false; // суммарно- были ли перестановки вообще

           do {

                           per_is_going= false; // обнуляем- перестановок не было

                           for (int j=0; j<size-1; j++) {

                                           // если текущий элемент больше следующего, то мы меняем эти 2 элемента местами, т.к. у нас сортировка по возрастанию

                                           if (mass[j] > mass [j+1]) {

                                                           buf= mass[j];

                                                           mass[j]= mass[j+1];

                                                           mass[j+1]= buf;

                                                           // учёт перестановки

                                                      per_is_going+= true;

                                           }

                           }

           } while (per_is_going); // цикл продолжается пока хоть какие-то перестановки происходят

}

Пример использования:

int m[11]= {3,2,5,7,1,6,6,2,2,1,2};

bubblesort(m,11);

for (int i=0; i<11; i++) cout << m[i] << " ";

 

Шейкерная сортировка ( cocktail sort)

Или по-другому называется "сортировка перемешиванием". Является усовершенствованием пузырьковой сортировки в том смысле, что массив сортируется с 2 сторон.

void cocktailsort (int a[], int size) {

           bool sort_or_not= true;

      int right = size;

      int left = 1;

      do {

  sort_or_not = true;

  for (int i= left; i <= right; i++) {

             if (a[i-1] > a[i]) {

                           swap (a[i-1], a[i]);

   sort_or_not= false;

}

}

right--;

for (int i= right; i >= left; i--) {

if (a[i] < a[i-1]) {

   swap (a[i], a[i-1]);

   sort_or_not = false;

}

}

left++;

 } while (!sort_or_not);

}

Кстати, функция swap, которая меняет местами 2 элемента, уже встроена и кроме iostream подключать ничего не пришлось.

Можно самому написать эту функцию с шаблоном:

template <typename Type>

void swap (Type &a, Type &b) {

           Type c= a; a= b; b= c;

}

Её использование упрощает алгоритмы и программы.

 


Дата добавления: 2018-09-22; просмотров: 290; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!