Русский
Русский
English
Статистика
Реклама

Массив

Демонстративно вертим массивы для новичков

19.01.2021 22:21:19 | Автор: admin

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

Цель этого поста собрать некоторую информацию о массивах, которой когда-то не хватало мне. Пост для новичков.

Что такое массив?

Массив - это структура однотипных данных, расположенная в памяти одним неразрывным блоком.

Расположение одномерного массива в памятиРасположение одномерного массива в памяти

Многомерные массивы хранятся точно также.

Расположение двухмерного массива в памятиРасположение двухмерного массива в памяти

Знание этого позволяет нам по-другому обращаться к элементам массива. Например, у нас есть двухмерный массив из 9 элементов 3х3. Так что есть, как минимум два способа вывести его правильно:

1-й вариант (Самый простой):

int arr[3][3] {1, 2, 3, 4, 5, 6, 7, 8, 9};int y = 3, x = 3;for (int i = 0; i < y, ++i) {for (int j = 0; j < x; ++j) {  std::cout << arr[i][j];  }  std::cout << std::endl;}

2-й вариант (Посложнее):

int arr [9] {1,2,3,4,5,6,7,8,9};int x = 3, y = 3;for (int i = 0; i < y; ++i) {  for (int j = 0; j < x; ++j) {std::cout << arr[x * i + j]; // x - ширина массива    }  std::cout << std::endl;}

Формула для обращения к элементу 2-размерного массива, где width - ширина массива, col - нужный нам столбец, а row - нужная нам строчка:

arr[width * col + row]

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

А вот так можно работать с трехмерным массивом
int arr[8] {1,2,3,4,5,6,7,8};int x = 2, y = 2, z = 2;for (int i = 0; i < x; ++i) {for (int j = 0; j < y; ++j) {  for (int k = 0; k < z; ++z) {    std::cout << arr[x * y * i + y * j + k];    }    std::cout << std::endl;  }  std::cout << std::endl;} 

Этим способом можно обходить трехмерные объекты, например.

Формула доступа к элементам в трехмерном массиве, где height - высота массива, width - ширина массива, depth - глубина элемента(наше новое пространство), col - столбец элемента, а row - строка элемента:

arr[height * width * depth + width * col + row]

Для получения доступа к элементам массива большей размерности по аналогии в формулу добавляем новые пространства.

Алгоритмы обработки массивов

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

Изображения - это целый комплекс из разных заголовков и информации о изображении, и самого изображения хранящемся в виде двухмерного массива.

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

1) Зеркальное отражение.

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

int data[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};int newArray[3][4];int height = 3, width = 4;for (int i = 0; i < height; ++i) {for (int j = 0; j < width; ++j) {  newArray[i][j] = data[i][width - j - 1];  }}

По такому же принципу выполняется переворот изображения по вертикали.

int data[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};int newArray[3][4];int height = 3, width = 4;for (int i = 0; i < height; ++i) {for (int j = 0; j < width; ++j) {  newArray[i][j] = data[height - i - 1][j];  }}

2) Поворот изображения на 90 градусов.

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

Пошаговое выполнение алгоритмаПошаговое выполнение алгоритма

Такой алгоритм появился, когда я нарисовал график координат c точками.

График, приведший к решениюГрафик, приведший к решению
int data[3][2] = {1,2,3,4,5,6};int newArray[2][3];int height = 3, width = 2; // Размеры массива (изображения)int newHeight = width, newWidth = height;// Транспонируем матрицуfor (int i = 0; i < newHeight; ++i) {for (int j = 0; j < newWidth; ++j) {  newArray[i][j] = data[j][i];// data - массив изображения  }}// Зеркально отражаем по горизонтали матрицуfor (int i = 0; i < newHeight; ++i) {for (int j = 0; j < newWidth/2; ++j) {  int temp = newArray[i][j];    newArray[i][j] = newArray[i][newWidth - j - 1];    newArray[i][newWidth - j - 1] = temp;  }}

