Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Техн.прогр.в.2.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
962.56 Кб
Скачать

Реализация массива переменного размера:

1. С быстрым извлечением – создаётся вектор размера top, если происходит попытка записи элемента с номером n больше top, происходит перевыделение памяти так, чтобы (n < top). Может дополнительно задаваться шаг роста массива. Далее существующие данные копируются в новый массив; освобождается место, где ранее размещался массив. Недостаток – существенные временные затраты на «рост».

2. С быстрым расширением – создаётся список векторов, инициализируется только первый вектор (размер top). При попытке записи элемента с номером n больше top к списку добавляются один или несколько векторов, чтобы (n<top). Для ускорения доступа все векторы целесообразно создавать одного размера. Доступ к элементу осуществляется по номеру вектора (k) и номеру элемента в векторе (m). При равных размерах векторов (top) и заданном порядковом номере элемента (n) получаем: k=n/top, m=n%top.

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

class Vector

{

protected:

void** data; //поле данных

int top,step; //верхняя граница и шаг роста

public:

//конструктор принимает аргументы: начальный размер вектора и шаг роста

Vector(int top = 10, int step = 10):top(top),step(step)

{

data = (void**)malloc(top*sizeof(void*));

memset(data,0,top*sizeof(void*)); //сброс всех данных в ноль

}

~Vector()

{

free(data);

}

void* GetAt(int n)

{

if (n>-1 && n<top) return data[n];

return NULL; //если данные за допустимым диапазоном

}

bool SetAt(int n, void* element)

{

if (n>=top) //рост массива если вышли за границы

{

int oldtop = top;

while((top+=step)<=n);

void **tdata = (void**)malloc(top*sizeof(void*));

if (tdata == NULL) return false;

memcpy(tdata,data,oldtop*sizeof(void*));

memset(tdata+oldtop,0,(top-oldtop)*sizeof(void*));

free(data);

data = tdata;

}

*(data+n) = element;

return true;

}

int Count() {return top;} //верхняя граница

};

Примеры программ

Половинное деление

int Find(int *array, int size, int x)

{

int a = 0,b = size-1,t;

do

{

t = (b+a)/2;

if (m[t] == x)return t;

if (m[t]>x) b = t;

else a = t;

}while (b-a>1);

if (m[a] == x) return a;

if (m[b] == x) return b;

return -1;

}

Сортировка пузырьком

int t;

char flag;

do

{

flag = 0;

for(int i=0;i<N-1-i;i++)

if (m[i]>m[i+1]) {t=m[i];m[i]=m[i+1];m[i+1]=t;flag=1;}

}while(flag)

Обход дерева

struct Node

{

Node *parent,*left,*right;

};

void Action(Node *node)

{

if (node == NULL) return;

//action;

Action(node->left);

Action(node->right);

}

void Action2(Node *node)

{

queue<Node*> q;

q.push(node);

do

{

node = q.front();

q.pop();

//action

if (node->left!=NULL) q.push(node->left);

if (node->right!=NULL) q.push(node->right);

}

while(!q.empty) // action

}

size_t first = 0; /* Номер первого элемента в массиве */

size_t last = n; /* Номер элемента в массиве, СЛЕДУЮЩЕГО ЗА последним */

/* Если просматриваемый участок непустой, first<last */

size_t mid;

if (n == 0)

{

/* массив пуст */

}

else if (a[0] > x)

{

/* не найдено; если вам надо вставить его со сдвигом - то в позицию 0 */

}

else if (a[n - 1] < x)

{

/* не найдено; если вам надо вставить его со сдвигом - то в позицию n */

}

while (first < last)

{

/* ВНИМАНИЕ! В отличие от более простого (first+last)/2, этот код стоек к переполнениям.

Если first и last знаковые, возможен код (unsigned)(first+last) >> 1. */

mid = first + (last - first) / 2;

if (x <= a[mid])

{

last = mid;

}

else

{

first = mid + 1;

}

}

/* Если условный оператор if(n==0) и т.д. в начале опущен - значит, тут раскомментировать! */

if (/* last<n &&*/ a[last] == x)

{

/* Искомый элемент найден. last - искомый индекс */

} else

{

/* Искомый элемент не найден. Но если вам вдруг надо его вставить со сдвигом, то его место - last. */

}