Алгоритмдер мен ассоциативтік жиымдар

Автор работы: Пользователь скрыл имя, 07 Февраля 2013 в 06:33, творческая работа

Описание

Үнсіз келісім бойынша теңдікті тексеру == операторы арқылы орындалады, ал реттеу
<(кіші) операторы арқылы. Стандартты кітапхананың алгоритмдері <algorithm> тақырыбында анықталған. Бұдан да нақты мәліметтерді оқырмандар Б.5 және 20.7 қосымшаларында таба алады. Бұл алгоритмдер бір немесе екі реттілікпен жұмыс істей алады. Берілген реттілік жұп итераторлармен анықталады, ал нәтижелік реттілік оның бірінші элементіне орнатылған итератормен анықталады.

Работа состоит из  1 файл

Алгоритмдер мен ассоциативтиік жиымдар.doc

— 341.50 Кб (Скачать документ)

 

Copy operations


 

copy(b,e,b2)   [b : e) реттілігін [b2 : b2 + (e-b)) реттілігіне көшіреді

unique_copy(b,e,b2) [b : e) реттілігін [b2 : b2 + (e-b)) реттілігіне көршілес көшірмелерді тастап көшіреді

copy_if(b,e,b2,p) р предикатын қанағаттандыратын элементтерді [b : e) реттілігінен [b2 : b2 + (e-b)) реттілігіне көшіреді


 

21.7.1 Copy() алгоритмі

 

Copy() алгоритмінің негізгі версиясы келесі түрде анықталған:

 

template<class In, class Out> Out copy(In first, In last, Out res)

{

while (first!=last) {

*res = *first;  // элементті көшіреді

++res;

++first;

}

return res;

}

 

Итераторлар жұбын алып, сopy() алгоритмі итераторы бірінші элементке анықталған бір реттілікті екіншісіне көшіреді. Мысал қарастырайық:

 

void f(vector<double>& vd, list<int>& li)

// int типті тізім сандарын

// double типті вектор сандарына өшіреді

{

if (vd.sizeO < li.sizeO) error ("мақсатты контейнер тым кішкентай");

copy (li.begin() , li.end(), vd.begin());

// . . .

}

 

Кіретін (входной) реттіліктің типі нәтижелік реттіліктің типімен сәйкес келмеуіне назар аударыңыздар! Бұл жағдай  STL кітапханасының алгоритмдерінің әмбебаптығын жоғарылатады: олар барлық реттіліктер түрімен олардың іске асырылуын артық жорамалдамай жұмыс істейді. Біз нәтижелік реттілікте енгізілетін элементтерді жазу үшін жеткілікті орын бар екендігін тексеруді ұмытқан жоқпыз. Мұндай тексеріс программисттің міндеті болып табылады. STL кітапханасының алгоритмдері максимал әмбебаптық пен ұтымды өнімділікке жету үшін программаланған; үнсіз келісім бойынша олар тұтынушыларды қорғайтын диапазондарды тексермейді және басқа тесттерді орындамайды. Қажет болғанда тұтынушы мұндай тексерісті өзі орындауы керек.

 

21.7.2 Итераторлар ағындары

 

 Сіз «шығару ағынына көшіру» немесе «енгізу ағынынан көшіру» деген сөйлемдерді жиі еститін боласыз. Бұл кейбір енгізу-шығару түрлерінің тиімді әрі ыңғайлы сипаттау тәсілі. Бұл операцияларды орындау үшін сopy() алгоритмі қолданылады.

 

Реттіліктердің ерекшеліктерін еске салайық.

 

  • Реттіліктің басы мен аяғы бар.

 

  • Реттіліктің келесі элементіне көшу ++ операторы арқылы жүзеге асырылады.

 

  • Реттілік элементінің мәнін * операторы арқылы табуға болады.

 

Енгізу және шығару ағындарын да тура солай сипаттауға болады. Мысал  қарастырайық.

 

ostream_iterator<string> oo(cout);  // *оо ағынын cout ағынымен

// жазу үшін байланыстырамыз

*оо = "Hello, ";    //яғни cout << "Hello, "

++оо;      // "келесі элементті шығару үшін дайын"

*оо  = "World!\ n";    // яғни cout << "World!\n"

 

Стандарт кітапханада шығару ағынынмен  жұмыс істейтін ostream_iterator деген тип бар; ostream_iterator<T> - бұл Т типті мәндерді жазу үшін қолданылатын итератор.