Хочу обратить ваше внимание, что здесь я применяю другой способ переворота изображения. Вместо выделения памяти под новый массив, здесь просто меняем местами первые и последние элементы.

Примечание: создать массив размерностью высоты и ширины реального изображения на стеке не выйдет. Только на куче с помощью оператора new.

Заключение

Этот небольшой пост не претендует на невероятные открытия мира информатики, но надеюсь успешно поможет немного вникнуть в устройство массивов падаванам мира IT.

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

Я надеюсь этот пост будет полезен, и если это будет так, то я напишу продолжение этой темы.

Подробнее..

Альтернативный способ заполнения спиральной матрицы

31.05.2021 18:12:13 | Автор: admin

В процессе изучения основ алгоритмизации и программирования в качестве студента еще в середине 2000х мне попалась довольно известная всем задача по заполнению спиральной матрицы. Суть состоит в том, чтобы начиная с позиции [1, 1], продвигаясь по часовой стрелке, заполнить квадратную матрицу заданной величины числами в возрастающем порядке. На ее решение было потрачено около двух часов.

Собственно алгоритм заполнения был тривиален, циклы, в общей сложности состоящие из N2 итерации, предполагали прохождение по всем элементам массива в требуемом порядке, при этом увеличивая значение итератора на 1 и заполняя им текущий элемент матрицы. Маршрут начинался с элемента [1, 1], далее продвигается по горизонтали до правого верхнего элемента [1, N], после вниз до нижнего правого угла [N, N], затем до левого нижнего угла [N, 1] и завершал первый круг на столбец ниже отправной точки [2, 1]. В дальнейшем, такое же круговое движение происходило уже в следующем внутреннем круге, и так далее до центра матрицы.

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

Через некоторое время после успешного решения задачи, на волне переоценки собственных способностей, я задумался: а возможно ли разработать универсальную формулу, позволяющей на основании размера матрицы и координат ячейки вычислить ее значение согласно условию задачи то есть в конечном итоге заполнить массив, перебирая элементы традиционным путем двумя вложенными циклами от 1 до N без использования счетчика.

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

Спустя эти самые 18 лет, перебирая наиболее интересные задачи и пути их решения для обучения уже следующего поколения представителей неординарной профессии программист, меня заинтересовала одна статья на ресурсе Хабр (http://personeltest.ru/aways/habr.com/ru/post/261773), описывающая процесс создания формулы для вычисления количества дней в заданном месяце без использования каких-либо условных операторов, циклов и заранее подготовленных данных.

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

Именно после этого я вспомнил ту самую спиральную матрицу и решился на очередную попытку выведения универсальной формулы.

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

Итак, задача: разработать алгоритм для вычисления значения элемента спиральной матрицы на основании его координат [i, j] и размера самой матрицы, пользуясь только простыми арифметическими вычислениями. Исключение составляет модуль - абсолютное значение числа.

Условие: никаких условных (прошу прощения за тавтологию) переходов или заготовленных данных в виде массивов, словарей и т.д.

Практическая полезность: никакая. Традиционным способом данная задача решается гораздо быстрее, при этом мозг программиста в процессе разработки функции не травмируется.

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

1) Найти закономерность между координатами ячейки и ее порядковым номером в первом внешнем кольце, и вывести соответствующую форму.

2) Найти связь между, опять же, координатами ячейки и номером кольца, в котором она находится. Составить формулу.

3) Связать между собой два алгоритма для выведения общей формулы вычисления значения элемента массива.

Входные данные: N размер квадратной матрицы (массива).

1 этап. Заполнение внешнего кольца. Для начала попытаемся вывести формулу вычисления значения ячейки для внешнего кольца массива, в котором отсчет начинается с ячейки [1, 1] и двигается по часовой стрелке поворачивая на углах [1, N], [N, N]. Заканчивается на строку ниже начальной точки, т.е. [2, 1].

Математический аппарат будет разрабатываться параллельно с написанием кода на языке программирования, в качестве которого выбираем C++, как наиболее распространенный и удобный язык программирования (здесь конечно читатели могут поспорить, но классика есть классика). Но, в принципе, выведенная формула не должна иметь привязки языке.

