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

1.1.5Операции со списками в статических массивах указателей в динамической памяти

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

Тексты основных процедур будут иметь вид:

//---------Вывод списка в ListView -------//

void PrintListInListView(TElmList** PtrStatArrPtrElList, int count, System:: Windows::

Forms::ListView * listView)

{

listView->Items->Clear();

if (count==0) return;

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

{ //listView->View=View::Details;

listView->Items->Add(PtrStatArrPtrElList[i]->Name);

listView->Items->Item[i]->SubItems-> Add(PtrStatArrPtrElList[i]

->Address);

}

}

/// ------------- Простой поиск ----------------///

void FindElList1(TElmList** PtrStatArrPtrElLst, int Cnt, char *Key,

int &PosFndEl, bool &FindOK)

{

/*функция имеет двойное назначение - поиск месторасположения искомого элемента и поиск места вставки добавляемого элемента*/

FindOK = false; /*элемент не найден*/

for(int J=0; J<Cnt; J++)

{

if (strcmp(PtrStatArrPtrElLst[J]->Name, Key)>=0)

{

PosFndEl = J; /*позиция найденного или следующего

большего элемента*/

if (strcmp ( PtrStatArrPtrElLst[J] -> Name, Key) == 0 )

{

FindOK = true; /*элемент найден. В противном случае PosFndEl

содержит позицию возможной вставки

нового элемента*/

}

return;

}

} /*for*/

PosFndEl = Cnt; /*перебран весь массив. Определена позиция возможной

вставки нового элемента*/

} /*FindElList1*/

///------------ Быстрый поиск -------------------///

void FindElList2 (TElmList** PtrStatArrPtrElLst, int Cnt, char *Key, int &PosFndEl, bool &FindOK)

/*Поиск выполняется методом половинного деления*/

/*функция имеет двойное назначение - поиск месторасположения искомого элемента и поиск места вставки добавляемого элемента*/

{

int Middl; /*Middl выступает как средняя граница обрабатываемой части массива*/

int Hi,Low; /*текущие границы - верхняя, нижняя*/

FindOK = false; /*элемент не найден*/

if (Cnt == 0)

{

PosFndEl = 0;

return;

}

Low = 0;

Hi = Cnt - 1;

do

{

Middl = (Hi - Low) / 2 + Low; /* Middl = (Hi + Low) / 2 */

switch (strcmp ( PtrStatArrPtrElLst [Middl] -> Name, Key ) )

{

case 0: PosFndEl = Middl; /*Элемент найден*/

FindOK = true; /*элемент найден*/

return;

case 1: Hi = Middl - 1;

break;

case -1:Low = Middl + 1;

break;

}

} while (Low <= Hi);

PosFndEl = Low; /*Перебран весь массив. Искомый элемент не найден. Оп

ределена позиция возможной вставки нового эле-мента*/

} /*FindElList2*/

/// -------- Добавление в отсортированный список ---///

bool AddElSortList(TElmList** PtrStatArrPtrElList, int &Cnt, TElmList* NewP,

int PosAddEl)

{

if (Cnt == SizeArrH + 1) /*Массив переполнен*/

{

return false;

}

if (PosAddEl == Cnt) /*Добавляемый элемент располагается в конце списка*/

{

PtrStatArrPtrElList[PosAddEl] = NewP;

}

else

{

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

for (int K = Cnt-1; K>=PosAddEl; K--) /*смещение на одну позицию вниз*/

{

PtrStatArrPtrElList[K+1] =PtrArrPtrElList[K];

}

PtrStatArrPtrElList[PosAddEl] = NewP;

}

Cnt++;

return true;

} /*AddElSortList*/

///--------- Удаление элемента -----------///

void DelElList (TElmList** PtrStatArrPtrElList, int &Cnt, int PosDelEl)

{

if (Cnt == 0)

{ /*Список пуст*/

return;

}

/*по окончании поиска месторасположения удаляемого элемента в списке - имеющего позицию PosDelEl*/

/*удаление элемента списка*/

delete PtrStatArrPtrElList [ PosDelEl ] ;

/*возможная корректировка содержимого списка указателей*/

if (PosDelEl != Cnt - 1)

{

/*удаляемый элемент внутри списка*/

for (int K = PosDelEl; K <= Cnt - 2; K++)

{

/*смещение на одну позицию вниз*/

PtrStatArrPtrElList [K] = PtrStatArrPtrElList [K+1];

}

}

Cnt--;

} /*DelElList*/

///-------- Удаление списка --------///

void DelList (TElmList** PtrStatArrPtrElList, int &Cnt)

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

Для полной очистки памяти от списка вслед за вызовом этой функции необходимо удалить массив указателей*/

{

if ( Cnt = 0) /*Список пуст*/

{

return;

}

/*удаление всех элементов внутри списка*/

for (int K = 0; K <= Cnt - 1; K++)

{

delete PtrStatArrPtrElList [K];

}

Cnt= 0; /*сброс счетчика элементов списка в 0*/

} /*DelList*/

