Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
23
Добавлен:
03.03.2016
Размер:
2.87 Mб
Скачать

Вставка элемента в упорядоченный массив

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

Пример.

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

При этом может иметь место один из трех вариантов:

а)

б)

в)

Пусть массив имеет вид

5 12 18 22 29 31 35 41 47 53 62 77 ()

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

#define NMAX 21

int main()

{

int b,x[NMAX];

int n,i,k;

// Ввод n, массива x и b

// Поиск ближайшего элемента, большего значения b

for (k=0; k<n && x[k]<=b; k++);

if (k==n) // b >= x[n-1]

x[n]=b;

else

{ //Сдвиг подмассива

for (i=n; i>k; i-- ) // при b<x[n-1]

x[i]=x[i-1];

x[k]=b; // Вставка значения b

}

n++; // Увеличение размера массива

//Печать массива x

getch();

return 0;

}

Примечание 1. Сдвиг части массива X вправо оператором

for (i=k+1; i<=n; i++ )

x[i]=x[i-1];

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

Примечание 2. Выход за пределы границ массива X будет иметь место при n = Nmax. Следствием этого будет попытка записи значения в несуществующий (n+1)-й элемент массива . Это может привести к получению неправильных результатов, так как эта область памяти может быть распределена для других переменных. Для повышения надежности работы программы целесообразно объявление типа массива выполнить в виде

int x[NMAX+1];

а при вводе массива X проверять условие nNmax и в случае его нарушения выдать соответствующее сообщение на экран.

Примечание 2. Таким способом можно вставить элемент в любой массив, а не только отсортированный.

П О И С К В У П О Р Я Д О Ч Е Н Н О М М А С С И В Е

Рассматривается массив целых чисел, сгруппированных по возрастанию (или убыванию). При этом предполагается, что в данном массиве нет повторяющихся элементов, т.е. строго выполняется отношение . Требуется для заданного целочисленного значения определить индекс элемента . Если в массиве нет элемента, равного значению , то присвоить переменной значение “-1”.

Такая задача поиска часто возникает в системах АСУ, САПР и других при выборке информации из различных архивов. Самым простым методом для ее решения является метод прямого перебора, или, как его еще называют, метод линейного поиска. При использовании указанного метода последовательно просматриваются элементы массива до тех пор, пока не будет найден искомый элемент или не станет ясно, после просмотра всего массива, что такого элемента здесь нет. Перед просмотром массива переменной k присваивается значение -1, а когда будет найден искомый элемент, в нее запишется его индекс (k=i).

int main()

{

int b,x[NMAX];

int n,i,k;

//Ввод n, массива x и b

k=-1;

for (i=0; i<n && k<0; i++)

if (x[i]==b)

k=i;

//Печать k

getch();

return 0;

}

Если , то в массиве анализируется лишь один элемент; если или в массиве отсутствует элемент, равный значению , то анализируются элементов. Среднее количество просмотров элементов массива равно .

Если массив неупорядочен, то метод прямого перебора является единственно возможным. Для упорядоченного массива наиболее эффективным является метод двоичного (бинарного) поиска.

Пусть массив имеет элементов. Сущность алгоритма двоичного поиска сводится к следующему.

1) Рассматривается диапазон поиска . Левая граница диапазона , правая граница . Выходной переменной присваивается начальное значение -1.

2) Если , поиск прекращается.

3) Определяется , т.е. индекс середины диапазона.

4) Если , поиск закончен, переменной присваивается значение m . В противном случае - переход к шагу 5.

5) Если , то это означает, что в правой половине подмассива (от m+1 до ) не может быть элемента, равного b. Тогда граница перемещается в точку m-1: . При этом диапазон поиска уменьшается вдвое. Дальше - переход к шагу 2.

6) Если , то аналогичным образом к точке m+1 сдвигается левая граница : . В этом случае диапазон поиска также уменьшается вдвое и производится переход к шагу 2.

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

Примечание. Выполнять в пп.5 и 6 переход в точку m нет смысла, так как элемент уже был проверен.

int main()

{

int x[NMAX];

int b,i1,i2,k,m;

//Ввод n, массива x и b

i1=0; i2=n-1; k=-1;

while (i1<=i2)

{

m=(i1+i2) / 2;

if (x[m]==b)

{ k=m; break; }

if (x[m]>b)

i2=m-1;

else

i1=m+1;

}

//Печать k

getch();

return 0;

}

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

Среднее количество просмотров элементов массива в методе двоичного поиска равно , что значительно меньше значения .

М Н О Г О М Е Р Н Ы Е М А С С И В Ы

В Си двумерный массив (матрица) рассматривается как одномерный массив, каждый элемент которого — также массив. Определение двумерного массива:

int A[10][10],B[3][15].

Таким образом определена квадратная матрица A, состоящая из 10 строк, каждая из которых состоит из 10 елементов (столбцов), и матрица B из 3 строк и 15 столбцов.

Компоненты такого массива обозначается A[i][j], B[i][j].

Массивы могут быть и более чем двумерные. Пример трехмерного массива:

int С[10][20][10];

Компоненты многомерного массива располагаются в памяти таким образом, что наиболее быстро изменяется последний индекс, а наиболее медленно - первый индекс. По отношению к матрице это означает, что ее элементы располагаются в памяти по строкам: вначале все элементы первой строки в соответствии с описанием типа матрицы, затем все элементы второй строки и т.д.

Сравним расположение в памяти элементов одномерного массива и матрицы.

#define Nmax 30

#define Mmax 40

char X[Nmax];

char A[Mmax][Nmax];

Предположим, что в программе введено n = 20 элементов массива X и элементов матрицы A ( Mmax, n Nmax).

В поле памяти, отведенном для массива X, будут последовательно заняты первые 20 байт. В отличие от этого, поле памяти A будет заполнено не всплошную, а фрагментарно элементами матрицы: 20 байтов первой строки, 20 свободных байтов, 20 байтов второй строки, 20 свободных байтов, …, 20 байтов пятнадцатой строки, 20 + 540 свободных байтов. Эту фрагментарность необходимо учитывать в ряде случаев при программной обработке матрицы.

Пусть многомерный массив имеет k индексов (для матрицы k = 2). При обработке такого массива в общем случае производится изменение каждого его индекса. В связи с этим каждому индексу должна соответствовать отдельная переменная, которая при использовании оператора for является именем параметра цикла. Имена переменных-индексов не должны совпадать между собой.

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

В В О Д И П Е Ч А Т Ь Э Л Е М Е Н Т О В М А Т Р И Ц Ы

Соседние файлы в папке Прогр_обменка