11.14. Реализация динамической матрицы
11.14. Реализация динамической матрицы
Проблема
Требуется реализовать числовые матрицы, размерности которых (количество строк и столбцов) неизвестны на этапе компиляции.
Решение
В примере 11.28 показана универсальная и эффективная реализация класса динамической матрицы, использующая итератор с шагом из рецепта 11.12 и valarray.
Пример 11.28. matrix.hpp
#ifndef MATRIX_HPP
#define MATRIX_HPP
#include "stride_iter.hpp" // см. рецепт 11.12
#include <valarray>
#include <numeric>
#include <algorithm>
template<class Value_T>
class matrix {
public:
// открытые имена, вводимые typedef
typedef Value_T value_type;
typedef matrix self;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef Value_T* row_type;
typedef stride_iter<value_type*> col_type;
typedef const value_type* const_row_type;
typedef stride_iter<const value_type*> const_col_type;
// конструкторы
matrix() : nrows(0), ncols(0), m() {}
matrix(int r, int c) : nrows(r), ncols(c), m(r * с) {}
matrix(const self& x) : m(x.m), nrows(x.nrows), ncols(x.ncols) {}
template<typename T>
explicit matrix(const valarray<T>& x)
: m(x.size() + 1), nrows(x.size()), ncols(1) {
for (int i=0; i<x.size(); ++i) m[i] = x[i];
}
// позволить конструирование из матриц других типов
template<typename T> explicit matrix(const matrix<T>& x)
: m(x.size() + 1), nrows(x.nrows), ncols(x.ncols) {
copy(x.begin(), x.end(), m.begin());
}
// открытые функции
int rows() const { return nrows; }
int cols() const { return ncols; }
int size() const { return nrows * ncols; }
// доступ к элементам
row_type row begin(int n) { return &m[n * cols()]; }
row_type row_end(int n) { return row_begin() + cols(); }
col_type col_begin(int n) { return col_type(&m[n], cols()); }
col_type col_end(int n) { return col_begin(n) + cols(); }
const_row_type row_begin(int n) const { return &m[n * cols()]; }
const_row_type row_end(int n) const { return row_begin() + cols(); }
const_col_type col_begin(int n) const { return col_type(&m[n], cols()); }
const_col_type col_end(int n) const { return col_begin() + cols(); }
iterator begin() { return &m[0]; }
iterator end() { return begin() + size(); }
const_iterator begin() const { return &m[0]; }
const_iterator end() const { return begin() + size(); }
// операторы
self& operator=(const self& x) {
m = x.m;
nrows = x.nrows;
ncols = x.ncols;
return *this;
}
self& operator=(value_type x) { m = x; return *this; }
row_type operator[](int n) { return row_begin(n); }
const_row_type operator[](int n) const { return row_begin(n); }
self& operator+=(const self& x) { m += x.m; return *this; }
self& operator-=(const self& x) { m -= x.m; return *this; }
self& operator+=(value_type x) { m += x; return *this; }
self& operator-=(value_type x) { m -= x; return *this; }
self& operator*=(value_type x) { m *= x; return *this; }
self& operator/=(value_type x) { m /= x; return *this; }
self& operator%=(value_type x) { m %= x; return *this; }
self operator-() { return -m; }
self operator+() { return +m; }
self operator!() { return !m; }
self operator~() { return ~m; }
// дружественные операторы
friend self operator+(const self& x, const self& y) { return self(x) += y; }
friend self operator-(const self& x, const self& y) { return self(x) -= y; }
friend self operator+(const self& x, value_type y) { return self(x) += y; }
friend self operator-(const self& x, value_type y) { return self(x) -= y; }
friend self operator*(const self& x, value type y) { return self(x) *= y; }
friend self operator/(const self& x, value_type y) { return self(x) /= y; }
friend self operator%(const self& x, value_type y) { return self(x) %= y; }
private:
mutable valarray<Value_T> m;
int nrows;
int ncols;
};
#endif
Пример 11.29 показывает, как можно использовать шаблонный класс matrix.
Пример 11.29. Применение шаблона matrix
#include "matrix.hpp"
#include <iostream>
using namespace std;
int main() {
matrix<int> m(2,2);
m = 0;
m[0][0] = 1;
m[1][1] = 1;
m *= 2;
cout << "(" << m[0][0] << "," << m[0][1] << ")" << endl;
cout << "(" << m[1][0] << "," << m[1][1] << ")" << endl;
}
Программа примера 11.29 выдает следующий результат.
(2,0)
(0,2)
Обсуждение
Проект шаблона матрицы, представленный в примере 11.28, в значительной степени инспирирован шаблоном матрицы Бьерна Страуструпа (Bjarne Stroustrup) из его книги «The C++ Programming Language», 3-е издание (издательство «Addison Wesley»). Реализация Страуструпа отличается тем, что его итератор использует класс slice и указатель на valarray для индексации. Реализованная в примере 11.27 матрица использует вместо них итератор с шагом из рецепта 11.12, что делает итераторы более компактными и при некоторых реализациях более эффективными.
Шаблонный класс matrix позволяет индексировать элемент i-й строки и j-го столбца, используя операцию двойной индексации. Например:
matrix<int> m(100,100);
cout << "the element at row 24 and column 42 is " << m[24][42] << endl;
Шаблонный класс matrix также имеет функции-члены begin и end, т.е. его легко можно использовать в различных алгоритмах STL.
Пример 11.28 содержит строку, которая, возможно, вызывает у вас некоторое удивление. Имеется в виду следующее объявление.
mutable valarray<Value_T> m;
Объявление поля-члена m со спецификатором mutable вынужденно. В противном случае я не мог бы обеспечить итераторы со спецификатором const, потому что нельзя создать итератор для const valarray.
Смотри также
Рецепты 11.15 и 11.16.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Понятие статической и динамической веб-страницы
Понятие статической и динамической веб-страницы Ранее мы уже кратко говорили о том, что представляют собой статические и динамические веб-страницы. В данном же разделе мы рассмотрим этот вопрос более детально.Название статической страницы говорит само за себя: на такой
Делаем статистику динамической
Делаем статистику динамической Итак, мы узнали, как подготовить внешний JavaScript-файл к динамической загрузке. Осталось понять, как теперь это использовать.Основное преимущество (или недостаток?) Omniture заключается в том, что JavaScript-файл (обычно s_code.js) располагается на нашем
Функции динамической загрузки
Функции динамической загрузки dlЗагрузка библиотеки расширения PHP во время выполнения.Синтаксис:int dl(string library);dl("extensions/php_db.dll");Загружает PHP расширение определенное в library.get_loaded_extensionsОпределения перечня загруженных модулей.Синтаксис:array get_loaded_extensions(void);Возвращает массив,
8.1.8. Реализация разреженной матрицы
8.1.8. Реализация разреженной матрицы Иногда бывает нужен массив, в котором определена лишь небольшая часть элементов, а остальные не определены вовсе или (даже чаще) равны 0. Подобная разреженная матрица потребляет так много памяти зря, что были найдены способы более
9.4.1. Реализация графа в виде матрицы смежности
9.4.1. Реализация графа в виде матрицы смежности Нижеприведенный пример основан на двух предыдущих. В листинге 9.3 неориентированный граф реализован в виде матрицы смежности с помощью класса ZArray (см. раздел 8.1.26). Это нужно для того, чтобы новые элементы по умолчанию получали
11.15. Реализация статической матрицы
11.15. Реализация статической матрицы ПроблемаТребуется эффективно реализовать матрицу, когда ее размерность (т.е. количество строк и столбцов) постоянна и известна на этапе компиляции.РешениеКогда размерность матрицы известна на этапе компиляции, компилятор может легко
А.2.1. Программа для тестирования динамической памяти
А.2.1. Программа для тестирования динамической памяти Программа malloc-use, приведенная в листинге А.2, позволяет тестировать операции выделения, освобождения и обращения к памяти. Единственный аргумент командной строки задает максимальное число выделяемых буферов. Например,
Режим с динамической компоновкой
Режим с динамической компоновкой Особенности режима с динамической компоновкойКак было отмечено выше, с помощью кнопки быстрого доступа Режим" и связанной с ней клавиши F4 можно осуществлять переключение между двумя режимами окна задачника: традиционного режима с
Разрешение матрицы
Разрешение матрицы Мы знаем, что матрица состоит из мельчайших светочувствительных элементов. Количество таких элементов в матрице – это и есть ее разрешение. Разрешение матрицы получают умножением количества элементов по горизонтали и вертикали. Самые
Физический размер матрицы
Физический размер матрицы Выбирая цифровую камеру, неплохо поинтересоваться физическим размером ее матрицы, ведь именно эта характеристика определяет качество камеры. Чем сенсор больше, тем больше он содержит ПЗС-элементов, тем выше его разрешение и, следовательно,
Динамический диапазон матрицы
Динамический диапазон матрицы Динамический диапазон светочувствительной матрицы – это ее способность воспринимать градации каждого из цветов. Говоря проще, динамический диапазон определяет, сколько ступеней разности контраста может увидеть и зафиксировать матрица.
Облет повисшего объекта, или Эффект «Матрицы»
Облет повисшего объекта, или Эффект «Матрицы» Несмотря на современные достижения компьютерной техники, для получения некоторых визуальных эффектов используются старые проверенные методы фотографии. Казалось бы, что общего может иметь фотография с таким современным
Аргументы в пользу динамической типизации
Аргументы в пользу динамической типизации Несмотря на все это, динамическая типизация не теряет своих приверженцев, в частности, среди Smalltalk-программистов. Их аргументы основаны прежде всего на реализме, речь о котором шла выше. Они уверены, что статическая типизация
Чистка матрицы зеркальной камеры
Чистка матрицы зеркальной камеры У владельцев зеркальных камер к радости от возможности смены объективов прибавляется забота о чистоте матрицы. Что делать, если вы заметили на снимках ровной светлой поверхности соринки и пятна? В некоторых моделях зеркальных камер
Чистка матрицы зеркальной камеры
Чистка матрицы зеркальной камеры В зеркальной камере, в отличие от компактной, приходится чистить матрицу. Хотите вы или нет, но рано или поздно на матрицу попадает пыль, мелкие соринки. Насколько скоро это произойдет, зависит от частоты смены объективов, условий
ТЕМА НОМЕРА: Реформирование матрицы
ТЕМА НОМЕРА: Реформирование матрицы Автор: Леонид Левкович-МаслюкГде-то в конце 1980-х или начале 1990-х я читал в "Независимой газете" обзор событий в мире книг. Автор отмечал, что на прилавках появилось оригинальнейшее сочинение по истории древнего мира, которое написал