Bir va ikki o‘lchovli massiv elementlarini tartiblash, qidirish algoritmlari va ularning murakkabligini tahlil qilish asosida dastur yaratish
![Bir va ikki o‘lchovli massiv elementlarini tartiblash, qidirish
algoritmlari va ularning murakkabligini tahlil qilish asosida dastur
yaratish
Reja:
1. Bir va ikki o’lchovli massiv elementlarni tartiblash
2. Qidirish algoritmlari
3. Algoritmning murakkabligini tahlil qilish](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_1.png)
![Massivni saralash - bu massivdagi barcha elementlarni ma'lum tartibda
joylashtirish jarayoni. Bu ko'pincha foydalidir. Masalan, pochta qutingizdagi
elektron pochta xabarlari qabul qilingan vaqtga qarab ko'rsatiladi; yangi
elektron pochta xabarlari sizga yarim soat, bir soat, ikki yoki bir kun oldin
kelgan elektron pochta xabarlariga qaraganda ko'proq mos keladi; kontaktlar
ro'yxatiga kirganingizda, ismlar odatda alifbo tartibida bo'ladi, chunki shu
tarzda biror narsani topish osonroq. Ushbu holatlarning barchasi
ma'lumotlarni namoyish qilishdan oldin ularni saralashni o'z ichiga oladi.
Saralash qanday ishlaydi?
Ma'lumotlarni saralash nafaqat odamlar uchun, balki kompyuterlar
uchun ham massiv ichidan qidirishni samaraliroq qilishi mumkin. Masalan,
ismlar ro'yxatida ma'lum bir ism paydo bo'lishini bilishimiz kerak bo'lgan
holatni ko'rib chiqaylik. Buni bilish uchun siz massivning har bir elementini
bizning qiymatimiz bilan tekshirishingiz kerak. Ko'p elementli qatorni
qidirish juda samarasiz (qimmat) bo'lishi mumkin.
Biroq, bizning nomlarimiz qatori alfavit bo'yicha tartiblangan deb
taxmin qiling. Keyin bizning qidiruvimiz ma'noning birinchi harfi bilan
boshlanadi va alifboda keyingi harf bilan tugaydi. Bunday holda, agar biz
ushbu harfga yetib borsak va ismini topa olmasak, unda biz bu qatorning
qolgan qismida yo'qligini aniq bilamiz, chunki biz allaqachon o'z harfimizni
alifbo tartibida topshirganmiz!
Hech kimga sir emaski, tartiblangan massivlar ichida yanada yaxshi
qidirish algoritmlari mavjud. Oddiy algoritmdan foydalanib, biz faqat 20 ta
taqqoslash yordamida aniqlangan elementni 1000000 elementlardan iborat
tartibda qidirishimiz mumkin! Salbiy tomoni shundaki, massivni juda ko'p
sonli elementlarga ko'ra saralash nisbatan qimmatga tushadi va bitta qidiruv
so'rovi uchun amalga oshirilmaydi.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_2.png)
![Ba'zi hollarda, qatorni saralash qidirishni keraksiz holga keltiradi.
Masalan, biz talabalar orasida eng yaxshi test balini qidirmoqdamiz. Agar
massiv saralanmagan bo'lsa, unda biz eng yuqori ballni topish uchun
massivning har bir elementini skanerlashimiz kerak bo'ladi. Agar massiv
saralangan bo'lsa, unda eng yuqori ball birinchi pozitsiyada yoki oxirgisi
bo'ladi (massivni saralash uslubiga qarab: ko'tarilish yoki tushish tartibida),
shuning uchun biz qidirishning umuman hojati yo'q.
Tartiblash odatda qator elementlari juftlarini qayta taqqoslash va
belgilangan mezonlarga mos keladigan bo'lsa, ularni almashtirish orqali
amalga oshiriladi. Ushbu elementlarni taqqoslash tartibi qaysi saralash
algoritmidan foydalanilganiga bog'liq. Mezonlar massivning qanday
tartiblanishini belgilaydi (masalan, ko'tarilish yoki tushish tartibida).
Ikki elementni almashtirish uchun biz C ++ standart kutubxonasidan
std :: swap () funktsiyasidan foydalanishimiz mumkin, bu sarlavha fayli
algoritmida aniqlangan. C ++ 11 da std :: swap () funktsiyasi yordam
dasturining sarlavha fayliga ko'chirildi:
#include <iostream>
#include <algorithm>
int main()
{
int a = 3;
int b = 5;
std::cout << " a = " << a << ", b = " << b << '\n';
std::swap(a, b);](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_3.png)
![std::cout << " a = " << a << ", b = " << b << '\n';
}
Dasturni bajarish natijasi:
a=3, b=5
a=5, b=3
O'zgartirish operatsiyasidan so'ng a va b o'zgaruvchilarning qiymatlari
almashtirildi.
Massivlarni tanlash usuli bo'yicha saralash
Massivlarni saralashning ko'plab usullari mavjud. Massivlarni tanlov
usulidan foydalanib saralash, ehtimol bu eng oson bo'lsa ham, eng
sekinlaridan biri. Massivni eng kichikdan kattagacha elementlarni tanlab
saralash uchun quyidagi amallarni bajaring:
- 0 indeksidagi elementdan boshlab biz massivdagi eng kichik qiymatni
qidiramiz.
- Topilgan qiymatni nol element bilan almashtiramiz.
- Massivdagi keyingi indeks uchun # 1 va # 2 bosqichlarini takrorlang (endi
saralangan elementga tegmang).
Boshqacha qilib aytganda, biz massivdagi eng kichik elementni qidiramiz va
uni birinchi o'ringa o'tkazamiz. Keyin biz ikkinchi eng kichik elementni
qidiramiz va uni birinchi kichik elementdan keyin ikkinchi holatga
o'tkazamiz. Ushbu jarayon massivda saralanmagan elementlar tugamaguncha
davom etadi.
Ushbu algoritm 5 ta elementdan iborat massivda qanday ishlashiga misol:](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_4.png)
![{ 30, 50, 20, 10, 40 }
Birinchidan , biz 0 indeksidan boshlab eng kichik elementni qidiramiz :
{30, 50, 20, 10, 40}
Keyin biz eng kichik elementni 0 indeksidagi element bilan almashtiramiz:
{10, 50, 20, 30, 40}
Endi massivning birinchi elementi saralangan, biz unga e'tibor bermaymiz.
Biz keyingi eng kichik elementni qidiramiz, lekin 1 indeksidan boshlaymiz:
{10, 50, 20, 30, 40}
Va biz uni indeks 1dagi element bilan almashtiramiz:
{10, 20, 50, 30, 40}
Endi biz dastlabki ikkita elementni e'tiborsiz qoldirmoqdamiz. Ikkinchi
indeksdan boshlab keyingi eng kichik elementni qidiryapsiz:
{10, 20, 50, 30, 40}
Va biz uni indeks 2 da element bilan almashtiramiz:
{10, 20, 30, 50, 40}
3-indeksdan boshlab keyingi eng kichik elementni qidiryapsiz:](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_5.png)
![{10, 20, 30, 50, 40}
Va biz uni 3-indeksdagi element bilan almashtiramiz:
{10, 20, 30, 40, 50}
4-indeksdan boshlab keyingi eng kichik elementni qidiryapsiz:
{10, 20, 30, 40, 50}
Va biz uni 4-indeksdagi element bilan almashtiramiz (o'z-o'zini almashtirish
amalga oshiriladi, ya'ni biz hech narsa qilmaymiz):
{10, 20, 30, 40 50}
Bajarildi!
{10, 20, 30, 40, 50}
E'tibor bering, oxirgi taqqoslash har doim bitta bo'ladi (ya'ni o'zini
almashtirish), bu keraksiz operatsiya, shuning uchun aslida biz qatorning
oxirgi elementidan oldin saralashni to'xtatishimiz mumkin.
C ++ da tanlash usuli yordamida massivlarni saralash
Ushbu algoritm C ++ da qanday amalga oshiriladi:
#include <iostream>](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_6.png)
![#include <algorithm>
int main()
{
const int length = 5;
int array[length] = { 30, 50, 20, 10, 40 };
// Massivning har bir elementi bo'ylab aylantirib o'ting (oxirgisidan
tashqari, u biz unga y etib kelgan vaqtgacha tartiblangan bo'ladi)
for (int startIndex = 0; startIndex < length - 1; ++startIndex)
{
// eng kichikIndex o'zgaruvchisi biz ushbu takrorlashda topilgan
eng kichik qiymat indeksini ushlab turadi.
// Ushbu iteratsiyadagi eng kichik element birinchi element
bo'lishidan boshlang (indeks 0)
int smallestIndex = startIndex;
// Keyin massivning qolgan qismidan kichikroq elementni
qidirib //toping
for (int currentIndex = startIndex + 1; currentIndex < length; +
+currentIndex)
{
// Agar biz eng kichik elementimizdan kichikroq elementni
topsak,
if (array[currentIndex] < array[smallestIndex])
// keyin eslab qoling
smallestIndex = currentIndex;
}](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_7.png)
![// smallestIndex endi eng kichik element.
// Bizning eng kichik raqamimizni topilgan raqam bilan
almashtiring std::swap(array[startIndex],
array[smallestIndex]);
}
// Endi butun massiv saralanib, uni ekranda ko'rsating
for (int index = 0; index < length; ++index)
std::cout << array[index] << ' ';
return 0;
}
Ushbu algoritmning eng chalkash qismi - bu boshqa tsikl ichidagi tsikl
("joylashtirilgan tsikl" deb nomlanadi). Tashqi tsikl (startIndex) elementlar
ustida birma-bir (o'z navbatida) takrorlanadi. Tashqi tsiklning har bir
takrorlanishida ichki tsikl (currentIndex) massivda qolgan elementlar orasida
eng kichik elementni topish uchun ishlatiladi (startIndex + 1 dan boshlab).
smallestIndex ichki tsikl tomonidan topilgan eng kichik element indeksini
kuzatib boradi. Keyin eng kichikIndex startIndex-dan o'zgartiriladi. Nihoyat,
tashqi tsikl (startIndex) massivning keyingi indeksiga o'tadi va jarayon
takrorlanadi.
Agar yuqoridagi dastur qanday ishlashini tushunishda muammolarga
duch kelsangiz, uni qog'ozga yozib ko'ring. Dastlab (saralanmagan) massiv
elementlarini varaqning yuqori qismidagi qatorga gorizontal ravishda yozing.
Ayni paytda qaysi elementlar startIndex, currentIndex va smallestIndex
ekanligini ko'rsatish uchun o'qlarni torting. Dasturni qo'lda aylantiring va
ko'rsatkichlar o'zgarganda o'qlarni qayta chizib oling. Tashqi tsiklning har bir](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_8.png)
![takrorlanishidan so'ng, massivning hozirgi holatini (uning elementlari
joylashishini) ko'rsatadigan yangi chiziq chizamiz.
Qidirish algoritmlari. Barcha dasturchilar muammolarni yuechishda
massivda biron bir qiymat borligini tekshirish zarurligiga duch kelishdi.
Ushbu muammoni hal qilish uchun ko'plab algoritmlar mavjud. Ushbu
algoritmlarning barchasi boshqa dasturlash tillarida ham qo'llaniladi.
Bugun biz eng sodda qidirish algoritmini o'rganamiz (ammo ayni paytda
eng ko'p vaqt talab qiladigan) - chiziqli qidiruv.
Ushbu algoritm massivdagi barcha elementlarni takrorlaydi, ularni
berilgan kalit bilan taqqoslaydi, chunki to'liq qidirish tufayli qidirish tezligi
boshqa algoritmlarga qaraganda ancha past.
Odatda, agar qidiruv segmentida elementlar kam bo'lsa, aks holda
boshqa qidirish algoritmlaridan foydalaniladi (ulardan biri ikkilik qidiruv).
Chiziqli qidiruv amalda qanday ishlashini ko'rib chiqamiz Quyidagi
misolda biz 20 elementdan iborat massiv yaratdik va rand funktsiyasi
yordamida uning yacheykalarini tasodifiy sonlar bilan to'ldirdik.
26-qatorda biz foydalanuvchidan klaviaturadan tugmachani kiritishni
so'raymiz, so'ngra ushbu tugmachaning mavjudligini tekshiramiz. Agar kalit
massivning ba'zi bir katakchalariga to'g'ri kelsa, u holda biz ushbu katakning
indeksini namoyish etamiz. Bu algoritm qanday ishlashini tushunish uchun
odatiy misol.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_9.png)
![int main() {
setlocale(LC_ALL, "rus");
int ans[20];
int h = 0;
int arr[20];
int key;
srand ( time(NULL) );
for (int i = 0; i < 20; i++) {
arr[i] = 1 + rand() % 20;
cout << arr[i] << " ";
if (i == 9) {
cout << endl;
}
}
cout << endl << endl << " Kalitni kiriting : "; cin >> key;
for (int i = 0; i < 20; i++) {
if (arr[i] == key) {
ans[h++] = i;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_10.png)
![}
}
if (h != 0) {
for (int i = 0; i < h; i++) {
cout << "Kalit " << key << " da joylashgan" << ans[i] << endl;
}
}
else {
cout << "Massivdan " << key << " topilmadi";
}
system("pause");
return 0;
}
Lineer qidiruv 28 - 32 qatorlarda.
Keling, ushbu misolni ko'rib chiqaylik:
9-10 qatorda: biz ans massivini va h o'zgaruvchisini (nolga teng) yaratdik.
Barcha indekslar ans massivida saqlanadi.
29-qatorda: biz if dallanmalarini ishlatdik.
Agar shartning natijasi ijobiy bo'lsa, unda ans [h] katakchaga i qiymatini
beramiz va h o'zgaruvchisini bittaga ko'paytiramiz.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_11.png)
![34-qatorda: tekshiring:
Agar shartning natijasi ijobiy bo'lsa, unda ans massivining birinchi h
elementlarini chiqaramiz;
Agar shart natija manfiy bo'lsa, biz "Biz qatorda kalit kalitni topmadik" ni
chiqaramiz.
Chiziqli qidiruvdan foydalanish kerakmi
Ushbu algoritmning yagona afzalligi - bu oddiy dastur.
Minus bitta, lekin juda katta - kod sekin.
Dastlabki vazifalari uchun uni qo'g'irchoqlar uchun ishlatishni tavsiya etamiz.
Ammo, agar siz juda yuklangan dastur yoki veb-serverni ishlab chiqayotgan
bo'lsangiz, ushbu qidiruv juda qimmatga tushadi. Sizga yanada samarali
algoritmlar kerak bo'ladi. Masalan, ikkilik qidirish. Bu juda tez va amalga
oshirish chiziqli qidirishdan ko'ra murakkabroq emas.
Ikki o‘lchovli massivlar, ularni e’lon qilish usullari va ularni dasturlash
tilida ishlash mexanizmlari
Ko'p o'lchovli massivlar. Hozirgacha biz ko'rib chiqqan massivlar
tokchadagi kitoblar singari edi. Uzunroq tokchada ko'proq kitob bo'lishi
mumkin, qisqaroq javonda kamroq bo'lishi mumkin. Shunday qilib, kitob
javon uzunligi uning imkoniyatlarini belgilaydigan yagona o'lchovdir, ya'ni.
javon bir o'lchovli. Agar 3-rasmda ko'rsatilgan quyosh panellarini
simulyatsiya qilish uchun massivdan foydalanish kerak bo'lsa nima bo'ladi.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_12.png)
![Quyosh panellari, kitob javonlaridan farqli o'laroq, ikki o'lchovga ega:
uzunligi va kengligi.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_13.png)
![0-panel 1-panel 2-panel
3-panel 4-panel 5-panel0-ustun 1-ustun
2-ustun
0-satr
1-satr
3-rasm. Quyosh panellari massivi
Rasmda ko'rib turganingizdek oltita quyosh panellari ikki o'lchovli
tartibda joylashtirilgan: uchta ustunli ikki satr (qatorlar). Ammo siz ushbu
tartibni har biri o'zi uchta paneldan iborat bo'lgan ikkita elementdan iborat
massiv deb o'ylashingiz mumkin; boshqacha qilib aytganda, massivlar qatori
sifatida. C++ da ikki o'lchovli massivlarni yaratishingiz mumkin, ammo faqat
ikki o'lchov bilan cheklanmaysiz. Ehtiyojingizga va dasturning xususiyatiga
qarab xotirada ko'p o'lchovli massivlarni yaratishingiz mumkin.
Ko'p o'lchovli massivlarni e'lon qilish va initsializatsiyalash. C++ tili
har bir o'lchovda ajratilishi kerak bo'lgan elementlar sonini ko'rsatib, ko'p
o'lchovli massivlarni e'lon qilishga imkon beradi. Shunday qilib, 3- rasmdagi
quyosh panellarini aks ettiruvchi ikki o'lchovli butun sonlar massivini
quyidagicha e'lon qilishingiz mumkin:
int solarPanellDs[2][3];
3-rasmda oltita panelning har biriga 0 dan 5 gacha bo'lgan identifikator
berilgan. Agar biz butun sonli qatorni bir xil tartibda initsializatsiya qilsak,
unda bu initsializatsiya quyidagicha bo’ladi:](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_14.png)
![int solarPanellDs[2][3] = {{0, 1, 2}, {3, 4, 5}};
Ko'rib turganingizdek, boshlang'ich sintaksis ikki o'lchovli massivni
ishga tushirishda ishlatiladigan sintaksisga o'xshaydi. Agar qator uchta
qator va uchta ustundan iborat bo'lsa, uning e'lonlari va initsializatsiyasi
quyidagicha bo'ladi:
int Array3[3][3] = {{-501, 206, 2017}, {989, 101, 206}, {303, 456,
596}};
C ++ tili ko'p o'lchovli massiv modelidan foydalanishga imkon
berishiga qaramay, bunday massivlar xotirada hanuzgacha bir o'lchovli
sifatida saqlanadi.
Kompilyator ko'p o'lchovli massivni faqat bitta yo'nalishda
kengayadigan xotira maydoniga tushiradi.
Agar istasak, xuddi shu solarPanellDs qatorini quyidagi tarzda ishga
tushirishingiz mumkin - natija bir xil:
int solarPanellDs[2] [3] = {0, 1, 2 , 3, 4, 5};
Biroq, avvalgi usul aniqroq, chunki u ko'p o'lchovli massiv massivlar
massivi ekanligini tasavvur qilishni va tushunishni osonlashtiradi.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_15.png)
![Ko'p o'lchovli massiv elementlariga murojaat qilish. Ko'p o'lchovli
massivni massivlar qatori kabi ko'rib chiqaylik. Ilgari muhokama qilingan
ikki o'lchovli massiv uchta satr va uchta ustunni o'z ichiga olganligi sababli,
uni uchta elementdan iborat massiv deb o'ylashimiz mumkin, ularning har
biri uchta butun sondan iborat.
Shuning uchun, ushbu massivda butun songa kirish kerak bo'lganda,
birinchi indeksdan butun sonlarni saqlaydigan satr sonini, ikkinchi indeksdan
esa ushbu massivdagi ustun sonini ko'rsatish kerak. Quyidagi massivni ko'rib
chiqaylik:
int Array3[3][3] ={{-501, 206, 2017}, {989, 101, 206}, {303, 456, 596}};
U har biri uchta butun sonni o'z ichiga olgan uchta massiv sifatida
qaralishi uchun initsializatsiya qilingan. Bu yerda 206 qiymatiga ega butun
element [0][1] pozitsiyasida, 456 qiymatga ega element esa [2] [1]
pozitsiyada.
Quyidagi misolda ikki o’lchamli massivni e’lon qilish, uni to’ldirish va
uning elementlariga murojaat qilish ko’rsatilgan.
#include <iostream>
using namespace std;
int main()
{
const int M=3, N=2;
int Array2 [M][N];
cout<<"Massivni to'ldiring"<<endl;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_16.png)
![for(int i=0; i<M; i++)
for(int j=0; j<N; j++){
cout<<i<<","<<j<<"-elementini kiriting: ";
cin>>Array2[i][j];
}
cout<<"Massivning (1,1)-elementi:"<<Array2[1][1]<<endl;
return 0;
}
Dasturlashda funksiyalar bilan ishlash. Funksiya parametrlari va
argumentlari. Kelishuv bo’yicha argumentlar.
Funksiya - bu ma'lum bir vazifani bajarish uchun bayonotlar ketma-
ketligi. Ko'pincha, dastur kodi funksiyani bajarishi uchun boshqa
operatorlarni to’xtatib turadi.
Haqiqiy hayotda ham shunga o'xshash narsalarni doimo bajarasiz.
Masalan, siz kitob o'qiyapsiz va telefon orqali qo'ng'iroq qilishingiz
kerakligini eslaysiz. Kitobingizda xatcho'p qoldirasiz, telefonni ko'tarib
raqamni terasiz. Suhbatlashgandan so'ng, kitobni o'qishga qaytasiz, ya’ni
qoldirgan sahifangizdan kitobni o’qishni davom ettirasiz.
C++ dasturlari shunga o'xshash tarzda ishlaydi. Ba'zan, dastur kodni
bajarayotganda, funksiya murojaatiga duch kelishi mumkin. Funksiyaga
murojaat – bu protsessorga joriy funksiyani bekor qilishni va boshqa
funktsiyani ishlatishni aytadigan ifoda. Protsessor joriy bajarilish nuqtasida](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_17.png)
!["xatcho'p qoldiradi" va keyin chaqirilgan funktsiyani ishlatadi. Murojaat
qilingan funksiyani bajarish tugagandan so'ng, protsessor “xatcho'p”ga
qaytadi va to'xtatilgan funktsiya bajarilishini davom ettiradi.
Funksiyani e’lon qilish. Funksiya dastur bajaradigan harakatlarni
belgilaydi. Funksiyalar sizga ko'rsatmalar to'plamini ajratib ko'rsatish va unga
nom berish imkonini beradi. Keyin dasturning turli qismlarida tayinlangan
funksiya nomi yordamida bir necha marta murojaat qilish mumkin. Funksiya
aslida kodning nomlangan blokidir.
tip funksiya_nomi(parametrlar)
{
ko’rsatmalar
}
Birinchi satr funksiya sarlavhasini aks ettiradi. Dastlab, funksiyani
qaytarish turi (tipi) ko'rsatiladi. Agar funktsiya hech qanday qiymat
qaytarmasa, u holda void turi ishlatiladi.
Keyin ixtiyoriy identifikatorni ifodalovchi funktsiya nomi keladi.
Funksiyani nomlashda o'zgaruvchi nomlashda qo'llaniladigan qoidalardan
foydalaniladi.
Funksiya nomidan keyin parametrlar qavs ichida keltirilgan.
Funktsiyaning parametrlari bo'lmasligi mumkin, bu holda bo'sh qavslar
ko'rsatiladi.
Funksiya sarlavhasidan so'ng, sistemali qavslarda bajariladigan
ko'rsatmalar berilgan funksiya tanasini ifodalaydi.
Qaytish qiymati. Natija qaytarish uchun funksiya return operatoridan
foydalanadi. Agar funksiya qaytarish turi sifatida void tipidan boshqa har
qanday turga ega bo'lsa, u return operatori yordamida qiymatni qaytarishi
shart. Masalan, har qanday C++ dasturida bo'lishi kerak bo'lgan va uning
bajarilishi boshlanadigan asosiy funksiya ta'rifi:](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_18.png)
![int main()
{
return 0;
}
main() bajarilishini tugatgandan so'ng, return operatori yordamida butun
sonni operatsion tizimga qaytaradi.
Biz yozadigan funksiyalar qiymatlarni ham qaytarishi mumkin. Buning
uchun siz qaytish turini (yoki "qaytish tipini") belgilashingiz kerak. Bu
funksiyani e'lon qilishda, uning nomidan oldin ko'rsatiladi. Qaytish turi qaysi
qiymat qaytarilishini ko'rsatmasligini unutmang. Bu faqat ushbu qiymat turini
bildiradi.
So'ngra, chaqirilgan funksiya ichida, qaytish qiymatini belgilash uchun
return operatoridan foydalanamiz - qaysi qiymat murojaat qiluvchiga
qaytariladi.
Butun sonni qaytaradigan oddiy funktsiyani ko'rib chiqaylik:
int return7()
{
// Ushbu funktsiya butun qiymatni qaytaradi, shuning uchun biz return
operatoridan foydalanishimiz kerak
return 7;
}
void tipi. Yuqoridagi funksiyaning qaytish turi int, shuning uchun
funksiya return operatoridan foydalanishi va int turiga mos keladigan ba'zi bir
qiymatni qaytarishi kerak. Qaytish qiymati return bayonotidan keyin
joylashtiriladi.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_19.png)
![Funksiyalar qiymatlarni qaytarishi yoki qaytarmasligi mumkin.
Kompilyatorga funksiya qiymatni qaytarmasligini aytish uchun siz void
return turidan foydalanishingiz kerak. Quyida berilgan doPrint() funksiyasini
ko'rib chiqamiz:
void doPrint()
{
cout<<"Salom";
}
Ushbu funksiya void qaytarish turiga ega, ya'ni funksiya qiymatni
qaytarmaydi. Hech qanday qiymat qaytarilmasligi sababli, hech qanday
return bayonoti talab qilinmaydi.
Funksiyaga murojaat qilish . Funksiyadan foydalanish uchun uni
chaqirish kerak. Funksiya quyidagi shaklda chaqiriladi:
funksiya_nomi(argumentlar);
Funksiya nomidan keyin qavslar qo'shiladi, unda argumentlar - funksiya
parametrlari uchun qiymatlar keltirilgan.
Masalan, eng oddiy funksiyani aniqlaymiz va uni chaqiramiz:
#include <iostream>
void hello()
{
std::cout << "Salom\n";
}](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_20.png)
![int main()
{
hello();
hello();
return 0;
}
Bu hello funksiyasini belgilaydi, bu asosiy funksiyada ikki marta
chaqiriladi. Bu funktsiyalarning afzalligi: biz ba'zi bir umumiy harakatlarni
alohida funksiyaga o'tkazamiz va keyin ularni dasturning turli joylarida ko'p
marta chaqiramiz. Natijada, dastur "Salom" satrini ikki marta bosib chiqaradi.
Funksiyalarni chaqirishda quyidagi xatoliklarga yo’l qo’ymaslik kerak.
Quyidagi misolni qarab chiqaylik:
#include <iostream>
void returnNothing()
{
cout<<"Salom!"<<endl;
}
int main()
{
returnNothing();
cout<<returnNothing();// bu xatolik
return 0;
}](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_21.png)
![ReturnNothing() ga birinchi murojatt “Salom!” ni bosib chiqaradi,
ammo murojaat qiluvchiga hech narsa qaytarilmaydi. Bajarilish nuqtasi
main() funksiyasiga qaytadi, bu yerda dastur o'z bajarilishini davom ettiradi.
ReturnNothing() ga ikkinchi murojaat hatto tuzilmaydi. ReturnNothing()
funksiyasi void qaytarish turiga ega, ya'ni bu funktsiya qiymat bermaydi.
Biroq, main() funksiyasi ushbu qiymatni (qaytarilmagan) cout operatoriga
chiqish uchun yuborishga harakat qiladi. cout bu ishni ko'rib chiqa olmaydi,
chunki chiqish qiymati berilmagan. Shunday qilib, kompilyator xatoga yo'l
qo'yadi.
main() funksiyasi haqida. Endi siz main() funksiyasi qanday ishlashini
tushunasiz. Dastur bajarilgach, operatsion tizim main() funksiyasini chaqiradi
va uning bajarilishini boshlaydi. main() dagi ifodalar ketma-ket bajariladi.
Nihoyat, main() funktsiyasi operatsion tizimga butun qiymatni qaytaradi
(odatda 0). Shuning uchun main() funksiyasi int main () deb e'lon qilinadi.
Nima uchun operatsion tizimga qiymatlarni qaytarish kerak? Gap
shundaki, main() funksiyasining qaytish qiymati operatsion tizimga
dasturning muvaffaqiyati yoki muvaffaqiyatsizligi to'g'risida ma'lumot
beradigan holat kodidir. Odatda, qaytarish qiymati 0 (nol) har bir narsaning
muvaffaqiyatli bo'lganligini anglatadi, boshqa har qanday qiymat esa xato /
xato degan ma'noni anglatadi.
Shuni bilib olingki, C++ standartlari bo'yicha main() funktsiyasi butun
sonni qaytarishi kerakligini unutmang. Ammo, main() funktsiyasi oxirida
qaytishni ko'rsatmasangiz, xatolar bo'lmasa kompilyator avtomatik ravishda 0
qaytaradi. Lekin main() funktsiyasi oxirida return ni ko'rsatish va main()
funktsiyasi uchun int return turidan foydalanish tavsiya etiladi.
Funksiyaning qaytuvchi tipi haqida quyidagi ma’lumotlarni bilib olsih
kerak:](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_22.png)
![Birinchidan, funksiyani qaytarish turi void bo’lmasa, u belgilangan
turdagi qiymatni qaytarishi kerak (return operatoridan foydalaning).
Faqatgina istisno main () funksiyasi bo'lib, u boshqa qiymat berilmasa 0
qiymatini beradi.
Ikkinchidan, protsessor funksiyada return operatoriga duch kelganda,
darhol qiymatni murojaat qiluvchiga qaytaradi va ijro etish nuqtasi ham
murojaat qiluvchiga o'tadi. Funksiyada qaytarilish orqasida turgan har qanday
kod e'tiborga olinmaydi.
Funktsiya murojaat qiluvchiga return orqali faqat bitta qiymatni
qaytarishi mumkin. Bu raqam yoki (masalan, 7), yoki o'zgaruvchining
qiymati, yoki ifoda (natijaga ega) yoki mumkin bo'lgan qiymatlar to'plamidan
ma'lum bir qiymat bo'lishi mumkin.
Ammo bir vaqtning o'zida bir nechta qiymatlarni qaytarish orqali bitta
qiymatni qaytarish qoidasidan o'tish usullari mavjud, ammo bu haqida boshqa
darsda batafsil gaplashamiz.
Nihoyat, funktsiya muallifi uning qaytish qiymati nimani anglatishini hal
qiladi. Ba'zi funktsiyalar funksiyalarni bajarish natijasini (muvaffaqiyatga
erishdimi yoki yo'qmi) ko'rsatish uchun qaytarish qiymatlarini holat kodlari
sifatida ishlatadilar. Boshqa funksiyalar mumkin bo'lgan qiymatlar
to'plamidan ma'lum bir qiymatni qaytaradi. Bundan tashqari, umuman hech
narsa qaytarmaydigan funksiyalar mavjud.
Funksiyalardan bir necha marta foydalanish. Xuddi shu funksiyani
hatto turli xil dasturlarda ham bir necha marta chaqirish mumkin, bu juda
foydali:
#include <iostream>
using namespace std;
//getValueFromUser() funksiyasi foydalanuvchidan qiymatni oladi va
keyin uni murojaat qiluvchiga qaytaradi](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_23.png)
![int getValueFromUser()
{
cout<<"Raqam kiriting:";
int x;
cin>>x;
return x;
}
int main()
{
int a = getValueFromUser();
int b = getValueFromUser();
cout<<a<<"+"<<b<<"="<<a+b<<endl;
return 0;
}
Bu yerda main () 2 marta to'xtatiladi. E'tibor bering, har ikkala holatda
ham natija x qiymati o'zgaruvchida saqlanadi va keyin return yordamida main
() ga qaytariladi va u yerda a va b o’zgaruvchisi navbat bilan qiymat oladi.
Bundan tashqari main() boshqa funksiyalarni chaqira oladigan yagona
funktsiya emas. Har qanday funksiya boshqa har qanday funksiyani chaqira
oladi.
#include <iostream>
using namespace std;
void print0()
{
cout << "O" << endl;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_24.png)
![}
void printK()
{
cout << "K" << endl;
}
// PrintOK() funksiyasi printO() va printK() ni chaqiradi
void printOK()
{
printO();
printK();
}
int main()
{
cout << "Starting main()" << endl;
printOK();
cout << "Ending main()" << endl;
return 0;
}
Ichki funksiyalar. C ++ da ba'zi funksiyalarni boshqa funksiyalar ichida
e'lon qilish mumkin emas (ya'ni ularni joylashtirish mumkin emas). Quyidagi
kod kompilyatsiya xatoligini keltirib chiqaradi:
#include <iostream>
using namespace std;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_25.png)
![int main()
{
int boo() // bu funksiya main() funksiyasi ichida joylashgan, bu esa
ta'qiqlangan
{
cout << "boo!";
return 0;
}
boo();
return 0;
}
Bu aslida quyidagicha bo’ladi:
#include <iostream>
using namespace std;
int boo() // bu funksiya main() funksiyasi ichida joylashgan, bu esa
ta'qiqlangan
{
cout << "boo!";
return 0;
}
int main()
{
boo();](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_26.png)
![return 0;
}
Funksiya parametrlari va argumentlari. Ko'p hollarda, biz
chaqirilgan funksiyaga qandaydir tarzda ta'sir o'tkazishi uchun ma'lumotlarni
uzatishimiz kerak bo'ladi. Masalan, agar biz ikkita sonni ko'paytirish uchun
funksiya yozmoqchi bo'lsak, unda qanday qilib funktsiyaga ular qaysi
raqamlar bo'lishini aytib berishimiz kerak. Aks holda, u nimani nimaga
ko'paytirishni qayerdan biladi? Bu yerda parametrlar va argumentlar
tushunchasi kerak bo'ladi.
Funksiya parametri - bu funksiyada ishlatiladigan va qiymatini
chaqiruvchi (murojaat qiluvchi) tomonidan ta'minlanadigan o'zgaruvchidir.
Parametrlar funktsiyani e'lon qilishda qavs ichida ko'rsatiladi. Agar ularning
soni ko'p bo'lsa, ular vergul bilan ajratiladi, masalan:
// Bu funksiya hech qanday parametrga ega emas
void doPrint()
{
cout << "doPrint() funksiyasi" << std::endl;
}
// Bu funksiya bitta parametrga ega va u int tipiga tegishli
void printValue(int a)
{
cout << a << endl;
}
// Bu funksiya ikkita int tipidagi a va b parametrlariga ega](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_27.png)
![int add(int a, int b)
{
return a + b;
}
Har bir funksiyaning parametrlari faqat shu funksiya doirasida amal
qiladi. Shuning uchun, agar printValue() va add() parametrlari a deb
nomlangan bo'lsa, unda bu nom ziddiyatli bo'lishini anglatmaydi. Ushbu
parametrlar mustaqil deb hisoblanadi va bir-birlari bilan hech qanday ta'sir
qilmaydi.
Funksiya argumenti - bu murojaat qiluvchidan funksiyaga uzatiladigan
va murojaat qiluvchida funksiyani chaqirishda qavs ichida ko'rsatilgan
qiymat:
printValue(7);
add(4,5);
E'tibor bering, argumentlar vergul bilan ham ajratilgan. Argumentlar
soni parametrlar soniga to'g'ri kelishi kerak, aks holda kompilyator xato
xabari chiqaradi.
Funksiya parametrlari va argumentlari qanday ishlaydi? Funksiya
chaqirilganda uning barcha parametrlari local o'zgaruvchilar sifatida
yaratiladi va har bir argumentning qiymati mos keladigan parametrga (lokal
o'zgaruvchiga) ko'chiriladi. Ushbu jarayon qiymat bo’yicha uzatish
deyiladi. Masalan:
#include <iostream>
using namespace std;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_28.png)
![void printValues(int a, int b)
{
cout<<a<<endl;
cout<<b<<endl;
}
int main()
{
printValues(8,9);
return 0;
}
PrintValues () funksiyasi chaqirilganda, 8 va 9 argumentlari a va b
parametrlariga ko'chiriladi. a parametrga 8, b parametrga esa 9 qiymat
beriladi.
Parametrlar va funktsiyalarning qaytish qiymatlari qanday ishlaydi?
Parametrlar va qaytish qiymatlari yordamida biz ma'lumotlarni qabul
qiladigan va ishlov beradigan funktsiyalarni yaratib, so'ngra murojaat
qiluvchiga natijani qaytaramiz.
Masalan, ikkita butun sonni oladigan va ularning yig'indisini
qaytaradigan oddiy funksiya:
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a+b;
}
int main()
{](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_29.png)
![cout<<add(7,8)<<endl;
return 0;
}
Misol. Funksiyalarni bir necha usullarida chaqirish
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a+b;
}
int main()
{
cout<<add(7,8)<<endl;
return 0;
}
Ko’rinishi sohasi. Lokal va global o’zgaruvchilar
Ko’rinishi sohasi (scope) dasturning obyektini ishlatish mumkin bo'lgan
qismini ifodalaydi. Odatda, ko’rinish sohasi sistemali qavs ichida joylashgan
kod bloki bilan cheklanadi. Ko’rinish sohasiga qarab, yaratilgan obyektlar
global , lokal yoki avtomatik bo'lishi mumkin.
Dastlab , ikkita atamani tushunishimiz kerak: ko’rinish sohasi va
yashash vaqti . Ko’rinish sohasi o'zgaruvchini qayerda ishlatishni aniqlaydi.
Yashash vaqti (yoki "yashash muddati") o'zgaruvchining qayerda
yaratilganligini va u yo'q qilinishini aniqlaydi. Ushbu ikkita tushuncha bir-
biriga bog'liqdir.
Blok ichida aniqlangan o'zgaruvchilar lokal o'zgaruvchilar deyiladi.
Lokal o'zgaruvchilar avtomatik ishlash muddatiga ega: ular aniqlanish
nuqtasida yaratiladi (va agar kerak bo'lsa, ishga tushiriladi) va blokdan](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_30.png)
![chiqqandan keyin yo'q qilinadi. Lokal o'zgaruvchilar lokal ko’rinish sohasiga
(yoki "blok") ega, ya'ni ular e’lon qilingan nuqtadan kelib chiqadi va ular
aniqlangan blokning oxirida chiqadi.
Masalan, quyidagi dasturni ko'rib chiqaylik:
#include <iostream>
using namespace std;
int main()
{
int x=4;
double y=5.0;
cout<<x;
return 0;
}
Asosiy funksiya bloki ichida x va y o'zgaruvchilar aniqlanganligi
sababli, ikkalasi ham main () bajarilishini tugatgandan so'ng yo'q qilinadi.
Ichki bloklar ichida belgilangan o'zgaruvchilar ichki blok tugashi
bilanoq yo'q qilinadi:
#include <iostream>
int main() // tashqi blok
{
int m=4; // bu yerda m o'zgaruvchisi e'lon qilinyapti va initsializatsiya
qilinyapti
{ // ichki blokning boshlanishi
double k=5.0; //bu yerda k o'zgaruvchisi yaratiladi va ishga
tushiriladi](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_31.png)
![} // k ko'rinish sohasidan chiqib ketadi va bu yerda yo'q qilinadi
// Bu yerda k o'zgaruvchisini ishlatib bo'lmaydi.
k = k+1; //Bu xato
return 0;
}
Bunday o'zgaruvchilardan faqat ular aniqlangan bloklar ichida
foydalanish mumkin. Har bir funksiya o'z blokiga ega bo'lganligi sababli,
bitta funksiyadagi o'zgaruvchilar boshqa funksiyadagi o'zgaruvchilarga ta'sir
qilmaydi:
#include <iostream>
using namespace std;
void someFunction()
{
int value=5;
// value o'zgaruvchisidan faqat shu blokda foydalanish mumkin
} // value o'zgaruvchisi ko'rinishi sohasidan chiqdi va u yo'q qilinadi
int main()
{
// value o'zgaruvchisidan bu blokda foydalanib bo'lmaydi
someFunction();
return 0;
}
Turli xil funksiyalar bir xil nomdagi o'zgaruvchilar yoki parametrlarni
o'z ichiga olishi mumkin. Bu yaxshi, chunki ikkita mustaqil funksiya](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_32.png)
![o'rtasidagi ziddiyatlarni nomlash ehtimoli haqida tashvishlanishingiz shart
emas. Quyidagi misolda ikkala funktsiya ham x va y o'zgaruvchilarga ega.
Ular hatto bir-birlarining mavjudligini bilishmaydi:
#include <iostream>
using namespace std;
// add() funksiyasi
int add(int x, int y)
{
return x + y;
}
// main() ichida ham x va y o'zgaruvchilari ishlatilgan
int main()
{
int x = 5; // x o'zgaruvchisi e'lon qilingan
int y = 6;
cout << add(x, y) << endl; //main() funksiyasining x qiymati add()
funksiyasining x o'zgaruvchisiga ko'chiriladi
return 0;
}
Ichki bloklar ular belgilanadigan tashqi blokning bir qismi hisoblanadi.
Shunday qilib, tashqi blokda aniqlangan o'zgaruvchilar ichki blok ichida ham
ko'rish mumkin:
#include <iostream>
using namespace std;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_33.png)
![int main()
{ // tashqi blok
int x=5;
{ // ichki blokning boshlanishi
int y=7;
// x va y dan foydalanish mumkin
cout << x << " + " << y << " = " << x + y;
} // y o'zgaruvchisi yo'q qilinadi
// y o'zgaruvchisini bu yerda ishlatish mumkin emas, chunki u
allaqachon yo'q qilingan!
return 0;
}
Nomlarni yashirish. Ichki blok ichidagi o'zgaruvchi tashqi blok ichidagi
o'zgaruvchiga o'xshash nomga ega bo'lishi mumkin. Bu sodir bo'lganda, ichki
(ichki) blokdagi o'zgaruvchi tashqi o'zgaruvchini "yashiradi". Bunga
nomlarni yashirish deyiladi:
#include <iostream>
using namespace std;
int main()
{ // tashqi blok
int a=5;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_34.png)
![if (a >= 5)
{ // ichki blok
int a; // a o'zgaruvchisi ichki blokda yashirilmoqda
// a identifikatori endi ichki o'rnatilgan a o'zgaruvchiga ishora
qiladi.
// a tashqi o'zgaruvchisi vaqtincha yashiringan
a = 10; //Bu yerda tashqi emas, balki ichki a o'zgaruvchisiga
qiymat berilgan
cout << a << endl;
} // ichki a o'zgaruvchisi o'chirildi
// a identifikatori yana tashqi o'zgaruvchiga ishora qiladi
cout << a << endl;
return 0;
}
Imkon qadar nomlarni yashirishga umuman yo'l qo'ymaslik kerak,
chunki bu juda chalkash holatlarda olib kelishi mumkin. Iloji boricha tashqi
o'zgaruvchilar bilan bir xil nomdagi ichki o'zgaruvchilarni ishlatishdan
saqlanish lozim.
Global o’zgaruvchilar. Global o'zgaruvchilar dastur faylida har qanday
funktsiyalardan tashqarida aniqlanadi va har qanday funksiya tomonidan
ishlatilishi mumkin.
#include <iostream>
using namespace std;
void print();](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_35.png)
![int n = 5; //Global o'zgaruvchi
int main()
{
print(); // n=6
n++;
cout << "n=" << n << endl; // n=7
return 0;
}
void print()
{
n++;
cout << "n=" << n << endl;
}
Bu yerda n o'zgaruvchisi global va har qanday funksiyadan foydalanish
mumkin. Bundan tashqari, har qanday funksiya o'z qiymatini o'zgartirishi
mumkin.
Lokal o’zgaruvchilar . Kod bloki ichida yaratilgan obyektlar (u
funksiyani yoki qandaydir sikl tipidagi konstruktsiyani ifodalashi mumkin)
lokal deb nomlanadi. Bunday obyektlar faqat ular belgilangan kod bloki
ichida mavjud bo’ladi.
Qayta yuk l a n uvchi funksiyalar
Ayr i m algoritmlar berilganlar n ing har xil turdagi qiymatlari
uch u n qo’llan i shi mumki n . Masalan, ik k ita s on n ing mak s imumini
topish algoritmida b u sonlar butun yo ki haqiqiy turda b o’ l ishi
mumkin. Bun d ay hollarda bu algoritmlar ama l ga oshiril g an fu n k-
siyalar nomlari bir xil bo’l g ani ma ’ qul. Bir nechta funksi ya ni bir xil](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_36.png)
![nom l ash, lekin har xil turdagi parametrlar bil a n ish l atish
funks i yani qayta yuklash deyiladi.
Kompilyator parame t rlar tur i ga va s oniga qarab mos funksiyani
chaqiradi. Bun d ay amal n i « hal qilish amali » de yiladi va u ni n g
maqsadi parametrlarga ko’ra aynan (nisbatan) to’ g’ ri keladigan
funksiyani cha q irishdir. Agar bunday funksiya topilmasa kompil ya tor
xatolik haqida xabar beradi. Funksiyani aniqlashda funksiya
qaytaruvchi qiym a t turining ahamiyati yo’ q . Mis o l:
#include <iostream>
using namespace std;
int Max(int,int);
char Max(char,char);
float Max(float,float);
int Max(int,int,int);
int main()
{
int a,b;
char c,d;
int k;
float x,y;
cin>>a>>b>>k>>c>>d>>x>>y;
cout<<Max(a,b)<<endl;
cout<<Max(c,d)<<endl;
cout<<Max(a,b,k)<<endl;
cout<<Max(x,y);
return 0;
}](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_37.png)
![int Max(int i,int j)
{
return (i>j)?i:j;
}
char Max(char s1,char s2)
{
return (s1>s2)?s1:s2;
}
float Max(float x,float y)
{
return (x>y)?x:y;
}
int Max(int i,int j,int k)
{
if(i>j)
if(i>k)
return i;
else
return k;
if(j>k)
return j;
else
return k;
}
Ag a r funksiya chaqirilishida argument turi un i ng prototipidagi xud d i
sh u o’rindagi parametr turi g a mos kelmasa, kompilyator uni parametr](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_38.png)
![tu r iga keltirilishga harakat qiladi - bool va char turlarini int t u riga, float
t u rini double t u ri g a va int turini d o uble turiga o’tkazishg a .
Qayta yuklanuvchi funksi ya lardan foyda l anishda quyidagi
qoidalarga r i oya qilish kera k :
1) qayta yuklanuv ch i funksiyalar bitta ko’rinish sohasida bo’lishi
kera k ;
2) qayta yu kla nu vchi funksiyalarda ke l ishuv bo’yicha parametrlar
ishlatilsa, bunday parametrlar barcha qayta yu k lanuvchi funksiya-
larda ham ishl a t ilishi va ular bir xil qiymatga ega bo’lish kera k ;
3) agar funksiyalar parametrlarining turi fa q at «const» va ‘&’
belgilari bilan farq qilad i gan b o’ lsa, bu funk s iyalar qayta yuklanmaydi.
Keli sh uv b o’y i cha argu me ntlar. С ++ tilida funksiya chaqirilga n da
ayrim argumentlarni tushirib q oldirish mumkin. B unga funksiya
prototipida ushbu parametrlarni kelishuv bo’yi ch a qiymatini ko’rs a tish
orqali e r i shish mumkin. Masala n , quyida prototipi keltir i lgan funksiya
turli chaqirishga e g a bo’lishi m umkin:
//funksiya prototipi
void Butun_Son(int I,bool Bayroq=true,char Blg=’\n’);
//funksiyani chaqirish variantlari
Butun_Son(1,false,’a’);
Butun_Son(2,false);
Butun_Son(3);
Birinchi chaqiruvda barcha parame t rlar mos ar g ume n t l ar orq a li
qiymatlarini qabul qiladi, ikkinchi holda I p a ramet r i 2 qiy m atini,
bayroq parametri false qiy m atini va Blg o’ zgaruv ch isi ke l ishuv
bo’yicha ‘\n’ qiymatini qab u l qila d i.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_39.png)
![Keli sh uv bo’yicha qiymat berishni n g bitta sha r ti bor - para-
metrlar ro’yxatida kelishuv b o’yicha qiymat beri l gan parametrlardan
keyingi p arametrlar h am keli sh uv b o’yicha qiymatga ega bo’lishlari
shart. Yuqoridagi misolda I par a metri ke lishuv bo’ y icha qiymat qabul
qiling a n holda, Bay r oq yoki Blg parametrlari qiymatsiz bo’l i shi
mumkin emas. Misol tariqasida ber i lgan sonni ko’rsatilgan
aniqlikda chop e tuvchi p r ogrammani ko’rayl i k. Qo’yi l gan
masalani yechishda sonni daraja g a oshirish funksiyasi - pow()
va
suz u vchi nuqtali uzun sondan modul olish fabs l () funksiyasidan
foydal-niladi. B u funk s iyalar prototipi «math.h» sarlavha
faylida joylashgan.
#include <iostream>
#include <math.h>
using namespace std;
void Chop_qilish(double Numb, double Aniqlik=1, bool Bayroq = true)
{
if(!Bayroq)
Numb=fabsl(Numb);
Numb=(int)(Numb*pow(10,Aniqlik));
Numb=Numb/pow(10,Aniqlik);
cout<<Numb<<'\n';
}
int main()
{
double Mpi=-3.141592654;](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_40.png)
![Chop_qilish(Mpi,4,false);
Chop_qilish(Mpi,2);
Chop_qilish(Mpi);
return 0;
}
Programmada s onni turli aniqlikda (Aniql i k parametri
qiymati orqali) chop etish uchun har xil variantlarda Chop_qilish()
funksiyasi chaqirilgan. Programma ishla sh i natijasida ekranda
quyidagi sonlar chop etil a di:
3.1 4 15 -
3. 1 4
-3.1
Parametrning kelishuv b o’yicha beriladigan qiymati o’zgarmas,
global o’ z garuv ch i yoki qa n daydir funksiya tomonidan q aytaradi g an
qiymat bo’li sh i mumkin.
Rekursiv funksiyalar.
Rekursiya - bu nafaqat ilm-fan sohasida, balki kundalik hayotda ham
uchraydigan juda keng tarqalgan hodisa.
Dasturlashda rekursiya funksiyalar bilan chambarchas bog'liq, aniqrog'i
dasturlashdagi funksiyalar tufayli rekursiya yoki rekursiv funksiya kabi
tushunchalar mavjud.
Dasturlashda rekursiya funksiyalar bilan chambarchas bog'liq, aniqrog'i
dasturlashdagi funksiyalar tufayli rekursiya yoki rekursiv funksiya kabi
narsalar mavjud. Oddiy so'zlar bilan aytganda, rekursiya - bu funksiya
qismini o'zi orqali belgilash, ya'ni o'zini to'g'ridan-to'g'ri (tanasida) yoki](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_41.png)
![bilvosita (boshqa funktsiya orqali) chaqiradigan funksiya. Odatda rekursiv
muammolarga sonning faktorialini topish, Fibonachchi raqamini topish va
hokazolarni keltirish mumkin. Bu kabi masalalarni sikllar yordamida ham
hal qilish mumkin. Umuman aytganda, iterativ ravishda yechilgan hamma
narsani rekursiv, ya'ni rekursiv funksiya yordamida hal qilish mumkin.
C++ da rekursiv funksiya (yoki shunchaki "rekursiya") o'zini o'zi
chaqiradigan funksiya.
Masalan:
#include <iostream>
using namespace std;
void countOut(int count1)
{
std::cout << "push " << count1 << '\n';
countOut(count1-1); //countOut () funktsiyasi o'zini rekursiv chaqiradi
}
int main()
{
countOut(4);
return 0;
}
countOut(4) ga murojaat qilish “push 4” yozuvini bosib chiqaradi va
keyin countOut (3) ni chaqiradi. countOut (3) “push 3” ni bosib chiqaradi va
countOut (2) ga murojaat qiladi.
Rekursiyani tugatish sharti. Rekursiv funksiya chaqiruvlari odatdagi
funktsiya murojaatlari singari ishlaydi. Shu bilan birga, yuqoridagi dastur
oddiy funksiyalar va rekursivlar o'rtasidagi eng muhim farqni aks ettiradi: siz](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_42.png)
![rekursiyani tugatish shartini belgilashingiz kerak, aks holda funktsiya cheksiz
marta bajariladi.
Rekursiyani tugatish sharti - bu bajarilgandan so'ng rekursiv
funksiyani o'zi chaqirishni to'xtatadigan shart. Ushbu holat odatda if ifodasini
ishlatadi.
Bu yerda yuqoridagi funksiyaga misol keltirilgan, ammo bu yerda
rekursiya tugashi sharti ham mavjud:
#include <iostream>
using namespace std;
void countOut(int count1)
{
cout << "push " << count1 << '\n';
if (count1 > 1) // chiqish sharti
countOut(count1-1);
cout << "pop " << count1 << '\n';
}
int main()
{
countOut(4);
return 0;
}
Ushbu dasturni ishga tushirganimizda quyidagi qiymatlar ekranda chop
etiladi boshlanadi:
push 4
push 3
push 2](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_43.png)
![push 1
Rekursiv algoritmlar. Eng
mashhur matematik rekursiv
algoritmlardan biri bu
Fibonachchi ketma-ketligi.
Fibonachchi ketma-ketligini
tabiatda ham ko'rish mumkin: daraxt shoxlari, spiral kabuklar, ananas
mevalari, ochiladigan fern va boshqalar.
Fibonachchi raqamlarining har biri berilgan son joylashgan kvadratning
gorizontal tomonining uzunligi. Fibonachchi raqamlari matematik jihatdan
quyidagicha aniqlanadi:
F(n) = 0, agar n = 0
1, agar n = 1
F(n-1) + F(n-2), agar n > 1
Shunday qilib, Fibonachchi sonini hisoblash uchun rekursiv funksiyani
yozish juda oson:
#include <iostream>
using namespace std;
int fibonacci(int number)
{
if (number == 0)
return 0;
if (number == 1)
return 1; //
return fibonacci(number-1) + fibonacci(number-2);
}](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_44.png)
![// Dastlabki 13 ta Fibonachchi sonini topish
int main()
{
for (int count=0; count < 13; ++count)
cout << fibonacci(count) << " ";
return 0;
}
Rekursiya va Iteratsiya.
Rekursiv funksiyalar haqida eng ko'p so'raladigan savol: "Nima uchun
rekursiv funksiyadan foydalanish kerak, chunki bu masalalarni for sikli yoki
while sikli yordamida ham bajarish mumkin?” Ma'lum bo'lishicha, har doim
rekursiv masalani takroriy ravishda hal qilishingiz mumkin. Biroq,
ahamiyatsiz bo'lmagan holatlar uchun rekursiv versiyani yozish va o'qish
ko'pincha ancha osonlashadi. Masalan, n-Fibonachchi raqamini hisoblash
funksiyasini takrorlash operatorlari yordamida yozish mumkin, ammo bu
murakkab bo'ladi.
Iteratsion funktsiyalar ( for yoki while sikllaridan foydalanadigan
funksiyalar) deyarli har doim o'zlarining rekursiv o'xshashlariga qaraganda
samaraliroq. Buning sababi shundaki, har safar funksiya chaqirilganda
ma'lum miqdordagi resurslar sarflanadi. Iterativ funksiyalar ancha kam resurs
sarf qiladi.
Bu takrorlanadigan funktsiyalar har doim eng yaxshi variant degani
emas. Ba'zan rekursiv dastur yanada toza va sodda bo'lishi mumkin va
qo'shimcha qo'shimcha xarajatlar ko'proq bo'lishi mumkin, bu kodni](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_45.png)
![kelgusida saqlashdagi qiyinchiliklarni minimallashtiradi, ayniqsa algoritm
echim topishga juda ko'p vaqt ketmasa.
Umuman olganda, rekursiya, agar quyidagilarning aksariyati to'g'ri
bo'lsa, yaxshi tanlovdir:
– rekursiv kodni amalga oshirish ancha oson;
– rekursiya chuqurligini cheklash mumkin;
– algoritmning takrorlanadigan versiyasi ma'lumotlar to'plamini
boshqarishni talab qiladi;
– bu dasturning ishlashiga bevosita ta'sir ko'rsatadigan muhim kod
emas.
Funksiyalardan foydalanish sabablari. Dastlabki boshlovchi
dasturchilarda ko'pincha "Masalani funksiyalarsiz bajarish va barcha kodlarni
to'g'ridan-to'g'ri main() funksiyasiga qo'yish mumkinmi?" degan savol paydo
bo’ladi. Agar dastur kodingiz atigi 10-20 satrdan iborat bo'lsa, unda siz buni
qila olasiz. Jiddiy eslatma sifatida, funksiyalar kodni murakkablashtirishga
emas, balki soddalashtirishga qaratilgan. Ularning notrivial dasturlarda juda
foydali bo'lgan bir qator afzalliklar bor.
Struktura. Dasturlar hajmi/murakkabligi oshib borgan sari, barcha
kodlarni main() ichida saqlash qiyin bo'ladi. Funksiya mini-dasturga
o'xshaydi, biz uni kodning qolgan qismi bilan asosiy dasturdan alohida
yozishimiz mumkin. Bu sizga murakkab vazifalarni kichikroq va sodda
vazifalarga ajratishga imkon beradi, bu esa dasturning umumiy
murakkabligini keskin pasaytiradi.
Takror foydalanish. Funksiya e'lon qilingandan so'ng, uni ko'p marta
chaqirish mumkin. Bu kodning takrorlanishiga yo'l qo'ymaydi va kodni
nusxalash/joylashtirishda xatolar ehtimolini kamaytiradi. Funksiyalar boshqa](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_46.png)
![dasturlarda ham ishlatilishi mumkin, bu har safar noldan yozilishi kerak
bo'lgan kod miqdorini kamaytiradi.
Testlash. Funksiyalar keraksiz kodni olib tashlaganligi sababli, uni
testlash osonroq bo'ladi va funksiya mustaqil birlik bo'lgani uchun, uning
ishlashiga ishonch hosil qilish uchun uni bir marta sinab ko'rishimiz kerak,
keyin uni sinovdan o'tkazmasdan (bu funksiyaga o'zgartirish
kiritmagunimizcha) qayta-qayta ishlata olamiz.
Modernizatsiya. Agar dasturga o'zgartirish kiritishingiz yoki uning
funksiyasini kengaytirishingiz kerak bo'lsa, unda funksiyalar juda yaxshi
imkoniyatdir. Ularning yordami bilan hamma joyda ishlashlari uchun ularni
bitta joyda o'zgartirishingiz mumkin.
Abstraktsiya. Funksiyadan foydalanish uchun biz uning nomini, kirish
ma'lumotlarini, chiqish ma'lumotlarini va funksiya qayerda joylashganligini
bilishimiz kerak. Uning qanday ishlashini bilishimiz shart emas. Bu
boshqalar tushunishi mumkin bo'lgan kod yozish uchun juda foydalidir
(masalan, C++ standart kutubxonasi va undagi barcha narsalar shu prinsip
asosida tuzilgan).
Har safar kiritish yoki chiqarish operatori uchun std::cin yoki std::cout
deb nomlaganimizda, biz C++ standart kutubxonasidan yuqoridagi barcha
tushunchalarga amal qiladigan funksiyadan foydalanamiz.
Funksiyalardan samarali foydalanish. Yangi boshlovchilar duch
keladigan eng keng tarqalgan muammolardan biri bu funksiyalarni qayerda,
qachon va qanday qilib samarali ishlatishni tushunishdir. Funktsiyalarni
yozish uchun ba'zi bir asosiy ko'rsatmalar:
1-tavsiya . Dasturda bir necha marta paydo bo'lgan kod funksiya sifatida
yaxshi yozilgan. Masalan, agar biz xuddi shu tarzda foydalanuvchidan bir
necha marta ma'lumotlarni olsak, bu alohida funktsiyani yozish uchun ajoyib
imkoniyat.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_47.png)
![2-tavsiya . Biron bir narsani saralash uchun ishlatiladigan kod alohida
funksiya sifatida yozilgan yaxshiroqdir. Masalan, bizda saralash kerak
bo'lgan narsalar ro'yxati bo'lsa, biz saralash funksiyasini yozamiz, bu yerda
biz saralanmagan ro'yxatni o'tkazamiz va saralangan joyni olamiz.
3-tavsiya . Funksiya bitta (va faqat bitta) vazifani bajarishi kerak.
4-tavsiya . Agar funksiya juda katta, murakkab yoki tushunarsiz bo'lib
qolsa, uni bir nechta kichik funksiyalarga bo'lish kerak. Bunga kodni qayta
ishlash deyiladi.](/data/documents/3e3c9b36-0b52-4398-827a-83154e82a539/page_48.png)
Bir va ikki o‘lchovli massiv elementlarini tartiblash, qidirish algoritmlari va ularning murakkabligini tahlil qilish asosida dastur yaratish Reja: 1. Bir va ikki o’lchovli massiv elementlarni tartiblash 2. Qidirish algoritmlari 3. Algoritmning murakkabligini tahlil qilish
Massivni saralash - bu massivdagi barcha elementlarni ma'lum tartibda joylashtirish jarayoni. Bu ko'pincha foydalidir. Masalan, pochta qutingizdagi elektron pochta xabarlari qabul qilingan vaqtga qarab ko'rsatiladi; yangi elektron pochta xabarlari sizga yarim soat, bir soat, ikki yoki bir kun oldin kelgan elektron pochta xabarlariga qaraganda ko'proq mos keladi; kontaktlar ro'yxatiga kirganingizda, ismlar odatda alifbo tartibida bo'ladi, chunki shu tarzda biror narsani topish osonroq. Ushbu holatlarning barchasi ma'lumotlarni namoyish qilishdan oldin ularni saralashni o'z ichiga oladi. Saralash qanday ishlaydi? Ma'lumotlarni saralash nafaqat odamlar uchun, balki kompyuterlar uchun ham massiv ichidan qidirishni samaraliroq qilishi mumkin. Masalan, ismlar ro'yxatida ma'lum bir ism paydo bo'lishini bilishimiz kerak bo'lgan holatni ko'rib chiqaylik. Buni bilish uchun siz massivning har bir elementini bizning qiymatimiz bilan tekshirishingiz kerak. Ko'p elementli qatorni qidirish juda samarasiz (qimmat) bo'lishi mumkin. Biroq, bizning nomlarimiz qatori alfavit bo'yicha tartiblangan deb taxmin qiling. Keyin bizning qidiruvimiz ma'noning birinchi harfi bilan boshlanadi va alifboda keyingi harf bilan tugaydi. Bunday holda, agar biz ushbu harfga yetib borsak va ismini topa olmasak, unda biz bu qatorning qolgan qismida yo'qligini aniq bilamiz, chunki biz allaqachon o'z harfimizni alifbo tartibida topshirganmiz! Hech kimga sir emaski, tartiblangan massivlar ichida yanada yaxshi qidirish algoritmlari mavjud. Oddiy algoritmdan foydalanib, biz faqat 20 ta taqqoslash yordamida aniqlangan elementni 1000000 elementlardan iborat tartibda qidirishimiz mumkin! Salbiy tomoni shundaki, massivni juda ko'p sonli elementlarga ko'ra saralash nisbatan qimmatga tushadi va bitta qidiruv so'rovi uchun amalga oshirilmaydi.
Ba'zi hollarda, qatorni saralash qidirishni keraksiz holga keltiradi. Masalan, biz talabalar orasida eng yaxshi test balini qidirmoqdamiz. Agar massiv saralanmagan bo'lsa, unda biz eng yuqori ballni topish uchun massivning har bir elementini skanerlashimiz kerak bo'ladi. Agar massiv saralangan bo'lsa, unda eng yuqori ball birinchi pozitsiyada yoki oxirgisi bo'ladi (massivni saralash uslubiga qarab: ko'tarilish yoki tushish tartibida), shuning uchun biz qidirishning umuman hojati yo'q. Tartiblash odatda qator elementlari juftlarini qayta taqqoslash va belgilangan mezonlarga mos keladigan bo'lsa, ularni almashtirish orqali amalga oshiriladi. Ushbu elementlarni taqqoslash tartibi qaysi saralash algoritmidan foydalanilganiga bog'liq. Mezonlar massivning qanday tartiblanishini belgilaydi (masalan, ko'tarilish yoki tushish tartibida). Ikki elementni almashtirish uchun biz C ++ standart kutubxonasidan std :: swap () funktsiyasidan foydalanishimiz mumkin, bu sarlavha fayli algoritmida aniqlangan. C ++ 11 da std :: swap () funktsiyasi yordam dasturining sarlavha fayliga ko'chirildi: #include <iostream> #include <algorithm> int main() { int a = 3; int b = 5; std::cout << " a = " << a << ", b = " << b << '\n'; std::swap(a, b);
std::cout << " a = " << a << ", b = " << b << '\n'; } Dasturni bajarish natijasi: a=3, b=5 a=5, b=3 O'zgartirish operatsiyasidan so'ng a va b o'zgaruvchilarning qiymatlari almashtirildi. Massivlarni tanlash usuli bo'yicha saralash Massivlarni saralashning ko'plab usullari mavjud. Massivlarni tanlov usulidan foydalanib saralash, ehtimol bu eng oson bo'lsa ham, eng sekinlaridan biri. Massivni eng kichikdan kattagacha elementlarni tanlab saralash uchun quyidagi amallarni bajaring: - 0 indeksidagi elementdan boshlab biz massivdagi eng kichik qiymatni qidiramiz. - Topilgan qiymatni nol element bilan almashtiramiz. - Massivdagi keyingi indeks uchun # 1 va # 2 bosqichlarini takrorlang (endi saralangan elementga tegmang). Boshqacha qilib aytganda, biz massivdagi eng kichik elementni qidiramiz va uni birinchi o'ringa o'tkazamiz. Keyin biz ikkinchi eng kichik elementni qidiramiz va uni birinchi kichik elementdan keyin ikkinchi holatga o'tkazamiz. Ushbu jarayon massivda saralanmagan elementlar tugamaguncha davom etadi. Ushbu algoritm 5 ta elementdan iborat massivda qanday ishlashiga misol:
{ 30, 50, 20, 10, 40 } Birinchidan , biz 0 indeksidan boshlab eng kichik elementni qidiramiz : {30, 50, 20, 10, 40} Keyin biz eng kichik elementni 0 indeksidagi element bilan almashtiramiz: {10, 50, 20, 30, 40} Endi massivning birinchi elementi saralangan, biz unga e'tibor bermaymiz. Biz keyingi eng kichik elementni qidiramiz, lekin 1 indeksidan boshlaymiz: {10, 50, 20, 30, 40} Va biz uni indeks 1dagi element bilan almashtiramiz: {10, 20, 50, 30, 40} Endi biz dastlabki ikkita elementni e'tiborsiz qoldirmoqdamiz. Ikkinchi indeksdan boshlab keyingi eng kichik elementni qidiryapsiz: {10, 20, 50, 30, 40} Va biz uni indeks 2 da element bilan almashtiramiz: {10, 20, 30, 50, 40} 3-indeksdan boshlab keyingi eng kichik elementni qidiryapsiz: