Dumaloq bir tomonlama ro'yxat. Dinamik ma'lumotlar tuzilmalari bo'yicha muammolarni hal qilish. OCS ga tugun qo'shish
Oxirgi yangilanish: 25.10.2016
Ringli (aylana, siklik) roʻyxatlar bogʻlangan roʻyxatlarning bir turidir. Ular oddiygina ulanishi yoki ikki marta ulanishi mumkin. Ularning o'ziga xos xususiyat shartli oxirgi element birinchi elementga havolani saqlaydi, shuning uchun ro'yxat yopiq yoki aylana bo'lib chiqadi.
Misol uchun, agar bizning ro'yxatimiz bitta bosh elementdan iborat bo'lsa, unda biz bunday ro'yxatni quyidagicha yopishimiz mumkin:
Head.next = bosh;
Amalga oshirish uchun, keling, alohida bog'langan ro'yxatda ishlatiladigan element sinfini olaylik:
Umumiy sinf tugunlari
Endi dumaloq ro'yxat sinfini aniqlaymiz:
System.Collections dan foydalanish; System.Collections.Generic yordamida; SimpleAlgorithmsApp nom maydoni (ommaviy sinf CircularLinkedList
Qo'shimcha, asosan, ko'rsatgichni oxirgi dum elementiga qayta o'rnatish va yangi elementni quyruq va bosh orasiga joylashtirishni anglatadi:
Umumiy bekor Qo'shish (T ma'lumotlari) ( Tugun
O'chirishda biz ko'rsatgichni o'chirilayotgan elementga nisbatan oldingi elementdan keyingi elementga qaytaramiz:
Umumiy bool olib tashlash (T ma'lumotlari) ( Tugun
Dumaloq ro'yxat yordamida:
CircularLinkedList
Konsol chiqishi:
Tom Bob Elis Jek olib tashlanganidan keyin: Tom Elis Jek
Chiziqli ro'yxatning kerakli elementiga kirish uchun siz asl ko'rish nuqtasining pozitsiyasidan qat'i nazar, ro'yxatni boshidan ko'rishingiz kerak. Bu ro'yxatdagi elementlarga kirish operatsiyalarini sekinlashtiradi. Ro'yxatning elementlarini halqaga yopish bu kamchilikni yo'q qiladi. Bunday ro'yxat tsiklik deb ataladi. Dumaloq ro‘yxatni faqat boshidan emas, balki istalgan elementdan ko‘rishni boshlashingiz mumkin va ro‘yxatning boshi uning istalgan elementi bo‘lishi mumkin. Doiraviy ro'yxatning mantiqiy tuzilishi:
Tsiklik ro'yxat bo'yicha operatsiyalar
Dumaloq ro'yxatning tepasida Bilan chiziqli ro'yxat uchun belgilangan barcha amallar bajarilishi mumkin. E'tibor bering, tsiklik ro'yxatning mantiqiy tuzilishida "boshlanishi" va "oxiri" tushunchalari shartli bo'lib, sarlavha bo'lgan ro'yxatning biron bir elementiga ko'rsatgichning o'rni bilan belgilanadi.
Tsiklik ro'yxat uchun yangi operatsiya ham joriy etiladi - ikkita tsiklik ro'yxatni birlashtirish - Concat(Bilan 1,Bilan 2).
Doiraviy ro'yxatning bir-biriga bog'langan amalga oshirilishi
Dinamik o'zgaruvchilar yordamida dumaloq ro'yxatni amalga oshirish:
Bunday ro'yxat deyiladi yakka bog'langan aylana ro'yxati. Ro'yxatning istalgan elementidan istalgan boshqa elementga kirishingiz mumkin. E'tibor bering, dumaloq ro'yxatda birinchi va oxirgi element mavjud emas. Tashqi ko'rsatgich Head ro'yxatning joriy elementiga ko'rsatgich sifatida foydalanish uchun qulay. Muayyan muammolarni hal qilishda, biz shartli ravishda u hal qiladi deb taxmin qilishimiz mumkin oxirgi ro'yxat elementi, bu avtomatik ravishda birinchi navbatda keyingi elementni qiladi.
tCircleList sinfini quyidagicha tavsiflash mumkin:
tValue= Haqiqiy; // ro'yxat elementi qiymat turi - haqiqiy
pItem= ^tItem; // ro'yxat elementiga ko'rsatgich turi
tItem = rekord// ro'yxat elementi turi
Qiymat: tValue; // ro'yxat elementining mazmuni
Keyingi: pItem; // ro'yxatning keyingi elementiga ko'rsatgich
oxiri; // yozib olish tItem
tCircleList = sinf // Sinf - tsiklik ro'yxati
himoyalangan
fHead:pItem; // maydon - ko‘rsatgichjoriy elementro'yxati
fSize: Word; // maydon - ro'yxat elementlari soni
ommaviy
// Xususiyat - ro'yxat elementlari soni (o'qish va yozish huquqi)
mulk Hajmi: Word o'qing fSize yozish fSize;
// Property - ro'yxat boshiga ko'rsatgich (o'qish va yozish huquqi)
mulk Bosh: So'z o'qing fBosh yozish fBosh;
vmanzil elementidan keyinAdr
tartib InsertAfter(Addr: pItem; v: tValue);
// Qiymatli elementni qo'shishvmanzil elementidan oldinAdr
tartib InsertBefore(Addr: pItem; v: tValue);
// Addr manzilli elementdan keyingi elementni chiqarib tashlang
funktsiyasi DeleteAfter(Addr: pItem): tValue;
// Ko'rsatkichli elementni istisno qilishAdr
funktsiyasi O'chirish(Addr:pItem):tValue;
// Qiymatli elementni qo'shishvro'yxatning boshiga
tartib InsertHead(v:tValue);
// Qiymatli elementni qo'shishvro'yxatning oxirigacha
tartib InsertRear(v:tValue);
// Ro'yxat boshidan elementni chiqarib tashlash
funktsiyasi DeleteHead: tValue;
// Ro'yxat oxiridagi elementni chiqarib tashlash
funktsiyasi DeleteRear: tValue;
tartib Concat( var CList2: tCircleList); // debriyaj bilan ro'yxatiCList2
// Ro'yxatda qiymatga ega elementni qidiringvva uning manzilini qaytaradi
funktsiyasi Qidiruv(v: tValue): pItem;
funktsiyasi Bo'sh: mantiqiy; // qaytishrost,Agar ro'yxati bo'sh
tartib Tozalash; // ro'yxatni tozalash
konstruktor Yaratmoq; // konstruktor - bo'sh ro'yxat yaratish
buzuvchi Yo'q qilish; bekor qilish; // buzuvchi - o'chirish ro'yxati
oxiri; // sinftCircleList
tCircleList klassi tList sinfining avlodi deb e'lon qilinmaydi, chunki uning deyarli barcha usullarini amalga oshirish tsiklik bo'lmagan ro'yxat uchun bir xil nomdagi usullarni amalga oshirishdan farq qiladi. Farqlar asosan quyidagilardan iborat:
– InsertAfter va InsertBefore amallari uchun elementni bo‘sh ro‘yxatga kiritish va tsiklik ro‘yxatning boshi va oxiriga kiritish boshqacha tarzda amalga oshiriladi;
– DeleteAfter operatsiyasini bitta elementdan iborat siklik ro‘yxatga qo‘llash ushbu elementning o‘zini chiqarib tashlashga olib kelmasligi kerak;
– DeleteAfter va Delete usullari, agar ushbu amallar davomida yo'q qilingan bo'lsa, ko'rsatgichni tsiklik ro'yxatning oxirgi elementiga qaytarishi kerak;
– Qidiruv va tozalash usullarida tsiklik ro‘yxatni ko‘rib chiqish tugallanganligi belgisi yordamchi ko‘rsatgich ko‘rish boshlangan elementga yetib borishi hisoblanadi.
Va faqat Create konstruktori va Destroy destruktori tList sinfidagi bir xil nomdagi usullar bilan bir xil tarzda amalga oshiriladi.
Shubhasiz, joriy elementning o'ng va chap tomonidagi qo'shish va istisno qilish operatsiyalari (InsertHead, InsertRear, DeleteHead, DeleteRear) siklik bo'lmagan ro'yxat uchun bir xil nomdagi operatsiyalar bilan bir xil amallarni bajaradi. Farqi shundaki, agar ro'yxat chapga yoki o'ngga kengaytirilgan yoki chapga yoki o'ngga toraygan bo'lsa, yangi amallar ko'rsatkich qiymatini aylana ro'yxatining oxirgi elementiga o'zgartiradi.
Ma'ruza matni.
Massivlar, to'plamlar, yozuvlar kabi tizimli ma'lumotlar turlari statik tuzilmalardir, chunki ularning o'lchamlari dasturning butun bajarilishi davomida o'zgarmaydi. Ma'lumotlar tuzilmalari ko'pincha muammoni hal qilishda ularning hajmini o'zgartirishi talab qilinadi. Bunday ma'lumotlar tuzilmalari dinamik deb ataladi, ular steklar, navbatlar, ro'yxatlar, daraxtlar va boshqalarni o'z ichiga oladi. Massivlar, yozuvlar va fayllar yordamida dinamik tuzilmalarni tavsiflash xotiradan behuda foydalanishga olib keladi va muammolarni hal qilish uchun zarur bo'lgan vaqtni oshiradi.
Struktura turlari, ko'rsatkichlar va dinamik o'zgaruvchilardan foydalanib, siz turli xil dinamik xotira tuzilmalarini yaratishingiz mumkin. C++ tilidagi ko'rsatkichlarning xususiyatlari statik e'lon qilingan o'zgaruvchilar yoki statik va dinamik o'zgaruvchilar aralashmasi asosida dinamik xotira tuzilmalarini qurish imkonini beradi. Barcha dinamik tuzilmalarni tashkil qilish g'oyasi bir xil. Bir yoki bir nechta maydonlari bir xil yoki boshqa struktura turiga ko'rsatgich sifatida e'lon qilingan ma'lum bir tuzilma turi S aniqlanadi. Dastur strukturaning to'liq dinamik yaratilishida S tipidagi d o'zgaruvchini yoki S tipidagi ko'rsatgichni e'lon qiladi. Ushbu o'zgaruvchining nomi dasturni bajarishda dinamik strukturaning "ildiz" (ota-ona nomi) nomi sifatida ishlatiladi. Dasturni bajarish jarayonida, dinamik tuzilma qurilayotganda, tegishli turdagi dinamik o'zgaruvchilar so'raladi va d o'zgaruvchisidan yoki d o'zgaruvchisi ko'rsatgichni o'z ichiga olgan birinchi dinamik o'zgaruvchidan boshlab havolalar orqali bog'lanadi. Ushbu yondashuv har qanday topologiyaga ega dinamik tuzilmani yaratishga imkon beradi.
Dumaloq (ring) ro'yxati elementlar ketma-ketligi bo'lgan ma'lumotlar strukturasi bo'lib, uning oxirgi elementida ro'yxatning birinchi elementiga ko'rsatgich, birinchisida (ikki tomonlama ro'yxat bo'lsa) oxirgisiga ko'rsatgich mavjud.
Ushbu tashkilotning asosiy xususiyati shundaki, ushbu ro'yxatda null ko'rsatkichlarni o'z ichiga olgan elementlar mavjud emas va shuning uchun eng tashqi elementlarni tanlab bo'lmaydi.
Chiziqli ro'yxatlar kabi doiraviy ro'yxatlar bir yo'nalishli yoki ikki tomonlama bo'lishi mumkin.
Dumaloq bir tomonlama ro'yxat chiziqli bir tomonlama roʻyxatga oʻxshaydi, lekin uning oxirgi elementida uni birinchi element bilan bogʻlovchi koʻrsatgich mavjud (1-rasm).
Bunday ro'yxatni to'liq aylanib o'tish uchun chiziqli bir tomonlama ro'yxatdagi kabi birinchisiga emas, balki ixtiyoriy elementga ko'rsatgich bo'lishi kifoya. Bu erda "birinchi" element tushunchasi juda o'zboshimchalik va har doim ham talab qilinmaydi. Ba'zida biron bir elementni maxsus ko'rsatgichni qo'yish orqali "birinchi" deb ta'kidlash foydali bo'ladi. Bu, masalan, ro'yxatni ko'rishda "aylanish" ning oldini olish uchun talab qilinadi.
Guruch. 1. Doiraviy bir tomonlama ro'yxat
Dumaloq bir tomonlama ro'yxat bilan bajariladigan asosiy operatsiyalar:
· ro'yxat tuzish;
· ro‘yxatni chop etish (ko‘rish);
· elementni ro‘yxatga kiritish;
· ro‘yxatdagi elementni qidirish;
· ro'yxat bo'sh yoki yo'qligini tekshirish;
· ro'yxatni o'chirish.
Ushbu asosiy operatsiyalar uchun algoritmlarni tavsiflash uchun biz chiziqli bir tomonlama ro'yxat uchun bir xil deklaratsiyalardan foydalanamiz.
Tsiklik bir yo'nalishli ro'yxat bilan ishlashda sanab o'tilgan asosiy operatsiyalarning funktsiyalarini keltiramiz.
// bir tomonlama dumaloq ro'yxat yarating
Void Make_Circle_Single_List(int n,
Circle_Single_list** Head, Circle_Single_list* Loop)(
(*Bosh) = yangi Circle_Single_List();
cout<< "Введите значение ";
cin >> (*Bosh)->Ma'lumotlar;
(*Bosh) ->
Doira_Yagona_Ro'yxat(n-1,&((*Bosh)->Keyingi), Loop);
// dumaloq bir yo'nalishli ro'yxatni chop etish
void Chop etish_doira_yagona_ro'yxat(aylana_yagona_ro'yxat* boshi) (
Circle_Single_List* ptr=Bosh;
//yordamchi ko'rsatgich
cout<< ptr->Ma'lumotlar<< "\t";
ptr=ptr->Keyingi;
) while (ptr!=Head);
cout<< "\n";
/*aylanma bir tomonlama ro‘yxatga berilgan raqamdan keyin element qo‘shing*/
Circle_Single_List* Insert_Element_Circle_Single_list(Circle_Single_list* Head,
int raqami, int DataItem)(
//birinchi element ustida turing
Circle_Single_List *NewItem = new(Circle_Single_List);
// yangi element yaratildi
NewItem->Data = DataItem;
NewItem->Keyingi = NewItem;
else (//roʻyxat boʻsh emas
uchun (int i = 1; i< Number; i++)
Joriy = Joriy->Keyingi;
NewItem->Keyingi = Current->Keyingi;
Current->Keyingi = NewItem;
/*aylanma bir tomonlama roʻyxatdan berilgan raqamga ega elementni olib tashlash*/
Circle_Single_List* Doira_Yagona_Ro'yxatni_o'chirish
(Circle_Single_List* Head, int Number)(
agar (Bosh != NULL)(
Circle_Single_List *Joriy = Bosh;
agar (Bosh->Keyingi!= Bosh)(
uchun (int i = 1; i< Number; i++)
Joriy = Joriy->Keyingi;
while (ptr->Keyingi!= Joriy)
ptr = ptr->Keyingi;
// elementni to'g'ridan-to'g'ri olib tashlash
ptr->Keyingi = Joriy->Keyingi;
agar (Bosh = Joriy) Bosh = Hozirgi->Keyingi;
o'chirish (joriy);
o'chirish (joriy);
//dumaloq bir tomonlama ro'yxatdagi elementni qidiring
bool Find_Item_Circle_Single_List(Circle_Single_list* boshi,
Circle_Single_List *ptr = Head;
//yordamchi ko'rsatgich
agar (DataItem == ptr->Data) rost qaytarsa;
else ptr = ptr->Keyingi;
while (ptr != Head);
//dumaloq bir yo'nalishli ro'yxatning bo'shligini tekshiring
bool Empty_Circle_Single_List(Circle_Single_list* Head)(
//doiraviy bir tomonlama ro'yxatni olib tashlash
bekor qilish_aylana_yagona_roʻyxatini oʻchirish(aylana_yagona_roʻyxat* boshi)(
agar (Bosh != NULL)(
Bosh = O'chirish_Item_Circle_Single_List(Bosh, 1);
Doira_yagona_ro'yxatini o'chirish (bosh);
Dumaloq dumaloq ro'yxat chiziqli ikkilangan roʻyxatga oʻxshaydi, lekin har bir element ikkita koʻrsatkichga ega boʻlib, biri roʻyxatdagi keyingi elementga, ikkinchisi esa oldingi elementga ishora qiladi (2-rasm).
2-rasm. Dumaloq dumaloq ro'yxat
Ikki tomonlama dumaloq ro'yxat bilan bajariladigan asosiy operatsiyalar:
· ro'yxat tuzish;
· ro‘yxatni chop etish (ko‘rish);
· elementni ro‘yxatga kiritish;
· elementni ro‘yxatdan olib tashlash;
· ro'yxatdagi elementni qidirish
· ro'yxat bo'sh yoki yo'qligini tekshirish;
· ro'yxatni o'chirish.
Ushbu asosiy operatsiyalar uchun algoritmlarni tavsiflash uchun biz chiziqli ikki yo'nalishli ro'yxat bilan bir xil deklaratsiyalardan foydalanamiz.
Keling, tsiklik ikki yo'nalishli ro'yxat bilan ishlashda sanab o'tilgan asosiy operatsiyalarning funktsiyalarini keltiramiz.
// dumaloq dumaloq ro'yxat yarating
Circle_Double_List* Circle_Double_List (int n,
Circle_Double_List** Bosh, Circle_Double_List* Loop)(
Circle_Double_List* ptr;//yordamchi ko'rsatgich
(*Bosh) = yangi Circle_Double_List();
//yangi element uchun xotira ajratish
if (Loop == NULL) Loop = (*Head);
cout<< "Введите значение ";
cin >> (*Bosh)->Ma'lumotlar;
//ma'lumot maydonining qiymatini kiriting
(*Bosh)->Keyingi=NULL;//manzil maydonini nolga solish
ptr = Doira_Double_Ro'yxat (n-1,&((*Bosh)->Keyingi), Loop);
agar ((*Bosh)->Keyingi!= NULL)
(*Bosh)->Keyingi->Avval = (*Bosh);
agar ((*Bosh)->Avval == NULL)
(*Bosh)->Prior = ptr;
agar (ptr == NULL)
Aks holda ptrni qaytaring;
// dumaloq dumaloq ro'yxatni chop eting
void Chop etish_aylana_ikkita_roʻyxati(doira_ikkita_roʻyxat* boshi) (
Circle_Double_List* ptr=Bosh;
//yordamchi ko'rsatgich
cout<< ptr->Ma'lumotlar<< "\t";
ptr=ptr->Keyingi;
) while (ptr!=Head);
cout<< "\n";
/*aylanma ikki yo‘nalishli ro‘yxatga berilgan sondan keyin element qo‘shing*/
Circle_Double_List* Doira_Double_Ro'yxatni qo'shing
(Circle_Double_List* Bosh, int raqami, int DataItem)(
//birinchi element ustida turing
Circle_Double_List *NewItem = new(Circle_Double_List);
// yangi element yaratildi
NewItem->Data = DataItem;
if (Head == NULL) (//roʻyxat boʻsh
NewItem->Keyingi = NewItem;
NewItem->Prior = NewItem;
else (//roʻyxat boʻsh emas
uchun (int i = 1; i< Number; i++)
Joriy = Joriy->Keyingi;
NewItem->Keyingi = Current->Keyingi;
Current->Keyingi = NewItem;
NewItem->Prior = Joriy;
NewItem->Keyingi->Prior = NewItem;
/*aylanali ikki yo‘nalishli ro‘yxatdan berilgan raqamga ega elementni olib tashlash*/
Circle_Double_List* Ob'ektni_o'chirish Circle_Double_list(Circle_Double_List* boshi,
agar (Bosh != NULL)(
Circle_Double_List *Joriy = Bosh;
agar (Bosh->Keyingi!= Bosh)(
uchun (int i = 1; i< Number; i++)
Joriy = Joriy->Keyingi;
Circle_Double_List *ptr = Current->Keyingi;
Joriy->Avval->Keyingi = Hozirgi->Keyingi;
Joriy->Keyingi->Avval = Hozirgi->Avvalgi;
agar (Bosh = joriy) // birinchisini o'chiring
Bosh = Joriy->Keyingi;
o'chirish (joriy);
o'chirish (joriy);
//dumaloq ikki yo'nalishli ro'yxatdagi elementni qidiring
bool Find_Item_Circle_Double_List(Circle_Double_List* boshi,
Circle_Double_List *ptr = Head;
//yordamchi ko'rsatgich
agar (DataItem == ptr->Ma'lumotlar)
else ptr = ptr->Keyingi;
while (ptr != Head);
// dumaloq dumaloq ro'yxat bo'sh yoki yo'qligini tekshiring
bool Empty_Circle_Double_List(Circle_Double_List* Head)(
qaytish (Head != NULL ? false: true);
// dumaloq dumaloq ro'yxatni olib tashlash
bekor qilish_aylana_ikkita_roʻyxatini oʻchirish(doira_ikkita_roʻyxat* boshi)(
agar (Bosh != NULL)(
Bosh = O'chirish_Item_Circle_Double_List(Bosh, 1);
Circle_Double_Ro'yxatni o'chirish (bosh);