Для наглядного изучения процесса напишем соответствующий скрипт, объявив в нем массив размером 5x5 (назовем его a), элементы которого будем перебирать традиционным способом двумя вложенными циклами от 1 до N. На данном этапе будем работать только с внешним кольцом.

#include <iostream>using namespace std;int main(){    int N = 5;          // задаем размер матрицы    int a[N][N];        // и инициализируем ее    for (int ik = 0; ik < N; ik++)        for (int jk = 0; jk < N; jk++)            a[ik][jk] = 0;          // заполнив для удобства нулями                                          for (int ik = 0; ik < N; ik++){     //назовем его "Основной цикл"        for (int jk = 0; jk < N; jk++){            if (!(ik == 0 || ik == N - 1 || jk == 0 || jk == N - 1))                 continue;      // Временное условие для фильтрации элементов внесшего "кольца"            int i = ik + 1;     // Номера строк и столбцов приводим в удобный            int j = jk + 1;     // в математическом плане вид (от 1 до N)              //  ... здесь будем вставлять основной код вычислений        }       }        for (int ik = 0; ik < N; ik++){          //Блок "Вывод массива"        for (int jk = 0; jk < N; jk++){           printf( "%02d ", a[ik][jk]);// дополняем число ведущими нулями        }        cout << endl;    }      return 0;}

Очевидно, что, по крайней мере, до правого нижнего угла внешнего кольца суммарное значение координат (i + j) увеличивается ровно на 1 с каждым шагом. Однако первый элемент в таком случае равняется 2, E1,2 = 3 и т.д. Поэтому необходимо уменьшить значение суммы (i + j) на один. В результате введем переменную Xs = i + j - 1, которая часто будет использоваться в дальнейших вычислениях. Пишем код:

int Xs = (i + j  1);a[ik][jk] = Xs;

В результате запуска первого скрипта получаем массив:

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

Очевидно a[ik][jk] = Xsнуждается в дополнении, при котором все его значения до [5, 5] останутся неизменными, но после этой точки начнут увеличиваться на 1.

Но для начала постараемся привести в норму вторую часть кольца, которая заполнялась бы с ячейки (i = 5, j = 4) начиная со значения 10. В данном случае это легко сделать, лишь вычитая от общего количества элементов первого кольца увеличенного на два (равняется периметру первого кольца N * 4 - 4 = 16 плюс 2) значение Xs.

То есть a1,2 = 4N 4 + 2 Xs = 4N Xs - 2.

int Xs = i + j - 1;     a[ik][jk] = 4 * N - Xs - 2;

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

На текущем этапе у нас имеются две формулы, пригодные только для определенных участков массива.

1. ai,j = Xs = i + j - 1; действует от [1, 1] до [N, N].

2. ai,j = 4*N 2 - X; действует от [N, N] до [2, 1].

Самым простым решением было бы использование условного перехода, однако это не соответствует нашей начальной установке. Здесь необходимо дополнительно отметить, что из всех стандартных кусочно-заданных функций, как отмечено выше, мы будем использовать только модуль (y = |x|) и формулы собственной разработки.

В этой связи, необходимо привести наше уравнение в вид:

a_1, _2= F _1(switcher) * Xs + F _2 (switcher) * (4 * N Xs - 2);

Здесь функция F1 принимает значение 1 при i, j между [1, 1] [N, N] , в остальных случаях 0. В свою очередь, F2 , наоборот, принимает значение 1 когда ячейка находится в диапазоне [N, N - 1] [2, 1], и 0 между [1, 1] [N, N].

В качестве аргумента функции используется переменная switcher, вычисляемая на основе значении i и j, и опять же, принимающая различные значения в вышеуказанных диапазонах.

Неплохим вариантом выглядит идея получения значений -1, 0 и/или 1 от манипуляций с координатами элемента. Тогда F1 и F2 содержали бы простые арифметические операции.

Итак, мы уже использовали сложение i и j, но оно всегда дает положительное число. Почему бы сейчас не попробовать вычитание?