Сонымен қатар стандарт кітапханада  Т типті мәндерді оқу үшін іstream_iterator<T> деген тип бар.

 

istream_iterator<string> ii(cin);   // *ii оқуы — бұл cin - нан

// тіркесті оқу

string s1 = *ii;     // яғни cin>>sl

++ii;      // "келесі элементті енгізу үшін дайын"

string s2  = *ii;    // яғни cin>>s2

 

ostream_iterator және іstream_iterator қолдана отырып, сopy() алгоритмі арқылы мәліметтерді енгізуге және шығаруға болады. Мысалы, тез арада жасалынған сөздікті келесі түрде жасауға болады:

 

int main ()

{

string from, to;

cin » from >> to;   // бастапқы және мақсатты

// файлдардың аттарын  енгіземіз

ifstream is (from.c_str()) ;     // енгізу ағынын ашамыз

ofstream os(to.c_str());      

// шығару ағынын ашамыз

istream_iterator<string> ii(is);  // ағыннан енгізу итераторын құрамыз

istream_iterator<string> eos;         // енгізудің сигналды белгісі

ostream_iterator<string> 00(os, "\n"); // итератор құрамыз

// ағынға шығару

vector<string> b(ii,eos);          // b — вектор, енгізу ағынының мәліметтерімен

// инициализацияланады

sort (b.begin ()   ,b.end());  // буферді сорттау

copy(b.begin()   ,b.end()  ,оо);       // шығару үшін көшіру буфері

}

 

Еos итераторы – бұл "енгізу соңын" білдіретін сигналды белгі. istream ағыны енгізу соңына жеткенде оның үнсіздік бойынша берілетін және eos деп аталынатын istream_iterator итераторы istream_iterator – ға тең болады.

 Біз vector классының объектісін итераторлар жұбы арқылы инициализациялайтынымызға назар аударыңыз. Контейнерді инициализациялайтын (а, b) итераторлар жұбы келесіні білдіреді: "[a:b) реттілігін контейнерге санау(считать)". Бұл үшін біз (ii,eos) итераторлар жұбын қолданамыз – енгізудің басы мен аяғы. Бұл бізге >> операторын және push_back() функциясын айқын қолданбауға мүмкіндік береді. Біз басқа варианттарды қолданбауға ұсыныс береміз.

 

vector<string> b(max_size);  // бастапқы мәліметтердің көлемін болжамай-ақ

// қойыңыз

сору(ii,eos,b.begin());

 

Енгізу ағынының көлемін болжап білуге тырысатын адамдар, әдетте, оны жете бағаламайды және буферді толтырып тастайды, соның себебінен өзіне әрі тұтынушыға проблема тудырады. Буфердің толып кетуі мәліметтердің түгелдігіне қауіп төндіреді.

 


  • Байқап көріңіз

Программаны жұмыс істейтін күйіне келтіріп, оны бірнеше жүз сөзден тұратын шағын файл арқылы тестілеп көріңіз. Содан кейін бастапқы мәліметтер көлемі болжап білінетін"қолдануға ұсынылмайтын версияны" тестілеп көріңіз және b енгізу буфері толып кеткен жағдайда не болатынын бақылаңыз. Сіз жаман ештеңе байқамаған әрі сол программаны тұтынушыға ұсынған жерді ең жаман сценарий екендігіне назар аударыңыз!


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Жаттығулар

  1. Бөлімді қайтадан оқып, "Байқап көріңіз" деген жердегі (егер оларды орындамаған болсаңыз) барлық жаттығуларды орындап көріңіз.
  2. STL кітапханасы бойынша сенімді мәліметтер көзінің документациясын тауып, барлық стандарт алгоритмдерді атап шығыңыз.
  3. Өздігіңізше count() алгоритмін жасаңыз. Оны тестілеңіз.
  4. Өздігіңізше count()_if алгоритмін жасаңыз. Оны тестілеңіз.
  5. Біз элемент табылмады дегенді білдіретін end() итераторын қайтара алмаған кезде не істеу керек едік? find() және count() алгоритмдерін , бірінші және соңғы элементінде орналасқан итераторларды алатындай етіп, жаңадан жобалап іске асырыңыз. Нәтижелерді стандарт версиялармен салыстырыңыз.
  6. 21.6.5 бөліміндегі Fruit классының мысалында, біз Fruit құрылымын set контейнеріне көшірдік. Біз бұл құрылымдарды көшіргіміз келмесе не істейміз? Біз бұның орнына set<Fruit*> контейнерін қолдансақ болар еді. Бірақ бұл жағдайда біз бұл контейнерге салыстыру операторын анықтауымыз керек болады. Бұл жаттығуды set<Fruit*, Fruit_comparison> контейнерін қолдана отырып тағы бір рет орындаңыз. Бұл екі іске асырудың айырмашылығын талқылаңыз.
  7. Vector<int> классы үшін (стандарт алгоритмдерді қолданбай) бинарлық іздеу функциясын жазыңыз. Қалауыңыз бойынша кез-келген интерфейсті таңдаңыз. Оны тестілеңіз. Сіздің бинарлық іздеу функцияңыз дұрыс істейтініне қаншалықты сенімдісіз? list<string> контейнері үшін бинарлық іздеу функциясын жазыңыз. Оны тестілеңіз. Бұл екі бинарлық іздеу функциялары қаншалықты ұқсас? Егер сіз STL кітапханасы туралы білмеген жағдайда олар соншалықты ұқсас болар ма еді?
  8. 21.6.1 бөліміндегі сөздер жиілігін есептеу мысалына қайта оралып оны түрлендіріңіз, сөздер лексикографиялық кезекте емес жиіліктердің кезектесу реті бойынша шығарылсын. Мысалы, экранға C++: 3 емес :3 C++ тіркесі шығарылуы тиіс.
  9. Клиент аты, оның адресі, туған жылы және Vector<Purchase> контейнерінен тұратын Order (заказ) классын анықтаңыз. Purchase классында тауарды сипаттайтын келесі алаңдар болуы тиіс: name, unit_price және count. Order классының объектілерін файлдан оқу және файлға жазу механизмін анықтаңыз. Order классының объектілерін экранға шығару механизмін анықтаңыз. Кем дегенде Order классының 10 объектісінен тұратын файл құрып, оларды Vector< Order > контейнеріне санаңыз (считать), клиент аты боынша сұрыптап қайтадан файлға жазыңыз. Кем дегенде Order классының 10 объектісінен тұратын шамалы 3-тен 1 бөлігі бірінші файлдан алынатын тағы бір басқа файл құрып, List< Order > контейнеріне санаңыз (считать), клиент адресі бойынша сұрыптап қайтадан файлға жазыңыз. Std::merge() функциясын қолданып, екі файлды үшінші бір файлға біріктіріңіз.
  10. Алдыңғы жаттығудағы екі файлдағы заказдардың жалпы санын есептеңіз. Purchase классының бөлек объектісінің мәні unit_price*count – қа тең.
  11. Файлдан енгізу үшін графикалық тұтынушы интерфейсін құрыңыз.
  12. Заказдар файлы сұранысы үшін графикалық тұтынушы интерфейсін құрыңыз; мысалы, "Joe-дан барлық заказдарды табу", "Hardware файлындағы заказдардың жалпы бағасын анықтау" немесе "Clothing файлынан барлық заказдарды атап шығу". Еске салу: алдымен қарапайым интерфейс құрыңыз, содан кейін соның негізінде графикалыққа кірісіңіз.
  13. Тексттік файлды "тазалайтын" , сұраныстарды өңдейтін программа жазыңыз; яғни, пунктуация таңбаларын пробелдермен ауыстыру, сөздерді кіші регистрге ауыстырыңыз, don’t тіркесін do not (т.с.с) тіркесімен ауыстырыңыз және көпше түрдегі зат есімдерді жекеше түрге ауыстырыңыз (мысалы, ships сөзі ship сөзіне айналады). Осы программаны кем дегенде 5000 сөзден тұратын кез-келген тексттік файлға қолданыңыз.
  14. Алдыңғы жаттығудың нәтижелеріне сүйене отырып, келесі сұрақтарға жауап беретін және келесі амалдарды орындайтын программа жазыңыз: "ship сөзі файлда қанша рет кездеседі?", : "Қай сөз көп кездеседі?","Файлдағы қай сөз ең ұзын?"," Файлдағы қай сөз ең қысқа?","s әрпінен басталатын барлық сөздерді атаңыз?" және "Төрт әріптен тұратын барлық сөздерді атаңыз?".
  15. Алдыңғы жаттығудан графикалық тұтынушы интерфейсін құрыңыз.

Информация о работе Алгоритмдер мен ассоциативтік жиымдар