Ниже приводятся обращения к приведенным процедурам. Данные об элементе списка вводятся в компонент textbox. Свойство Text данного компонента содержит строку ввода и имеет тип System::String*, а строковое поле элемента списка объявлено как массив символов (например, char [30]). Для перевода значения типа System::String* в char* воспользуемся дополнительной функцией char* SystemStringToChar(System::String * string)

char* SystemStringToChar(System::String * string)

{

return (char*) (void*) System:: Runtime:: InteropServices:: Marshal:: StringToHGlobalAnsi(string);

}

Кнопка – создание списка. Массив статический, находится в динамической памяти. Создание списка состоит в инициализации переменной Count , которая содержит количество элементов списка изначально равное 0 и выделении места в динамической памяти для массива указателей.

//// ------ Создать список -------------///

void Form1::btn_Create_Click(System::Object * sender, System::EventArgs * e)

{

Count=0;

PtrStatArrPtrElmList = new TElmList* [SizeArrH];

/* PtrStatArrPtrElmList - указатель на массив указателей в динамической памяти*/

}

Занесение нового элемента списка осуществляется по нажатию кнопки Добавить на главной форме. Для ввода полей нового элемента создана дополнительная форма FAdd, которая содержит компоненты textBox для ввода и кнопку "+" для подтверждения окончания ввода информации о новом элементе.

Рисунок 1.10 - Дополнительная форма для ввода информации о новом элементе.

Для кнопки "+" на дополнительной форме необходимо установить свойству DialogResult значение OK для того чтобы по окончании ввода информации можно было проанализировать – чем закончился диалог с пользователем – нажатием кнопки "+" или нжатием кнопки Выход.

Рисунок 1.11 - Установка свойства DialogResult для кнопки «+»

/// ------------ Добавить новый элемент ------------///

void Form1::btnAdd_Click(System::Object * sender, System::EventArgs * e)

{

FormAdd *FAdd=new FormAdd();

if (FAdd->ShowDialog()==DialogResult::OK)

{

/*Формирование и занесение нового элемента списка*/

TElmList* NPtrElm =new ElmList;

NPtrElm ->Age=Convert::ToInt32(FAdd->textBoxAge->Text);

strcpy(NPtrElm ->Name,SystemStringToChar(FAdd->textBoxName->Text));

strcpy(NPtrElm ->Address,SystemStringToChar(FAdd->textBoxAdres->Text));

int PosAdd;

bool FindOK;

/*Поиск местоположения добавляемого элемента в массиве*/

FindElList2(PtrStatArrPtrElmList, Count,NPtrElm ->Name, PosAdd, FindOK);

/*Функция AddElSortList возвращает false если массив переполнен и добавление элемента не выполнено */

bool okAdd=AddElSortList (PtrStatArrPtrElmList,Count, NPtrElm, PosAdd );

if (!okAdd)

{

MessageBox(NULL,"Массив переполнен","Добавить элемент невозможно",MB_OK);

}

PrintListInListView(PtrStatArrPtrElmList, Count, listView1);

}

}

/*Поиск элемента по полю Name*/

///------------- Простой поиск-------------///

void Form1::btnFindEl_Click(System::Object * sender, System::EventArgs * e)

{

int PosFndEl; /*позиция в массиве найденного элемента*/

bool FindOK; /*Результат поиска - true -найден,false-нет такого элемента*/

char *Key=SystemStringToChar(textBox1->Text); /*Ключ поиска*/

FindElList2(PtrStatArrPtrElmList, Count, Key, PosFndEl, FindOK);

if (FindOK) /*Если элемент найден*/

{

/*Формирование строки результата и вывод ее в окно сообщения*/

char* findResult=SystemStringToChar(String::Concat(textBox1->Text, S", адрес: ", PtrStatArrPtrElmList[PosFndEl]->Address));

MessageBox(NULL,findResult,"Результат поиска",MB_OK);

}

else

{

MessageBox(NULL,"Элемент не найден","Результат поиска",MB_OK);

}

}

///------- Удалить элемент ----------////

void Form1::btnDel_Click(System::Object * sender, System::EventArgs * e)

{

/*Фамилия, которую необходимо удалить из списка вводится в

компонент textBox1*/

char * Key=SystemStringToChar(textBox1->Text);

int PosDel;

bool FindOK;

FindElList2(PtrStatArrPtrElmList,Count,Key,PosDel,FindOK);

if (FindOK==false)

{ return; }

DelElList (PtrStatArrPtrElmList,Count, PosDel);

PrintListInListView(PtrStatArrPtrElmList, Count, listView1);

}

///--------- Удаление всего списка ----------////

void Form1::btnDelList_Click(System::Object * sender, System::EventArgs * e)

{

DelList (PtrStatArrPtrElmList, Count);

PrintListInListView(PtrStatArrPtrElmList, Count, listView1);

/*удаление массива указателей на элементы списка*/

delete [] PtrStatArrPtrElmList;

}

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