Заменим в нашем предыдущем листинге значение a[ik][jk].

int Xs = i + j - 1;     a[ik][jk] = j  i;

Наиболее легким вариантом видится целочисленное деление на самого себя, но в таком случае мы столкнемся с ошибкой деления на 0, поскольку а[1][1] и а[N][N] уже содержат 0. В данном случае можно прибавить ко всем значениям N и осуществить целочисленное деление на N. Введенную переменную назовем switcher.

int switcher =  (j - i + N) / N;a[ik][jk] =  switcher; // временно подставим в ячейки switcher

Теперь осталось немногое для завершения данного этапа, а именно создать функции F1 и F2. F1 должна возвращать такое же значение, какое ей передали в качестве аргумента, т.е. F1 (switcher) = switcher. В таком случае F1 (switcher) * Xs работает только для диапазона от [1, 1] до [N, N], в остальных случаях равняется нулю. Вторая часть уравнения, должна действовать наоборот. В таком случае она должна возвращать значение по модулю switcher 1, т.е. F2.(switcher) = |switcher 1|.

Итак, пишем:

a[ik][jk] =  switcher * Xs + abs(switcher - 1) * (4 * N - 2 - Xs);

Проверяем:

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

2 этап. Альтернативная система координат.

Нам удалось заполнить внешнее первое кольцо требуемыми данными. Однако, что произойдет, если мы снимем фильтр, и попытаемся вычислить данные для остальных элементов массива? Для этого необходимо удалить участок кода if (!(ik == 0 || ik == N - 1 || jk == 0 || jk == N - 1)) continue;

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

Очевидно, в ячейке [2, 2] вместо 03 должно находиться число 17, следующее значение после конечного элемента внешнего круга. Небольшое размышление показывает, что необходимо ввести определенный коэффициент, выправляющий значение ячейки в зависимости от глубины залегания кольца в котором он находится. Т.е. требуется вычислить степень удаленности элемента массива от центра (или наоборот) на основании номера строки и номера столбца.

Для этого, введем альтернативную систему координат. Так, обычная нумерация ячеек в матрице начинается с левого верхнего угла и аналогична двухмерной системе координат, с центром в указанном месте. Для тех, кто еще помнит древний Turbo Pascal с синим экраном графики в нем чертились именно таким образом (да и в большинстве современных графических сред разработки ПО принята подобная система координат при работе с визуальными компонентами).

Мы же, перенесем начало координат в центр нашей матрицы следующим образом:

a[ik][jk] =  abs(N / 2 + 1 -  i);

Поскольку нам требуется только расстояние ячейки от центра, мы берем только абсолютные значения.

Сейчас элементы массива заполнены номерами строк относительно его центра. Если мы проделаем ту же самую операцию со стоблцами, мы получим такой же массив, только с вертикальным распределением значений.

Введем две новые переменные Ic, Jc (c обозначает center).

Ic = abs(i -  N / 2  - 1);Jc = abs(j -  N / 2  - 1);

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

Опять же, самый простой способ что-то узнать попробовать вывести суммы номеров строк и столбцов.

a[ik][jk] =  Ic + Jc;

Пока ничего путного не выходит, но проявляется закономерность чем дальше от центра, тем больше сумма. В дальнейшем это пригодится. Теперь рассмотрим, что нам даст разница между Ic и Jc.

a[ik][jk] =  Ic - Jc;

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

a[ik][jk] =  abs(Ic  Jc) + Ic + Jc;

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

Ring = N / 2 -  (abs(Ic  Jc) + Ic + Jc) / 2; a[ik][jk] =  Ring;

Замечательно. Однако, при размере матрицы N = 6 данная формула работает не совсем корректно, так она в качестве центра считает только один элемент (что является справедливым для матриц с нечетной размерностью, как в предыдущих примерах).

N = 6

При четном размере центральный квадрат из четырех элементов должен считаться центром матрицы. Возникает вопрос: как это реализовать? Здесь к нам опять на помощь приходит целочисленное деление и кусочно-заданная функция.

Но для этого вернемся немного назад, к вычислению Ic и Jc. Попробуем запустить наш скрипт при N = 6, и посмотрим значения Ic = |i - N / 2 - 1|.

В данный момент требуется привести массив в симметричную форму. Легче всего это сделать, увеличив значение на 1 всех строк после 3-й (то есть вторую половину).

Ic = abs(i - N / 2  - 1) + (i - 1) / (N /2) * ((N-1) % 2);

Вторая часть данного выражения работает только при четном N, и приводит номера строк в симметричный вид по горизонтали.

Тоже самое проделываем и Jc.

Jc = abs(j - N / 2  - 1) + (j - 1)/(N /2) * ((N-1) % 2);

В итоге получаем симметричную матрицу уже по вертикали. Теперь проверяем значение Ring для матрицы с размером 6.

 a[ik][jk] =  Ring;

Все работает нормально. Второй этап завершен.

3 этап. Соединение. На данном этапе мы объединим полученные данные и выведем искомую матрицу (через формулу вычисления значения заданной ячейки).

Но для начала, вернемся к первому этапу и выведем на экран:

a[ik][jk] =  switcher * Xs + abs(switcher - 1) * (4 * N - 2 - Xs);

Дальнейший порядок действий представляется следующим образом: привести значения элементов внутренних колец к спиральному виду (т.е. заполнить их начинания с верхнего левого угла по спирали возрастающими значениями от 1), далее вычислить коэффициент прироста, которой обеспечит нормальный переход от одного кольца к нижестоящему (в нашем примере от ячейки [1,2] к ячейке [2,2], при этом меняя значение с 16 на 17)

Описывать естественным языком или даже академическим стилем математические вычисления крайне тяжело, но еще сложнее понимать чьи-то не всегда ясные наработки изложенные подобным образом. Поэтому если вы столкнулись с определенными трудностями в понимании материала, просто читайте дальше и следите за вычислениями скоро все будет ясно.

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

Xs = (i Ring) + (j Ring) 1.

Теперь попробуем вывести

a[ik][jk] =  switcher * Xs + abs(switcher - 1) * (4 * N - 2 - Xs);

Как вы могли заметить верхние и правые элементы внутренних колец пришли в требуемое значение. Однако нижние и левые стороны приняли гораздо большие значения, чем ожидалось. Это связано с тем, что выражение 4 * N - 2 - Xs во второй части функции вычисляет значения исходя из размера внешнего кольца, которое нужно уменьшить, заменив на N 2 * Ring. То есть формула будет работать в соответствии с размером текущего кольца.

Итак:

a[ik][jk] =  switcher * (Xs) + abs(switcher - 1) * (4 * (N - 2 * Ring) - 2 - Xs); 

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

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

Coef = N2 (N 2Ring)2

Воспользовавшись правилами разложения квадратов разницы элементов ((ab)2=a22ab+b2), можно сократить до 4Ring(N - Ring).

Теперь этот коэффициент нужно добавить к нашей основной формуле.

a[ik][jk] =  Coef + switcher * (Xs) + abs(switcher - 1) * (4 * (N - 2 * Ring) - 2 - Xs);

Требуемый результат!

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

int switcher =  (j - i + N) / N;int Ic = abs(i - N / 2  - 1) + (i - 1)/(N /2) * ((N-1) % 2);int Jc = abs(j - N / 2  - 1) + (j - 1)/(N /2) * ((N-1) % 2);int Ring = N / 2 - (abs(Ic - Jc) + Ic + Jc) / 2;int Xs = i - Ring + j - Ring - 1;    int Coef =  4 * Ring * (N - Ring);a[ik][jk] =  Coef + switcher * Xs + abs(switcher - 1) * (4 * (N - 2 * Ring) - 2 - Xs);

Можно конечно попробовать развернуть единую формулу, заменив дополнительные переменные выражениями, основанными только на i, j и N, и попытаться сократить ее математическими методами. Но поверьте мне, я пытался, получилось нечто такое невообразимое (на половину страницы), что я решил оставить все как есть.

