Студопедия


Авиадвигателестроения Административное право Административное право Беларусии Алгебра Архитектура Безопасность жизнедеятельности Введение в профессию «психолог» Введение в экономику культуры Высшая математика Геология Геоморфология Гидрология и гидрометрии Гидросистемы и гидромашины История Украины Культурология Культурология Логика Маркетинг Машиностроение Медицинская психология Менеджмент Металлы и сварка Методы и средства измерений электрических величин Мировая экономика Начертательная геометрия Основы экономической теории Охрана труда Пожарная тактика Процессы и структуры мышления Профессиональная психология Психология Психология менеджмента Современные фундаментальные и прикладные исследования в приборостроении Социальная психология Социально-философская проблематика Социология Статистика Теоретические основы информатики Теория автоматического регулирования Теория вероятности Транспортное право Туроператор Уголовное право Уголовный процесс Управление современным производством Физика Физические явления Философия Холодильные установки Экология Экономика История экономики Основы экономики Экономика предприятия Экономическая история Экономическая теория Экономический анализ Развитие экономики ЕС Чрезвычайные ситуации ВКонтакте Одноклассники Мой Мир Фейсбук LiveJournal Instagram

Статический массив указателей




Статический массив указателей, например, на объекты типа int размерности 5, объявляется следующим образом:

const n=5; int * ap[n];

Память для такого массива выделяется на этапе компиляции. При таком объявлении массив, который называется ap, состоит из n элементов, каждый из которых имеет тип int *. Другими словами, ap[i], где i=0, 1, 2, …, n-1, представляет собой не целое обрабатываемое в программе число (оценку студента, план выпуска продукции и т. п.), а адрес ячейки оперативной памяти, в которой будет храниться целое число. Можно использовать операцию разыменования “*”. Содержимое ячейки памяти, адрес которой находится в ap[i], обозначается в программе *ap[i].

По аналогии с обычными указателями, i-й элемент объявленного таким образом массива указателей ap[i] можно проинициальзировать одним из следующих способов:

1) с помощью адреса предварительно объявленной простой целочисленной переменной. Например,

int v; ap[i]=&v;

2) с помощью объявленного указателя. Например,

int * p; p= new int; ap[i]=p;

3) непосредственно с помощью операции new. Например,

a) … ap[i]=new int; резервируем память для размещения одного целого числа и его адрес засылаем в i-й элемент массива указателей. Значение i должно быть определено.

б) резервируем память для размещения массива из m целых чисел и адрес его начала засылаем в i-й элемент массива указателей

unsigned m; cin>>m;…ap[i]=new int[m];

В качестве m можно использовать как переменную (см. в примере), так и константу. Переменная i может принимать значение от 0 до n-1;

4) для инициализации элемента массива ap можно использовать адрес предварительно объявленного одномерного массива фиксированной размерности:

const m=10; int a[m]; ap[i]=a;

где i по-прежнему может принимать значение от 0 до n-1 (а не до m-1).

Напомним, что при таком объявлении a — адрес начала одномерного массива. Поэтому последнее присваивание будет корректным.

Логическим продолжением последнего способа является использование массива указателей при работе со статической числовой матрицей. Пусть объявлена матрица

const п=5, m=10; int matr[n][m];

и надо переставить к1-ю строку с k2-й строкой.

Один из способов, при котором элементы двух строк физически переставляются в памяти, был показан в первом семестре. Так как matr[k1] и matr[k2] — адреса начала k1-й и k2-й строк, то возникает вопрос: как для такой перестановки строк ограничиться изменением нескольких адресов, не перемещая элементы в памяти? Объявим для этого ещё один указатель int *p. Казалось бы, можно изменить адреса следующим образом:

p=matr[k1]; matr[k1]=matr[k2]; matr[k2]=p; // ошибка




Но при компиляции второго и третьего присваиваний будут ошибки, так как matr[k1] и matr[k2] — константные указатели на начало строк, то есть их значения нельзя менять. Заметим, что если бы такая возможность разрешалась, то мы потеряли бы доступ к строкам матрицы.

Выход из этой ситуации следующий. Объявляем дополнительно массив указателей размерности n, где n — количество строк матрицы: int * ap[n]; Инициализируем этот массив:

for (int i=0; i<n; i++) ap[i]=matr[i];

Почему присваивание, записанное в цикле, будет корректным? С одной стороны, ap[i] — это указатель, так как ap объявлен не как массив целых чисел (int ap[n];) и не как один указатель (int * ap;) , а как массив указателей. Напомним, что с другой стороны, объявив статическую матрицу, мы этим самым объявили и константый массив указателей, то есть matr[i] — это адрес начала i-й строки матрицы. И тогда меняем не matr[k1] и matr[k2], а ap[k1] и ap[k2] аналогичным образом:

int *p; p=ap[k1]; ap[k1]=ap[k2]; ap[k2]=p;

Вместо m*3 присваиваний, которые необходимо было выполнить при физическом перемещении элементов строк, достаточно выполнить всего три операции присваивания для адресов. При необходимости такие “перестановки” строк можно выполнять несколько раз в цикле. Это имеет место, например, в алгоритмах сортировки. Понятно, что в этом случае эффективность такого метода возрастает.

После таких “перестановок” матрица matr не изменилась. В этом легко убедиться, если вывести её (matr[i][j]) на экран. Доступ к преобразованной матрице осуществляется с помощью идентификатора ap. Например, вывод изменённой матрицы можно выполнить так:



for(int i=0; i<n; i++)

{ cout<< endl;

for(int j=0; j<m; j++)

printf ( “%5d”, ap[i][j]);

}

Заметим, что несмотря на то, что, казалось бы, переменную ap не объявляли как двумерный массив (как матрицу), а как одномерный массив, но массив указателей, мы имеем возможность использовать эту переменную с двумя индексами (ap[i][j]).

Пример (+). Сортировка строк целочисленной матрицы по возрастанию некоторого параметра строки (например, по возрастанию максимальных элементов строк). Порядок чисел в каждой строке не меняется.

const m=4;

int main()

{ // 1) Статическую матрицу не создаём. Её достаточно объявить

const n=5; int matr[n][m];

// Cтатический массив указателей на строки матрицы

int*u[n];

// 2) Получаем матрицу…

for(int i=0;i<n;i++)

{ for(int j=0;j<m;j++)

matr [i][j]=random(15)-6;

/* … и формируем статический массив указателей на строки матрицы */

u[i]= matr [i];

}

/* 3) Получаем одномерный массив параметров s, каждый элемент которого —максимальное число в строке. Поэтому размерность этого массива совпадает с количеством строк матрицы */

int s[n],Mymax,Mymin,nmin;

for(int i=0;i<n;i++)

{ Mymax= matr [i][0];

for(int j=0;j<m;j++)

if (matr [i][j]>Mymax)

Mymax= matr [i][j];

s[i]=Mymax;

}

// 4) Вывод матрицы matr и вектора s

for(int i=0;i<n;i++)

{ cout<<endl;

for(int j=0;j<m;j++)

printf("%5d", matr [i][j]);

printf(" => %5d",s[i]);

}

cout<<endl;

// 5) Сортировка методом выбора минимального элемента

for(int start=0;start<=n-2;start++)

{

Mymin=s[start]; nmin=start;

for(int i=start;i<n;i++)

if(s[i]<Mymin)

{ Mymin=s[i];

nmin=i;

}

cout<< Mymin<< " "<<nmin<<endl;

// Комментарии в конце

int *p; p=u[start]; u[start]=u[nmin]; u[nmin]=p;

/* Переставляем элементы одномерного массива s с номерами start и nmin, не используя никакие указатели */

int t; t=s[start]; s[start]=s[nmin]; s[nmin]=t;

}

/* 6) Выводим рассортированную матрицу u (а не matr) и вектор s. */

for(int i=0;i<n;i++)

{ cout<<endl;

for(int j=0;j<m;j++)

printf("%5d",u[i][j]);

printf(" => %5d",s[i]);

}

cout<<endl;

/* 7)Убеждаемся, что матрица matr осталась не рассортированной! Матрицы u и matr занимают одну и туже оперативную память, но u[i] и matr [i] имеют, вообще говоря, разные адреса. */

for(int i=0;i<n;i++)

{ cout<<endl;

for(int j=0;j<m;j++)

printf("%5d",matr[i][j]);

}

getch(); return 0;

}

В первом семестре без использования указателей две строки матрицы c номерами start и nmin переставляли бы “физически” следующим образом:

int t1;

for(int j=0;j<m;j++)

{ t1= matr [start][j];

matr [start][j]= matr [nmin][j];

matr [nmin][j]=t1; }

Так как matr [i] – это константные адреса строк статической матрицы, их нельзя менять. Т. е. нельзя написать matr [start]= matr [nmin]. Поэтому переставляли полученные “новые” адреса строк матрицы с номерами start и nmin, то есть соответствующие элементы массива указателей u. Физически элементы этих строк остаются на старых местах, меняли только значения двух адресов в массиве u.





Дата добавления: 2015-02-24; просмотров: 547; Опубликованный материал нарушает авторские права? | Защита персональных данных | ЗАКАЗАТЬ РАБОТУ


Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Да какие ж вы математики, если запаролиться нормально не можете??? 8396 - | 7314 - или читать все...

Читайте также:

 

34.204.171.108 © studopedia.ru Не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования. Есть нарушение авторского права? Напишите нам | Обратная связь.


Генерация страницы за: 0.007 сек.