(PS. Не работает только при N = 1, так как возникает ошибка деления на ноль. Но как говорится, чуть-чуть не считается).

Подробнее..

Восстанавливаем RAID 5, 1 или 0 при поломке одного или нескольких дисков

15.03.2021 12:08:42 | Автор: admin
В нашей пошаговом руководстве, я расскажу о нескольких методах восстановления информации с программных RAID 5, 0 или 1, которые собраны под Linux.

image



Если один или несколько физических накопителей повреждены, то кажется что восстановить данные просто невозможно. На самом деле это не так, объем информации, который можно достать из массива, сильно зависит от типа RAID и количества сломанных носителей.



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

Установочный файл программы есть только под ОС Windows. Чтобы запустить ее под Linux понадобиться, либо установить дополнительную систему на компьютер, либо воспользоваться виртуальной машиной под Windows. В нашем случае, я выбрал второй вариант.

image

Восстанавливаем файлы с RAID-1



Тестовый массив первого типа состоит из двух одинаковых накопителей. Этот тип очень надежен сам по себе, так как может состоять из четного количества физических дисков, которые работают как полное зеркало. Если поврежден только один носитель, то все устройство невозможно смонтировать в Linux.

image

Запускаем программу, она нашла и пересобрала устройство, все параметры указаны верно.

image

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

image

Восстанавливаем данные с RAID 5



image

Тип RAID-5 это избыточный массив накопителей с чередованием, без определенного диска четности. Главная особенность этого типа, в том что массив гарантировано будет работать даже при поломке одного диска. Но, при попытке смонтировать его в Linux ничего не вышло. Чтобы исправить ситуацию, необходимо подключить чистый винчестер на место сломанного, или пересобрать с помощью ПО.

Тестовый RAID 5 состоит из 5 физических дисков, один из них гарантированно сломан. Добавляем их в виртуальную машину с Windows, запускаем Hetman RAID Recovery, массив обнаружен и все настройки и свойства указаны верно.

image

Как и положено один накопитель пустой. Так как это RAID 5, то снова запускаем быстрый анализ, находим нужные данные с помощью функции превью и восстанавливаем их. Когда процесс сохранения закончится, все файлы будут находится в выбранном каталоге.

image

Теперь рассмотрим вариант когда повреждены два физических новсителя из пяти. Программа обнаружила RAID, и два винчестера пустые.

image

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

image

Если повреждены два или более физических носителя, RAID 5 становиться полностью неработоспособным, что сулить 100% потерю всех данных. Поэтому наш результат можно считать удовлетворительным.

Как восстановить данные RAID-0


Наш тестовый RAID 0 включает 5 жестких дисков, этот тип один из самых ненадежных. Фактически, это вообще не RAID, так как он не хранит избыточную информацию о хранящихся файлах. Если выйдет из строя хоть один винчестер, то все устройство целиком нельзя монтировать в ОС. Все данные становятся недоступны.

Тип RAID-0 это массив физических носителей с чередованием. Он показывает хорошую производительность благодаря высокой скорости чтения/записи, но отказ оборудования для него будет критическим. Посмотрим, сможем ли мы восстановить хоть часть потерянных данных.

image

Добавляем диски в виртуальную машину и запускаем утилиту. Hetman Partition Recovery со скрежетом смогла правильно определить тип и свойства массива, один диск отображается пустым.

image

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

image

Вывод
Как показали тесты, количество восстанавливаемой информации напрямую зависит от типа массива. Данные с RAID 5 или 1 можно восстановить практически в полном объеме, благодаря зеркалам или избыточности информации. Даже при поломке нескольких жестких дисков, шансы вернуть большую часть нужных файлов достаточно высока.

Выход из строя хоть одного носителя, для RAID 0 становиться критическим. В большинстве случаев вы сможете восстановить только малую часть хранящихся данных. Что касается программы, то она смогла в автоматическом режиме распознать подключенные диски и правильно определить тип массива, что дало возможность уже восстанавливать файлы.

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

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru